I want make RESTful services using embedded jetty with JAX-RS (either resteasy or jersey).
I am trying to create with maven/eclipse setup.
if I try to follow http://wikis.sun.com/pages/viewpage.action?pageId=21725365 link I am not able to resolve error from ServletHolder sh = new ServletHolder(ServletContainer.class);
public class Main {
#Path("/")
public static class TestResource {
#GET
public String get() {
return "GET";
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws Exception {
ServletHolder sh = new ServletHolder(ServletContainer.class);
/*
* For 0.8 and later the "com.sun.ws.rest" namespace has been renamed to
* "com.sun.jersey". For 0.7 or early use the commented out code instead
*/
// sh.setInitParameter("com.sun.ws.rest.config.property.resourceConfigClass",
// "com.sun.ws.rest.api.core.PackagesResourceConfig");
// sh.setInitParameter("com.sun.ws.rest.config.property.packages",
// "jetty");
sh.setInitParameter("com.sun.jersey.config.property.resourceConfigClass",
"com.sun.jersey.api.core.PackagesResourceConfig");
sh.setInitParameter("com.sun.jersey.config.property.packages",
"edu.mit.senseable.livesingapore.platform.restws");
// sh.setInitParameter("com.sun.jersey.config.property.packages",
// "jetty");
Server server = new Server(9999);
ServletContextHandler context = new ServletContextHandler(server, "/",
ServletContextHandler.SESSIONS);
context.addServlet(sh, "/*");
server.start();
server.join();
// Client c = Client.create();
// WebResource r = c.resource("http://localhost:9999/");
// System.out.println(r.get(String.class));
//
// server.stop();
}
}
even this is not working.
can anyone suggest me something/tutorial/example ?
huh, linked page is ancient - last update 3 years ago.
Do you really need jetty? Jersey has excellent thoroughly tested integration with Grizzly (see http://grizzly.java.net) which is also acting as Glassfish transport layer and it is possible to use it as in your example.
See helloworld sample from Jersey workspace, com.sun.jersey.samples.helloworld.Main class starts Grizzly and "deploys" helloworld app: http://repo1.maven.org/maven2/com/sun/jersey/samples/helloworld/1.9.1/helloworld-1.9.1-project.zip .
If you really need jetty based sample, I guess I should be able to provide it (feel free to contact me).
EDIT:
ok, if you really want jetty, you can have it :) and looks like its fairly simple. I followed instructions from http://docs.codehaus.org/display/JETTY/Embedding+Jetty and was able to start helloworld sample:
public static void main(String[] args) throws Exception {
Server server = new Server(8080);
Context root = new Context(server,"/",Context.SESSIONS);
root.addServlet(new ServletHolder(new ServletContainer(new PackagesResourceConfig("com.sun.jersey.samples.helloworld"))), "/");
server.start();
}
http://localhost:8080/helloworld is accessible. I used Jetty 6.1.16. Hope it helps!
You can find more information about configuring Jersey in servlet environment in user guide, see http://jersey.java.net/nonav/documentation/latest/
EDIT:
dependencies.. but this is kind of hard to specify, it changed recently in jersey.. so..
pre 1.10:
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<version>6.1.16</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
</dependency>
post 1.10:
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<version>6.1.16</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
and you need this maven repo for jetty:
<repositories>
<repository>
<id>codehaus-release-repo</id>
<name>Codehaus Release Repo</name>
<url>http://repository.codehaus.org</url>
</repository>
</repositories>
Here's a github repo with a Maven based HelloWorld sample configured for Grizzly on master branch and for Jetty on "jetty" branch:
https://github.com/jesperfj/jax-rs-heroku
Despite the repo name it's not Heroku specific. Start the server by running the command specified in Procfile, e.g.
$ java -cp "target/dependency/*":target/classes Main
Embedded jetty with reaseasy without web.xml
java code:
final QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMinThreads(2); // 10
threadPool.setMaxThreads(8); // 200
threadPool.setDetailedDump(false);
threadPool.setName(SERVER_THREAD_POOL);
threadPool.setDaemon(true);
final SelectChannelConnector connector = new SelectChannelConnector();
connector.setHost(HOST);
connector.setAcceptors(2);
connector.setPort(PROXY_SEVLET_PORT);
connector.setMaxIdleTime(MAX_IDLE_TIME);
connector.setStatsOn(false);
connector.setLowResourcesConnections(LOW_RESOURCES_CONNECTIONS);
connector.setLowResourcesMaxIdleTime(LOW_RESOURCES_MAX_IDLE_TIME);
connector.setName(HTTP_CONNECTOR_NAME);
/* Setup ServletContextHandler */
final ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
contextHandler.setContextPath("/");
contextHandler.addEventListener(new ProxyContextListener());
contextHandler.setInitParameter("resteasy.servlet.mapping.prefix","/services");
final ServletHolder restEasyServletHolder = new ServletHolder(new HttpServletDispatcher());
restEasyServletHolder.setInitOrder(1);
/* Scan package for web services*/
restEasyServletHolder.setInitParameter("javax.ws.rs.Application","com.viacom.pl.cprox.MessageApplication");
contextHandler.addServlet(restEasyServletHolder, "/services/*");
final HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[] { contextHandler });
final Server server = new Server();
server.setThreadPool(threadPool);
server.setConnectors(new Connector[] { connector });
server.setHandler(handlers);
server.setStopAtShutdown(true);
server.setSendServerVersion(true);
server.setSendDateHeader(true);
server.setGracefulShutdown(1000);
server.setDumpAfterStart(false);
server.setDumpBeforeStop(false);
server.start();
server.join();
Web services detector:
package com.viacom.pl.cprox;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.viacom.pl.cprox.services.impl.AbstractWebServiceMethod;
public class MessageApplication extends Application {
private static final Logger LOGGER = LoggerFactory.getLogger(MessageApplication.class);
private Set<Object> singletons = new HashSet<Object>();
#SuppressWarnings("rawtypes")
public MessageApplication() {
/* Setup RestEasy */
Reflections reflections = new Reflections("com.viacom.pl.cprox.services.impl");
/*All my web services methods wrapper class extends AbstractWebServiceMethod, so it is easy to get sub set of expected result.*/
Set<Class<? extends AbstractWebServiceMethod>> set = reflections
.getSubTypesOf(AbstractWebServiceMethod.class);
for (Class<? extends AbstractWebServiceMethod> clazz : set) {
try {
singletons.add(clazz.newInstance());
} catch (InstantiationException e) {
LOGGER.error(e.getMessage(), e);
} catch (IllegalAccessException e) {
LOGGER.error(e.getMessage(), e);
}
}
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
}
pom.xml
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
<version>2.2.0.GA</version>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.9-RC1</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.0.3.Final</version>
</dependency>
I was able to get this maven archetype up and running in half an hour.
See https://github.com/cb372/jersey-jetty-guice-archetype
Steps:
git clone https://github.com/cb372/jersey-jetty-guice-archetype.git
mvn install
mvn archetype:generate -DarchetypeGroupId=org.birchall \
-DarchetypeArtifactId=jersey-jetty-guice-archetype -DarchetypeVersion=1.0
mvn compile exec:java -Dexec.mainClass=com.yourpackage.Main
Huge thanks to cb372 for creating this archetype. It makes it so easy.
Related
we have a connector on port 7777 and we want to reject any requests that are coming for /serverStatus on that connector?
at the same time I want to accept only /serverStatus requests on a different connector which is on port 80.
Name your ServerConnectors.
The ServerConnector on port 7777 is named "admin"
The ServerConnector on port 80 is named "normal"
Then setup the webapp for /serverStatus to have a virtualhost of #admin, and your root webapp on a virtualhost of #normal.
See Embedded-Jetty Cookbook: ConnectorSpecificContexts.java for example.
package org.eclipse.jetty.cookbook;
import org.eclipse.jetty.cookbook.handlers.HelloHandler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
public class ConnectorSpecificContexts
{
public static void main(String[] args) throws Exception
{
Server server = new Server();
ServerConnector connectorA = new ServerConnector(server);
connectorA.setPort(8080);
connectorA.setName("connA");
ServerConnector connectorB = new ServerConnector(server);
connectorB.setPort(9090);
connectorB.setName("connB");
server.addConnector(connectorA);
server.addConnector(connectorB);
// Collection of Contexts
ContextHandlerCollection contexts = new ContextHandlerCollection();
server.setHandler(contexts);
// Hello Handler (connection A)
ContextHandler ctxHelloA = new ContextHandler();
ctxHelloA.setContextPath("/");
ctxHelloA.setHandler(new HelloHandler("Hello Connection A"));
ctxHelloA.setVirtualHosts(new String[] { "#connA" });
contexts.addHandler(ctxHelloA);
// Hello Handler (connection B)
ContextHandler ctxHelloB = new ContextHandler();
ctxHelloB.setContextPath("/");
ctxHelloB.setHandler(new HelloHandler("Greetings from Connection B"));
ctxHelloB.setVirtualHosts(new String[] { "#connB" });
contexts.addHandler(ctxHelloB);
server.start();
server.join();
}
}
I am trying to configure my WSO2 Identity Server to set up service providers via a .xml file. Here are the steps I am taking:
Paste the service provider .xml file into the $WSO2_HOME/repository/conf/identity/service-providers folder
Run the wso2server.sh script in a fresh WSO2 environment (never setup, databases with empty tables)
The .xml file I created in step 1 was created using the "export" feature from the console, so I am pretty confident it is set up correctly. Just in case, this is the code (lines with "REMOVED" were removed for privacy):
<?xml version="1.0" encoding="UTF-8"?><ServiceProvider>
<ApplicationName>__REMOVED__</ApplicationName>
<Description>__REMOVED__</Description>
<InboundAuthenticationConfig>
<InboundAuthenticationRequestConfigs>
<InboundAuthenticationRequestConfig>
<InboundAuthKey>__REMOVED__</InboundAuthKey>
<InboundAuthType>passivests</InboundAuthType>
<InboundConfigType>standardAPP</InboundConfigType>
<Properties/>
</InboundAuthenticationRequestConfig>
<InboundAuthenticationRequestConfig>
<InboundAuthKey>__REMOVED__</InboundAuthKey>
<InboundAuthType>openid</InboundAuthType>
<InboundConfigType>standardAPP</InboundConfigType>
<Properties/>
</InboundAuthenticationRequestConfig>
<InboundAuthenticationRequestConfig>
<InboundAuthKey>__REMOVED__</InboundAuthKey>
<InboundAuthType>oauth2</InboundAuthType>
<InboundConfigType>standardAPP</InboundConfigType>
<inboundConfiguration><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<oAuthAppDO>
<oauthConsumerKey>__REMOVED__</oauthConsumerKey>
<oauthConsumerSecret>__REMOVED__</oauthConsumerSecret>
<applicationName>__REMOVED__</applicationName>
<callbackUrl></callbackUrl>
<oauthVersion>OAuth-2.0</oauthVersion>
<grantTypes>client_credentials </grantTypes>
<scopeValidators/>
<pkceSupportPlain>true</pkceSupportPlain>
<pkceMandatory>false</pkceMandatory>
<userAccessTokenExpiryTime>3600</userAccessTokenExpiryTime>
<applicationAccessTokenExpiryTime>3600</applicationAccessTokenExpiryTime>
<refreshTokenExpiryTime>84600</refreshTokenExpiryTime>
<idTokenExpiryTime>3600</idTokenExpiryTime>
<audiences/>
<bypassClientCredentials>false</bypassClientCredentials>
<requestObjectSignatureValidationEnabled>false</requestObjectSignatureValidationEnabled>
<idTokenEncryptionEnabled>false</idTokenEncryptionEnabled>
<idTokenEncryptionAlgorithm>null</idTokenEncryptionAlgorithm>
<idTokenEncryptionMethod>null</idTokenEncryptionMethod>
<backChannelLogoutUrl></backChannelLogoutUrl>
<tokenType>JWT</tokenType>
</oAuthAppDO>
]]></inboundConfiguration>
<Properties/>
</InboundAuthenticationRequestConfig>
</InboundAuthenticationRequestConfigs>
</InboundAuthenticationConfig>
<LocalAndOutBoundAuthenticationConfig>
<AuthenticationSteps/>
<AuthenticationType>default</AuthenticationType>
<alwaysSendBackAuthenticatedListOfIdPs>false</alwaysSendBackAuthenticatedListOfIdPs>
<UseTenantDomainInUsername>false</UseTenantDomainInUsername>
<UseUserstoreDomainInRoles>true</UseUserstoreDomainInRoles>
<UseUserstoreDomainInUsername>false</UseUserstoreDomainInUsername>
<EnableAuthorization>false</EnableAuthorization>
</LocalAndOutBoundAuthenticationConfig>
<RequestPathAuthenticatorConfigs/>
<InboundProvisioningConfig>
<ProvisioningUserStore/>
<IsProvisioningEnabled>false</IsProvisioningEnabled>
<IsDumbModeEnabled>false</IsDumbModeEnabled>
</InboundProvisioningConfig>
<OutboundProvisioningConfig>
<ProvisioningIdentityProviders/>
</OutboundProvisioningConfig>
<ClaimConfig>
<RoleClaimURI/>
<LocalClaimDialect>false</LocalClaimDialect>
<IdpClaim/>
<ClaimMappings>
<ClaimMapping>
<LocalClaim>
<ClaimUri>http://wso2.org/claims/role</ClaimUri>
<claimId>0</claimId>
</LocalClaim>
<RemoteClaim>
<ClaimUri>roles</ClaimUri>
<claimId>0</claimId>
</RemoteClaim>
<RequestClaim>true</RequestClaim>
<MandatoryClaim>false</MandatoryClaim>
</ClaimMapping>
</ClaimMappings>
<AlwaysSendMappedLocalSubjectId>false</AlwaysSendMappedLocalSubjectId>
<SPClaimDialects/>
</ClaimConfig>
<PermissionAndRoleConfig>
<Permissions/>
<RoleMappings/>
<IdpRoles/>
</PermissionAndRoleConfig>
<IsSaaSApp>false</IsSaaSApp>
</ServiceProvider>
After the startup script completes, I don't see the service provider in the console:
Something strange I noticed - If I try to import the service provider manually using the console, I get an error on the UI reading:
Error in importing provided service provider serviceprovider#carbon.super from file
My console output says:
Caused by: org.wso2.carbon.identity.application.common.IdentityApplicationManagementException: Application with the same name loaded from the file system.
at org.wso2.carbon.identity.application.mgt.ApplicationManagementServiceImpl.doAddApplication(ApplicationManagementServiceImpl.java:1637)
at org.wso2.carbon.identity.application.mgt.ApplicationManagementServiceImpl.createApplicationWithTemplate(ApplicationManagementServiceImpl.java:169)
at org.wso2.carbon.identity.application.mgt.ApplicationManagementServiceImpl.importSPApplicationFromObject(ApplicationManagementServiceImpl.java:1025)
... 80 more
I found the source code this error is from and it is the ApplicationManagementServiceImpl.java file
if (ApplicationManagementServiceComponent.getFileBasedSPs().containsKey(applicationName)) {
throw new IdentityApplicationManagementException(
"Application with the same name loaded from the file system.");
}
which makes a call to ApplicationManagementServiceComponent.java.
private void buildFileBasedSPList() {
String spConfigDirPath = CarbonUtils.getCarbonConfigDirPath() + File.separator + "identity"
+ File.separator + "service-providers";
FileInputStream fileInputStream = null;
File spConfigDir = new File(spConfigDirPath);
OMElement documentElement;
if (spConfigDir.exists()) {
for (final File fileEntry : spConfigDir.listFiles()) {
try {
if (!fileEntry.isDirectory()) {
fileInputStream = new FileInputStream(new File(fileEntry.getAbsolutePath()));
documentElement = new StAXOMBuilder(fileInputStream).getDocumentElement();
ServiceProvider sp = ServiceProvider.build(documentElement);
if (sp != null) {
fileBasedSPs.put(sp.getApplicationName(), sp);
}
}
} catch (Exception e) {
log.error("Error while loading idp from file system.", e);
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
log.error("Error occurred while closing file input stream for file " + spConfigDirPath, e);
}
}
The error is thrown because my service provider directory has a file with the same service provider name that is trying to be imported through the console. However, the service provider in my file system wasn't imported in the first place.
So my failure to import the service provider when the server gets configured prevents me from importing the files through the console later.
Any help is appreciated.
The service providers deployed as the file $WSO2_HOME/repository/conf/identity/service-providers folder will not be visible in the UI. But it will be active in the system. Currently the InboundAuthenticationConfig in the deployed file is not supported. But, you can have the SAML configurations in the $WSO2_HOME/repository/conf/identity/sso-idp-config.xml file.
<SSOIdentityProviderConfig>
<ServiceProviders>
.......
.......
<ServiceProvider>
<Issuer>_InboundAuthKey_</Issuer>
<AssertionConsumerServiceURLs>
<AssertionConsumerServiceURL>_url_</AssertionConsumerServiceURL>
</AssertionConsumerServiceURLs>
......
......
</ServiceProvider>
</ServiceProviders>
</SSOIdentityProviderConfig>
Here the InboundAuthKey is the value of for saml InboundAuthenticationRequestConfig
I've failed to setup service provider by storing file to $WSO2_HOME/repository/conf/identity/service-providers. OAuth2/token request always fails with error that the particular client_id is not found.
What works for me is to create python script to load XML using SOAP interface.
import zeep
from requests import Session
import os
session = Session()
#uncomment in case you use HTTPS without valid certificates
session.verify = False
transport = zeep.Transport(session=session)
def get_client(service):
base_url = 'https://{IS_SERVICE_NAME}:{IS_PORT}/services/{SERVICE}?wsdl'.format(
IS_SERVICE_NAME=os.environ["IS_SERVICE_NAME"],
IS_PORT=os.environ["IS_PORT"],
SERVICE=service)
print("Getting client %s" % base_url)
return zeep.Client(base_url, transport=transport)
def init_session():
client = get_client('AuthenticationAdmin')
client.service.login(username=os.environ["IS_USERNAME"],
password=os.environ["IS_PASSWORD"],
remoteAddress=os.environ["IS_SERVICE_NAME"])
def import_config(path):
print("Calling IdentityApplicationManagementService")
client_iam = get_client('IdentityApplicationManagementService')
with open(path) as f:
contents = f.read()
# list of available namespaces
# print client_iam.client_iam.namespaces
sp_file_content_type = client_iam.get_type('ns2:SpFileContent')
sp_file_content = sp_file_content_type(content=contents,
fileName='service-provider.xml')
client_iam.service.importApplication(sp_file_content)
if __name__ == '__main__':
assert "IS_USERNAME" in os.environ, "Define IS_USERNAME env variable"
assert "IS_PASSWORD" in os.environ, "Define IS_PASSWORD env variable"
assert "IS_SERVICE_NAME" in os.environ, "Define IS_SERVICE_NAME env variable"
assert "IS_PORT" in os.environ, "Define IS_PORT env variable"
init_session()
import_config('/conf/service-provider.xml')
This SOAP interface is enabled by setting in carbon.xml.
<HideAdminServiceWSDLs>false</HideAdminServiceWSDLs>
I am getting the following exception when I run my build in jenkins.
Here is what I did
I created java files from running the following command
wsimport -keep -verbose http://foobar.com/ws/server?wsdl
I copied the files created to my project and used it to construct the client stubs
Here is how my client looks
public class SoapClient {
private ServiceSoap soapService;
//30 secs
private static final Integer REQUEST_TIMEOUT_MILLI = 90000;
//15 secs
private static final Integer CONNECT_TIMEOUT_MILLI = 90000;
public SoapClient(){
Service service = new Service();
service.setHandlerResolver(new JaxWsHandlerResolver());
soapService = service.getServiceSoap();
((BindingProvider)soapService).getRequestContext()
.put(BindingProviderProperties.REQUEST_TIMEOUT,REQUEST_TIMEOUT_MILLI);
((BindingProvider)soapService).getRequestContext()
.put(BindingProviderProperties.CONNECT_TIMEOUT,CONNECT_TIMEOUT_MILLI);
}
public SoapResponse processRequest(String refNum){
SoapResponse response = null;
try {
response = soapService.requestInfo(refNum);
}
catch (Exception ex){
LOG.error("error connecting to Soap service, {}",ex.getLocalizedMessage());
LOG.error(ex.getMessage());
LOG.error(ex.getCause().toString());
ex.printStackTrace();
}
return response;
}
}
I have set connection and request timeouts above. I have increased upto 10 minutes. till I see the same exception. I have included the jaxws-rt dependency in my pom.xml
Here it is
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<jaxws.version>2.2.10</jaxws.version>
</dependency>
Here is the exception I am seeing
2016-05-05 04:43:40,337 [main] ERROR foo.bar.foobar.client.SoapClient - java.net.SocketTimeoutException: Read timed out
javax.xml.ws.WebServiceException: java.net.SocketTimeoutException: Read timed out
at com.sun.xml.ws.transport.http.client.HttpClientTransport.readResponseCodeAndMessage(HttpClientTransport.java:210)
at com.sun.xml.ws.transport.http.client.HttpTransportPipe.createResponsePacket(HttpTransportPipe.java:241)
at com.sun.xml.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:232)
at com.sun.xml.ws.transport.http.client.HttpTransportPipe.processRequest(HttpTransportPipe.java:145)
at com.sun.xml.ws.transport.DeferredTransportPipe.processRequest(DeferredTransportPipe.java:110)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:1136)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:1050)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:1019)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:877)
at com.sun.xml.ws.client.Stub.process(Stub.java:463)
at com.sun.xml.ws.client.sei.SEIStub.doProcess(SEIStub.java:191)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:108)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:92)
at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:161)
at com.sun.proxy.$Proxy50.requestInfo(Unknown Source)
at
The exception seems to be sun related. I have read other posts. but none helped me actually. I am stuck here for two days and any help here would be much appreciated.
Thanks
EDIT
I pretty much see same issue as here. but no solution has been posted
I am trying to start the https port 443 as root then downgrade to non-root user using embedded jetty. I gone through the
https://www.eclipse.org/jetty/documentation/current/setting-port80-access.html#configuring-jetty-setuid-feature
but didn't get any solution how to do it from java program.
This is the embedded jetty code :
package com.jetty.startup;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.annotations.ServletContainerInitializersStarter;
import org.eclipse.jetty.apache.jsp.JettyJasperInitializer;
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.apache.log4j.Logger;
import org.eclipse.jetty.setuid.*;
/**
* Handles Webapp server's serviice
*
*
*/
class MyServer {
private static Logger logger = Logger.getLogger(MyServer.class);
private static Server server;
private String jettyHome;
/**
* Creates an instance of {#link MyServer}
*
* #param jettyHome
* jetty home path
*/
public MyServer(String jettyHome) {
this.jettyHome = jettyHome;
}
/**
* Initializes Webapp server:
*
*/
public Server init() throws Exception {
server = new Server();
int httpsPort = 443;
String keyStoreFile = "/home/jetty/webserver/etc/keystore";
String keyStorePassword = "secret";
String keyManagerPassword = "secret";
String trustStorePassword = "secret";
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath(keyStoreFile);
sslContextFactory.setKeyStoreType("JKS");
sslContextFactory.setKeyStorePassword(keyStorePassword);
sslContextFactory.setKeyManagerPassword(keyManagerPassword);
SetUIDListener set = new SetUIDListener();
set.setStartServerAsPrivileged(true);
set.setUsername("jetty");
set.setGroupname("jetty");
set.setUmask(002);
server.addLifeCycleListener(set);
HttpConfiguration httpConfiguration = new HttpConfiguration();
httpConfiguration.setSecurePort(httpsPort);
httpConfiguration.setSecureScheme("https");
httpConfiguration.addCustomizer(new SecureRequestCustomizer());
ServerConnector serverConnector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory, "http/1.1"),
new HttpConnectionFactory(httpConfiguration));
serverConnector.setPort(httpsPort);
server.setConnectors(new Connector[] { serverConnector });
WebAppContext myContext = new WebAppContext();
myContext.setContextPath("/myapp");
myContext.setWar(jettyHome + "/webapps/myapp/");
myContext.setDefaultsDescriptor(jettyHome + "/etc/webdefault.xml");
File overrideFile = new File(jettyHome
+ "/webapps/myapp/WEB-INF/generated-web.xml");
if (overrideFile.exists()) {
myContext.setOverrideDescriptor(jettyHome
+ "/webapps/myapp/WEB-INF/generated-web.xml");
}
server.setHandler(myContext);
JettyJasperInitializer sci = new JettyJasperInitializer();
ServletContainerInitializersStarter sciStarter =
new ServletContainerInitializersStarter(myContext);
ContainerInitializer initializer = new ContainerInitializer(sci, null);
List<ContainerInitializer> initializers = new ArrayList<>();
initializers.add(initializer);
myContext.setAttribute("org.eclipse.jetty.containerInitializers", initializers);
myContext.addBean(sciStarter, true);
ContextHandlerCollection contexts = new ContextHandlerCollection();
contexts.setHandlers(new Handler[] { myContext });
server.setHandler(contexts);
return server;
}
public static void main(String args[]) {
String jetty_home = "/home/jetty/webServer";
MyServer myServer = new MyServer(jetty_home);
try {
server = myServer.init();
server.start();
} catch (Exception excp) {
}
}
}
As for the libsetuid-linux.so I've already created the native version of it using mvn clean install from the jetty-setuid project.
If httpsPort = 2400 then this is the log file details:
Log
2016-02-11 15:36:16.413:INFO::main: Logging initialized #2424ms
2016-02-11 15:36:16.593:INFO:oejs.SetUIDListener:main: Setting umask=02
2016-02-11 15:36:16.603:INFO:oejs.SetUIDListener:main: Opened ServerConnector#b96fde{SSL,[ssl, http/1.1]}{0.0.0.0:2400}
2016-02-11 15:36:16.603:INFO:oejs.SetUIDListener:main: Setting GID=504
2016-02-11 15:36:16.676:INFO:oejs.SetUIDListener:main: Setting UID=504
2016-02-11 15:36:16.680:INFO:oejs.Server:main: jetty-9.3.7.v20160115
whereas when httpsPort = 443 this is how the log file looks:
Log
2016-02-11 15:37:35.049:INFO::main: Logging initialized #2199ms
2016-02-11 15:37:35.228:INFO:oejs.SetUIDListener:main: Setting umask=02
Nothing happens after this on the log and also the webapp isn't working.
This is ultimately a OS permissions issue, and you'll need a way to work around that.
This means any solution you come up with will also be OS specific
One example is to use the jetty-setuid-java artifact, and appropriate jetty-setuid-native library to accomplish this.
Make sure you fully understand how setuid functions on your desired OS before starting this effort
As for enabling the jetty setuid specific pieces, you can either use the XmlConfiguration to inject the appropriate lifecycle listener into your Server, or you can do it entirely in code.
See the Jetty Distribution's etc/jetty-setuid.xml for help.
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN"
"http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ================================================================ -->
<!-- Configure the Jetty SetUIDListener -->
<!-- ================================================================ -->
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<Call name="addLifeCycleListener">
<Arg>
<New class="org.eclipse.jetty.setuid.SetUIDListener">
<Set name="startServerAsPrivileged">false</Set>
<Set name="umaskOctal">002</Set>
<Set name="username">jetty</Set>
<Set name="groupname">jetty</Set>
<!-- uncomment to change the limits on number of open file descriptors for root -->
<!--
<Call name="setRLimitNoFiles">
<Arg>
<New class="org.eclipse.jetty.setuid.RLimit">
<Set name="soft">20000</Set>
<Set name="hard">40000</Set>
</New>
</Arg>
</Call>
-->
</New>
</Arg>
</Call>
</Configure>
Well finally I was able to achieve what I'd asked in the above question by creating a libsetuid-linux.so for 32-bit, the one that's supplied with jetty-9.3.7 is for 64-bit.
How I created the 32-bit libsetuid-linux.so?
This link helped http://www.eclipse.org/jetty/documentation/current/setting-port80-access.html
Point number 5 to be precise
But unfortunately the link for jetty-setuid project isn't working anymore.
Also, the sudo had to be done with sudo -E.
I am new to CXF web services. I need to write a Rest Client. I am getting
java.lang.NoClassDefFoundError: org/apache/cxf/jaxrs/client/WebClient
com.test.ws.CXFWebServiceConnector.get(CXFWebServiceConnector.java:21)
com.test.ws.SimpleServlet.doGet(SimpleServlet.java:29)
javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
root cause
java.lang.ClassNotFoundException: org.apache.cxf.jaxrs.client.WebClient
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1720)
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571)
com.test.ws.CXFWebServiceConnector.get(CXFWebServiceConnector.java:21)
com.test.ws.SimpleServlet.doGet(SimpleServlet.java:29)
javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
This is not a maven project. Below jars are added in my class path. To get the NoClassDefinition Exception am I missing any other library ?
abdera-core-0.4.0-incubating.jar
abdera-extensions-main-0.4.0-incubating.jar
abdera-i18n-0.4.0-incubating.jar
abdera-parser-0.4.0-incubating.jar
axiom-api-1.2.7.jar
axiom-impl-1.2.7.jar
cxf-2.2.6.jar
geronimo-activation-1.1.jar
geronimo-annotation-1.0.jar
jaxb-api-2.1.jar
jaxb-impl-2.1.12.jar
jra-1.0-alpha-4.jar
jsr311-api-1.0.jar
neethi-2.0.4.jar
wss4j-1.5.8.jar
wstx-asl-3.2.9.jar
xml-resolver-1.2.jar
XmlSchema-1.4.5.jar
This is the way I access the Restful web service
public String get(String url) {
String response = null;
WebClient client = WebClient.create(url);
client.accept(MediaType.APPLICATION_JSON);
HTTPConduit conduit = WebClient.getConfig(client).getHttpConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setAllowChunking(false);
conduit.setClient(httpClientPolicy);
TLSClientParameters clientParameters = new TLSClientParameters();
clientParameters.setDisableCNCheck(true);
clientParameters.setSecureSocketProtocol("TLS");
conduit.setTlsClientParameters(clientParameters);
try {
response = client.get(String.class);
} finally {
if (client != null) {
client.reset();
}
}
return response;
}
WebClient is part of cxf-rt-frontend-jaxrs.jar. You do not have cxf JAXRS related jars I guess.
Use the below command in your project root to detect which dependencies are required:
mvn dependency:tree -Dincludes=org.apache.cxf