Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Asynchronous Callbacks in Jersey 2 in tomcat 7

How to use asynchronous callbacks of jersey 2 in tomcat server. I found some examples in Jersey manual : https://jersey.java.net/documentation/latest/user-guide.html#d0e8496.

But the issue occurs when I'm tring to test following code with this: https://jersey.java.net/documentation/latest/user-guide.html#d0e8615 code as mentioned on Jersey 2 Manual.

-------------------------------------------------------------------------------------------------------------------------------

As, manual version has been changed, I'm posting the codes over here:

This is my Service:

            import javax.ws.rs.GET; 
            import javax.ws.rs.Path; 
            import javax.ws.rs.Produces; 
            import javax.ws.rs.container.AsyncResponse; 
            import javax.ws.rs.container.CompletionCallback; 
            import javax.ws.rs.container.Suspended; 
            import javax.ws.rs.core.MediaType; 
            import javax.ws.rs.core.Response; 

            @Path("/resource") 
            public class AsyncResource { 
                private static int numberOfSuccessResponses = 0; 
                private static int numberOfFailures = 0; 
                private static Throwable lastException = null; 

                @GET 
                public void asyncGetWithTimeout(@Suspended final AsyncResponse asyncResponse) { 
                System.out.println("AsyncResource.asyncGetWithTimeout()"); 
                    asyncResponse.register(new CompletionCallback() { 
                        @Override 
                        public void onComplete(Throwable throwable) { 
                            if (throwable == null) { 
                                // no throwable - the processing ended successfully 
                                // (response already written to the client) 
                                numberOfSuccessResponses++; 
                            } else { 
                                numberOfFailures++; 
                                lastException = throwable; 
                            } 
                        } 
                    }); 

                    new Thread(new Runnable() { 
                        @Override 
                        public void run() { 
                            String result = veryExpensiveOperation(); 
                            asyncResponse.resume(result); 
                        } 

                        private String veryExpensiveOperation() { 
                            // ... very expensive operation 
                        return "Hi"; 
                        } 
                    }).start(); 
                } 
            }

This is client:

    ClientConfig clientConfig = new ClientConfig(); 
    Client client = ClientBuilder.newClient(clientConfig); 

    WebTarget webTarget = client.target("http://localhost:8080/Jersey2.5Service/rest"); 
    WebTarget target = webTarget.path("resource"); 

    final AsyncInvoker asyncInvoker = target 
                    .request().async(); 
    final Future<Response> responseFuture = asyncInvoker.get(); 
    System.out.println("Request is being processed asynchronously."); 
    final Response response = responseFuture.get(); 
            // get() waits for the response to be ready 
    System.out.println("Response received." +response.readEntity(String.class));

web.xml

