Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jetty+Jersey, unexpected exception: Asynchronous processing not supported on Servlet 2.x container

Tags:

java

maven

jersey

I'm developing a JAX-RS server where I need to provide answers to client asynchronously. I'm loading the Server programmatically. To my purposes, I'm using Jetty and the Jersey implementation. Here you have my relevant parts of code:

// file: EntryPoint.java

@Path("/explorer")
public class EntryPoint {

@GET
@Path("/{table}")
@Produces(MediaType.APPLICATION_JSON)
public void querySearch( @PathParam     ("table")   String          table, 
                         @QueryParam    ("source")  String          source, 
                         @QueryParam    ("from")    int             startTime, 
                         @QueryParam    ("until")   int             endTime,
                         @Suspended     final       AsyncResponse   asyncResponse) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            String result = veryExpensiveOperation();
            asyncResponse.resume(result);
        }

        private String veryExpensiveOperation() {
            return "{\"Source\":"+source+",\"Table\":\""+table+",\"StartTime\":\""+startTime+",\"EndTime\":\""+endTime+"\"}";
        }
    }).start();
}

// file: Service.java

private void startWS(String address, int port) throws Exception, InterruptedException {

    ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
    context.setContextPath("/");

    Server jettyServer = new Server();

    // HTTP connector
    ServerConnector http = new ServerConnector(jettyServer);
    http.setHost(address);
    http.setPort(port);

    jettyServer.addConnector(http);
    jettyServer.setHandler(context);

    ServletHolder jerseyServlet = context.addServlet(
         org.glassfish.jersey.servlet.ServletContainer.class, "/*");
    jerseyServlet.setInitOrder(0);

    // Tells the Jersey Servlet which REST service/class to load.
    jerseyServlet.setInitParameter(
       "jersey.config.server.provider.classnames",
       EntryPoint.class.getCanonicalName());

    try {
        jettyServer.start();
        jettyServer.join();
    } finally {
        jettyServer.destroy();
    }
}

// pom.xml (only relevant dependencies... I put the version in each dep)

    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-server</artifactId>
        <version>9.3.8.v20160314</version>
    </dependency>

    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-servlet</artifactId>
        <version>9.3.8.v20160314</version>
    </dependency>

    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-util</artifactId>
        <version>9.3.8.v20160314</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-server</artifactId>
        <version>2.22.2</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet-core</artifactId>
        <version>2.22.2</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-jetty-http</artifactId>
        <version>2.22.2</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-moxy</artifactId>
        <version>2.22.2</version>
    </dependency>

The server runs and goes up correctly, however, when I try to invoke my service I get the following exception:

12:39:22:497|3698-00048:WARN [org.eclipse.jetty.server.HttpChannel] - //pisa122:9090/explorer/cm_order?ource=BBG_BOND&from=20160410&until=20160418 Thread {qtp872786524-48}
javax.servlet.ServletException: java.lang.UnsupportedOperationException: Asynchronous processing not supported on Servlet 2.x container.
at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:489)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:845)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:583)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:224)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1160)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1092)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
at org.eclipse.jetty.server.Server.handle(Server.java:518)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:308)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:244)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceAndRun(ExecuteProduceConsume.java:246)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:156)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:654)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:572)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.UnsupportedOperationException: Asynchronous processing not supported on Servlet 2.x container.
at org.glassfish.jersey.servlet.WebComponent$3.suspend(WebComponent.java:138)
at org.glassfish.jersey.servlet.internal.ResponseWriter.suspend(ResponseWriter.java:125)
at org.glassfish.jersey.server.ServerRuntime$AsyncResponder.suspend(ServerRuntime.java:910)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:327)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102)
at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154)
at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473)
... 24 more

The very same request, when I return synchronously, works with no problems. I also checked in the maven Dependency Hierarchy and I do see the 3.1 version of the servlet-api (see screenshot). Any idea of what's wrong in my code/pom? I already checked the Register ServletContainer programatically in Osgi but that didn't help. Thanks all! :)

like image 439
Marco Solinas Avatar asked Dec 05 '22 01:12

Marco Solinas


1 Answers

You need the following for servlet 3.x support

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet</artifactId>
    <version>2.22.2</version>
</dependency>
like image 53
Paul Samsotha Avatar answered Dec 06 '22 18:12

Paul Samsotha