Author: markt Date: Mon Nov 22 14:35:51 2010 New Revision: 1037735 URL: http://svn.apache.org/viewvc?rev=1037735&view=rev Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=50308 Allow asynchronous request processing to call AsyncContext.dispatch() once the asynchronous request has timed out.
Modified: tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java tomcat/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java tomcat/trunk/webapps/docs/changelog.xml Modified: tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java?rev=1037735&r1=1037734&r2=1037735&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java (original) +++ tomcat/trunk/java/org/apache/coyote/AsyncStateMachine.java Mon Nov 22 14:35:51 2010 @@ -213,7 +213,8 @@ public class AsyncStateMachine { boolean doDispatch = false; if (state == AsyncState.STARTING) { state = AsyncState.MUST_DISPATCH; - } else if (state == AsyncState.STARTED) { + } else if (state == AsyncState.STARTED || + state == AsyncState.TIMING_OUT) { state = AsyncState.DISPATCHING; doDispatch = true; } else { Modified: tomcat/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java?rev=1037735&r1=1037734&r2=1037735&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java (original) +++ tomcat/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java Mon Nov 22 14:35:51 2010 @@ -314,14 +314,20 @@ public class TestAsyncContextImpl extend } public void testTimeoutListenerComplete() throws Exception { - doTestTimeout(true); + doTestTimeout(true, null); } public void testTimeoutListenerNoComplete() throws Exception { - doTestTimeout(false); + doTestTimeout(false, null); + } + + public void testTimeoutListenerDispatch() throws Exception { + doTestTimeout(true, "/nonasync"); } - private void doTestTimeout(boolean completeOnTimeout) throws Exception { + + private void doTestTimeout(boolean completeOnTimeout, String dispatchUrl) + throws Exception { // Setup Tomcat instance Tomcat tomcat = getTomcatInstance(); @@ -336,12 +342,19 @@ public class TestAsyncContextImpl extend Context ctx = tomcat.addContext("", docBase.getAbsolutePath()); - TimeoutServlet timeout = new TimeoutServlet(completeOnTimeout); + TimeoutServlet timeout = + new TimeoutServlet(completeOnTimeout, dispatchUrl); Wrapper wrapper = Tomcat.addServlet(ctx, "time", timeout); wrapper.setAsyncSupported(true); ctx.addServletMapping("/async", "time"); + if (dispatchUrl != null) { + NonAsyncServlet nonAsync = new NonAsyncServlet(); + Tomcat.addServlet(ctx, "nonasync", nonAsync); + ctx.addServletMapping(dispatchUrl, "nonasync"); + } + tomcat.start(); ByteChunk res = getUrl("http://localhost:" + getPort() + "/async"); StringBuilder expected = new StringBuilder(); @@ -349,7 +362,11 @@ public class TestAsyncContextImpl extend if (!completeOnTimeout) { expected.append("onError-"); } - expected.append("onComplete-"); + if (dispatchUrl == null) { + expected.append("onComplete-"); + } else { + expected.append("NonAsyncServletGet-"); + } assertEquals(expected.toString(), res.toString()); } @@ -357,9 +374,11 @@ public class TestAsyncContextImpl extend private static final long serialVersionUID = 1L; private boolean completeOnTimeout; - - public TimeoutServlet(boolean completeOnTimeout) { + private String dispatchUrl; + + public TimeoutServlet(boolean completeOnTimeout, String dispatchUrl) { this.completeOnTimeout = completeOnTimeout; + this.dispatchUrl = dispatchUrl; } @Override @@ -370,7 +389,8 @@ public class TestAsyncContextImpl extend final AsyncContext ac = req.startAsync(); ac.setTimeout(3000); - ac.addListener(new TrackingListener(false, completeOnTimeout)); + ac.addListener(new TrackingListener( + false, completeOnTimeout, dispatchUrl)); } else resp.getWriter().print("FAIL: Async unsupported"); } @@ -463,7 +483,7 @@ public class TestAsyncContextImpl extend final AsyncContext ctxt = req.startAsync(); if (addTrackingListener) { TrackingListener listener = - new TrackingListener(completeOnError, true); + new TrackingListener(completeOnError, true, null); ctxt.addListener(listener); } Runnable run = new Runnable() { @@ -510,7 +530,7 @@ public class TestAsyncContextImpl extend wrapper.setAsyncSupported(true); ctx.addServletMapping("/stage1", "tracking"); - TimeoutServlet timeout = new TimeoutServlet(true); + TimeoutServlet timeout = new TimeoutServlet(true, null); Wrapper wrapper2 = Tomcat.addServlet(ctx, "timeout", timeout); wrapper2.setAsyncSupported(true); ctx.addServletMapping("/stage2", "timeout"); @@ -546,7 +566,7 @@ public class TestAsyncContextImpl extend TrackingServlet.first = false; final AsyncContext ctxt = req.startAsync(); - TrackingListener listener = new TrackingListener(false, true); + TrackingListener listener = new TrackingListener(false, true, null); ctxt.addListener(listener); ctxt.setTimeout(3000); @@ -572,11 +592,13 @@ public class TestAsyncContextImpl extend private boolean completeOnError; private boolean completeOnTimeout; + private String dispatchUrl; public TrackingListener(boolean completeOnError, - boolean completeOnTimeout) { + boolean completeOnTimeout, String dispatchUrl) { this.completeOnError = completeOnError; this.completeOnTimeout = completeOnTimeout; + this.dispatchUrl = dispatchUrl; } @Override @@ -592,7 +614,11 @@ public class TestAsyncContextImpl extend resp.getWriter().write("onTimeout-"); resp.flushBuffer(); if (completeOnTimeout){ - event.getAsyncContext().complete(); + if (dispatchUrl == null) { + event.getAsyncContext().complete(); + } else { + event.getAsyncContext().dispatch(dispatchUrl); + } } } Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1037735&r1=1037734&r2=1037735&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Mon Nov 22 14:35:51 2010 @@ -154,6 +154,11 @@ continue to use the version of the web application with which the session is associated until the session expires. (markt) </add> + <fix> + <bug>50308</bug>: Allow asynchronous request processing to call + <code>AsyncContext.dispatch()</code> once the asynchronous request has + timed out. (markt) + </fix> </changelog> </subsection> <subsection name="Coyote"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org