users@jersey.java.net

[Jersey] Re: ChunkedOutput with AsyncResponse

From: Van Klaveren, Brian N. <bvan_at_slac.stanford.edu>
Date: Fri, 27 Jun 2014 10:28:17 -0700

Hi,

What version of jersey/java/OS are you using?
Can you provide a code snippet?

I had issues with tomcat 7.0.54 on Mac OS X 10.9.3 with 1.7u60, using Jersey 2.9. It seems like it did work for me with tomcat 7.0.27 with java 1.7.0_41. on the same OS.

At one point, I think I was getting the same exception as you, so I’m going to assume that maybe you might be having the same problem as me. I wasn’t trying to use ChunkedOutput but I was trying to use EventOutput which is a subclass. I can’t remember exactly the error I was getting, however.

There’s a Jira about this which may be related, but I’m not sure:
https://java.net/jira/browse/JERSEY-2270

A couple of things to check or try:

1. Make sure you have:
<asyncSupported>true</asyncSupported> in your web.xml under your servlet declaration.

2. Double check tomcat is using NIO. In your server.xml, you should have something like this (I don’t think this is a problem):
<Connector connectionTimeout="20000" port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" redirectPort="8443”/>


3. You could maybe try telling tomcat that async is supported for the request before the request is suspended, like in the constructor:
public ResourceClassConstructor(@Context HttpServletRequest request){
        request.setAttribute( "org.apache.catalina.ASYNC_SUPPORTED", true );
}

Brian

On Jun 27, 2014, at 3:02 AM, Christopher Ng <cng1067_at_gmail.com> wrote:

> It seems that it is currently possible to return a ChunkedOutput with an AsyncResponse, but it causes Tomcat to log a warning as Jersey tries to suspend the AsyncContext twice.
>
> This might seem like a bit of an odd thing to do, but returning ChunkedOutput synchronously always immediately returns a 200, whereas I would like to be able to choose whether to return a ChunkedOutput or eg a 500 at a 'later' point, using AsyncResponse.
>
> I get the following warning in Tomcat, but apart from that things seem to work as expected:
>
> 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: Calling [asyncStart()] is not valid for a request with Async state [STARTED]
> at org.apache.coyote.AsyncStateMachine.asyncStart(AsyncStateMachine.java:175)
> at org.apache.coyote.ajp.AbstractAjpProcessor.action(AbstractAjpProcessor.java:453)
> at org.apache.coyote.Request.action(Request.java:346)
> at org.apache.catalina.core.AsyncContextImpl.setStarted(AsyncContextImpl.java:345)
> at org.apache.catalina.connector.Request.startAsync(Request.java:1665)
> at org.apache.catalina.connector.RequestFacade.startAsync(RequestFacade.java:1029)
> at javax.servlet.ServletRequestWrapper.startAsync(ServletRequestWrapper.java:379)
> at javax.servlet.ServletRequestWrapper.startAsync(ServletRequestWrapper.java:379)
> at org.glassfish.jersey.servlet.async.AsyncContextDelegateProviderImpl$ExtensionImpl.suspend(AsyncContextDelegateProviderImpl.java:87)
> at org.glassfish.jersey.servlet.internal.ResponseWriter.suspend(ResponseWriter.java:121)
> at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:674)
> at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:375)
> at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:365)
> at org.glassfish.jersey.server.ServerRuntime$AsyncResponder$3.run(ServerRuntime.java:820)
> 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:297)
> at org.glassfish.jersey.server.ServerRuntime$AsyncResponder.resume(ServerRuntime.java:850)
> at org.glassfish.jersey.server.ServerRuntime$AsyncResponder.resume(ServerRuntime.java:812)