<servlet>  
      <servlet-name>HelloServlet</servlet-name>  
        <servlet-class>  
         org.glassfish.jersey.servlet.ServletContainer  
       </servlet-class>  
       <init-param>  
         <param-name>jersey.config.server.provider.packages</param-name>  
         <param-value>main.java</param-value>  
       </init-param>  
       <load-on-startup>1</load-on-startup>  
     </servlet>  
     <servlet-mapping>  
       <servlet-name>HelloServlet</servlet-name>  
       <url-pattern>/rest/*</url-pattern>  
     </servlet-mapping>

These are the jars I'm using:

    asm-all-repackaged-2.2.0-b21.jar 
    cglib-2.2.0-b21.jar 
    guava-14.0.1.jar 
    hk2-api-2.2.0-b21.jar 
    hk2-locator-2.2.0-b21.jar 
    hk2-utils-2.2.0-b21.jar 
    javax.annotation-api-1.2.jar 
    javax.inject-2.2.0-b21.jar 
    javax.servlet-api-3.0.1.jar 
    javax.ws.rs-api-2.0.jar 
    jaxb-api-2.2.7.jar 
    jersey-client.jar 
    jersey-common.jar 
    jersey-container-servlet-core.jar 
    jersey-container-servlet.jar 
    jersey-server.jar 
    org.osgi.core-4.2.0.jar 
    osgi-resource-locator-1.0.1.jar 
    persistence-api-1.0.jar 
    servlet-api-3.0.jar 
    validation-api-1.1.0.Final.jar 

These errors are coming:

Jan 31, 2014 4:06:53 PM org.glassfish.jersey.servlet.internal.ResponseWriter suspend
WARNING: Attempt to put servlet request into asynchronous mode has failed. Please check your servlet configuration - all Servlet instances and Servlet filters involved in the request processing must explicitly declare support for asynchronous request processing.
java.lang.IllegalStateException: Not supported.
    at org.apache.catalina.connector.Request.startAsync(Request.java:1676)
    at org.apache.catalina.connector.RequestFacade.startAsync(RequestFacade.java:1031)
    at org.glassfish.jersey.servlet.async.AsyncContextDelegateProviderImpl$ExtensionImpl.suspend(AsyncContextDelegateProviderImpl.java:87)
    at org.glassfish.jersey.servlet.internal.ResponseWriter.suspend(ResponseWriter.java:120)
    at org.glassfish.jersey.server.ServerRuntime$AsyncResponder.suspend(ServerRuntime.java:758)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:330)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:106)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:259)
    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:318)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:236)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1010)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:373)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:382)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:345)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:220)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

Jan 31, 2014 4:06:53 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [HelloServlet] in context with path [/Jersey2.5Service] threw exception [javax.ws.rs.ProcessingException: Attempt to suspend a connection of an asynchronous request failed in the underlying container.] with root cause
javax.ws.rs.ProcessingException: Attempt to suspend a connection of an asynchronous request failed in the underlying container.
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:331)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:106)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:259)
    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:318)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:236)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1010)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:373)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:382)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:345)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:220)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
like image 628
anij Avatar asked Jan 31 '14 11:01

anij


People also ask

What is asynchronous callbacks in JavaScript?

Here the sort ( ) method completes first before the execution of console.log ( ) function. Now next is the Asynchronous Callbacks in JavaScript. Asynchronous simply means that if JavaScript must wait for an operation to complete then it will execute the rest of the code while waiting.

What is a callback in JavaScript?

The event and callback structure is the fundamental mechanism by which JavaScript engines are able to efficiently handle overlapping tasks, like responding to I/O requests. This is why understanding JavaScript callbacks is essential to understanding asynchronous programming in JavaScript.

How to create a nested callback in a JavaScript program?

Create a new nestedCallbacks.js file in the root directory of the project and insert the following JavaScript code: Run the program by executing the following command-line instruction in the project root directory: The best movie by Quentin Tarantino is... Inglourious Basterds !!! Examine the code line-by-line.

Why are nested callbacks so difficult to manage?

In the above code, we have multiple callbacks which depend on data from the previous functions, the callbacks are nested one inside another. As calls become more nested, the code becomes deeper and increasingly more difficult to manage, especially if we have real code that may include more loops, conditional statements, and so on.


3 Answers

For me the solution was to add support for Async in a Servlet Filter. The error message gave me a hint:

Attempt to put servlet request into asynchronous mode has failed. Please check your servlet configuration - all Servlet instances and Servlet filters involved in the request processing must explicitly declare support for asynchronous request processing

I am using Spring for Dependency Injection and using the default Jersey servlet. For Spring I use a Delegating Filter Proxy. I needed to declare for the Filter asycn support true.

So for the servlet:

 <servlet>
    <servlet-name>myserlet</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>        
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
</servlet>

AND add async support true for the the Spring filter as well.

<filter>
        <description>Spring filter</description>
        <display-name>spring-filter</display-name>
        <filter-name>springFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <async-supported>true</async-supported>
    </filter>

I hope this might help for you and others.

like image 165
Aschwin Avatar answered Oct 19 '22 09:10

Aschwin


I know this question is very old, but for people who are facing this issue Please update Tomcat Server to the Latest Version 8.** . Tomcat starting from version 8 has support for Async Processing.

like image 29
user3933885 Avatar answered Oct 19 '22 08:10

user3933885


For Async callback you can use Guava lib. For example:

@GET
@Produces(MediaType.APPLICATION_JSON)
@ManagedAsync
public void getBooks(@Suspended final AsyncResponse response){

ListenableFuture<Collection<Book>> bookFuture = dao.getBooksAsync();
    Futures.addCallback(bookFuture, new FutureCallback<Collection<Book>>() {

        public void onSuccess(Collection<Book> books){
            response.resume(books);
        }
        public void onFailure(Throwable thrown){
            response.resume(thrown);
        }
    });
}

And in my book DAO I have:

BookDao(){
    books = new HashMap<String,Book>();

    Book b1 = new Book();

    service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));               
}

Collection<Book> getBooks(){

    return(books.values());
}

ListenableFuture<Collection<Book>> getBooksAsync(){

    ListenableFuture<Collection<Book>> future = 
            service.submit(new Callable<Collection<Book>>() {
                public Collection<Book> call() throws Exception{
                    return getBooks();
                }
            });
    return(future);
}
like image 1
FelasDroid Avatar answered Oct 19 '22 07:10

FelasDroid