Jersey on Jetty on Android throws ContainerExcepti

2019-06-25 13:40发布

问题:

I'm trying to run Jersey on Jetty on Android.

I've created an Android that instantiate a Jetty Server with a Jersey Servlet. Anyway when I start Jetty and visit a REST resource (in my case: http://192.168.1.12:8080/api/hello) I get a ContainerException with message: No WebApplication provider is present (see exception stack trace below).

Any idea why?

I've added javax package JNDI to the project since it was required by either Jetty or Jersey. Android doesn't like imporitng javax libraries so I'm temporarily using the --core-library command line parameter to compile the dex files anyway.

EXCEPTION trace:

com.sun.jersey.api.container.ContainerException: No WebApplication provider is present
at com.sun.jersey.spi.container.WebApplicationFactory.createWebApplication(WebApplicationFactory.java:69)
at com.sun.jersey.spi.container.servlet.ServletContainer.create(ServletContainer.java:391)
at com.sun.jersey.spi.container.servlet.ServletContainer$InternalWebComponent.create(ServletContainer.java:306)
at com.sun.jersey.spi.container.servlet.WebComponent.load(WebComponent.java:605)
at com.sun.jersey.spi.container.servlet.WebComponent.init(WebComponent.java:208)
at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:373)
at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:556)
at javax.servlet.GenericServlet.init(GenericServlet.java:241)
at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:444)
at org.eclipse.jetty.servlet.ServletHolder.getServlet(ServletHolder.java:335)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:523)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:479)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:483)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:227)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1031)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:406)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:186)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:965)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111)
at org.eclipse.jetty.server.Server.handle(Server.java:349)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:449)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:910)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:647)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:233)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:76)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:615)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:45)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:599)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:534)
at java.lang.Thread.run(Thread.java:1019)

ACTIVITY CODE:

public class StartServerActivity extends Activity {

private Server webServer;
private final static String LOG_TAG = "Jetty";

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    System.setProperty("java.net.preferIPv4Stack", "true");
    System.setProperty("java.net.preferIPv6Addresses", "false");

    webServer = new Server(8080);

    ServletHolder servletHolder = new ServletHolder(ServletContainer.class);
    servletHolder.setInitParameter("com.sun.jersey.config.property.packages", "com.famenu.server.resources");
    servletHolder.setInitParameter("com.sun.jersey.config.property.resourceConfigClass", "com.sun.jersey.api.core.PackagesResourceConfig");
    ServletContextHandler servletContextHandler = new ServletContextHandler(webServer, "/api");
    servletContextHandler.addServlet(servletHolder, "/");


    webServer.setHandler(servletContextHandler);

    try {
        webServer.start();
        webServer.join();
        Log.d(LOG_TAG, "started Web server");

    }
    catch (Exception e) {
        Log.d(LOG_TAG, "unexpected exception starting Web server: " + e);
    }
}

}

I'm using Jetty 7.3.0.v20110203 , Jersey 1.12 , Android 1.6

回答1:

WebApplicationProviderImpl is registered through META-INF/services entry in jersey-server.jar. Any chance you are repackaging Jersey into your own jars and missed the META-INF/services entries?

So to solve this exception is necessary to add the META-INF/services folders from jersey-core jersey-server and jersey-servlet to the META-INF folder of the apk.

Then you won't be able to use Eclipse to deploy but the following command line will work:

cd PROJECT_DIRECTORY

ant debug

adb install -r "bin/YOUR_PROJECT-debug.apk"



回答2:

I had the same issue with Jetty 8 and Jersey 1.13. To solve this I added the following dependency.

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-servlet</artifactId>
    <version>1.13</version>
</dependency>