Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 330738

Summary: Servlet3Continuation throws exception on timeout
Product: [RT] Jetty Reporter: Juriy Mising name <juriy.bura>
Component: otherAssignee: Project Inbox <jetty-inbox>
Status: RESOLVED FIXED QA Contact:
Severity: major    
Priority: P3 CC: gregw
Version: unspecified   
Target Milestone: 7.1.x   
Hardware: PC   
OS: Windows 7   
Whiteboard:

Description Juriy Mising name CLA 2010-11-20 10:32:19 EST
Build Identifier: jetty-8 M1

When you try to use the Servlet3Continuation wrapper it causes the exception to be thrown.

Here's the simple code that I used to test Servlet3Continuation on the Servlet 3.0 enabled server (Tomcat 7.0.4).

		Servlet3Continuation continuation = new Servlet3Continuation(request);
		continuation.suspend();
		continuation.setTimeout(4000);

When timeout hits the Servlet3Continuation calls the asyncEvent.getAsyncContext().dispatch(); method. The call causes the following exception in Tomcat:

java.lang.IllegalStateException: Calling [dispatchAsync()] is not valid for a request with Async state [TIMING_OUT]
	at org.apache.coyote.AsyncStateMachine.asyncDispatch(AsyncStateMachine.java:220)
	at org.apache.coyote.http11.Http11NioProcessor.actionInternal(Http11NioProcessor.java:672)
	at org.apache.coyote.http11.AbstractHttp11Processor.action(AbstractHttp11Processor.java:937)
	at org.apache.coyote.Request.action(Request.java:348)
	at org.apache.catalina.core.AsyncContextImpl.dispatch(AsyncContextImpl.java:173)
	at org.apache.catalina.core.AsyncContextImpl.dispatch(AsyncContextImpl.java:135)
	at org.apache.catalina.core.AsyncContextImpl.dispatch(AsyncContextImpl.java:130)
	at org.eclipse.jetty.continuation.Servlet3Continuation$1.onTimeout(Servlet3Continuation.java:48)
	at org.apache.catalina.core.AsyncListenerWrapper.fireOnTimeout(AsyncListenerWrapper.java:45)
	at org.apache.catalina.core.AsyncContextImpl.timeout(AsyncContextImpl.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:270)
	at org.apache.coyote.http11.Http11NioProcessor.asyncDispatch(Http11NioProcessor.java:232)
	at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.event(Http11NioProtocol.java:305)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1526)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)

I'm not quite sure if it is a Jetty's or Tomcat's bug. 



Reproducible: Always

Steps to Reproduce:
1. Create a web application with a single Servlet:
public class SnowServlet extends HttpServlet {

	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Servlet3Continuation continuation = new Servlet3Continuation(request);
		continuation.suspend();
		continuation.setTimeout(4000);
}

2. Launch in Tomcat 7 (should run with protocol="org.apache.coyote.http11.Http11NioProtocol" and <async-enabled>true</async-enabled> in servlet description block in web.xml

3. Invoke the servlet in the browser and look at in the console (or in the tomcat's log)
Comment 1 Greg Wilkins CLA 2010-11-20 18:09:44 EST
I'm 99% sure this is a tomcat bug.   onTimeout calls should be able to call dispatch, from the servlet 3.0 spec:

In the event that an asynchronous operation times out, the container must run
through the following steps:
■ Invoke the AsyncListener.onTimeout method on all the AsyncListener
   instances registered with the ServletRequest on which the asynchronous
  operation was initiated.
■ If none of the listeners called AsyncContext.complete() or any of the
   AsyncContext.dispatch methods, perform an error dispatch with a status
  code equal to HttpServletResponse.SC_INTERNAL_SERVER_ERROR.
If no matching error page was found, or the error page did not call
AsyncContext.complete() or any of the AsyncContext.dispatch
methods, the container MUST call AsyncContext.complete().


So this implies that a timeout request can call dispatch.

cheers

PS. you should probably not create continuations directly, but instead use the ContinuationSupport class to do tht.