Return-Path: Delivered-To: apmail-tomcat-dev-archive@www.apache.org Received: (qmail 73916 invoked from network); 28 Aug 2010 11:09:04 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 28 Aug 2010 11:09:04 -0000 Received: (qmail 55206 invoked by uid 500); 28 Aug 2010 11:09:04 -0000 Delivered-To: apmail-tomcat-dev-archive@tomcat.apache.org Received: (qmail 54606 invoked by uid 500); 28 Aug 2010 11:09:00 -0000 Mailing-List: contact dev-help@tomcat.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "Tomcat Developers List" Delivered-To: mailing list dev@tomcat.apache.org Received: (qmail 54597 invoked by uid 99); 28 Aug 2010 11:08:58 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 28 Aug 2010 11:08:58 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 28 Aug 2010 11:08:57 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 4A9A123888FD; Sat, 28 Aug 2010 11:07:40 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r990342 - in /tomcat/trunk: java/org/apache/catalina/core/AsyncContextImpl.java test/org/apache/catalina/core/TestAsyncContextImpl.java webapps/docs/changelog.xml Date: Sat, 28 Aug 2010 11:07:40 -0000 To: dev@tomcat.apache.org From: markt@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20100828110740.4A9A123888FD@eris.apache.org> Author: markt Date: Sat Aug 28 11:07:39 2010 New Revision: 990342 URL: http://svn.apache.org/viewvc?rev=990342&view=rev Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=49698 Allow listeners to call complete when a async request times out Add a test case based on pero's previous timeout test case Modified: tomcat/trunk/java/org/apache/catalina/core/AsyncContextImpl.java tomcat/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java tomcat/trunk/webapps/docs/changelog.xml Modified: tomcat/trunk/java/org/apache/catalina/core/AsyncContextImpl.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/AsyncContextImpl.java?rev=990342&r1=990341&r2=990342&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/AsyncContextImpl.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/AsyncContextImpl.java Sat Aug 28 11:07:39 2010 @@ -51,7 +51,7 @@ public class AsyncContextImpl implements public static enum AsyncState { NOT_STARTED, STARTED, DISPATCHING, DISPATCHED, COMPLETING, TIMING_OUT, - ERROR_DISPATCHING + TIMING_OUT_NEED_COMPLETE, ERROR_DISPATCHING } private static final Log log = LogFactory.getLog(AsyncContextImpl.class); @@ -82,13 +82,19 @@ public class AsyncContextImpl implements } if (state.get()==AsyncState.COMPLETING) { //do nothing - } else if (state.compareAndSet(AsyncState.DISPATCHED, AsyncState.COMPLETING) || - state.compareAndSet(AsyncState.STARTED, AsyncState.COMPLETING)) { + } else if (state.compareAndSet(AsyncState.DISPATCHED, + AsyncState.COMPLETING) || + state.compareAndSet(AsyncState.STARTED, + AsyncState.COMPLETING) || + state.compareAndSet(AsyncState.TIMING_OUT_NEED_COMPLETE, + AsyncState.COMPLETING)) { AtomicBoolean dispatched = new AtomicBoolean(false); - request.getCoyoteRequest().action(ActionCode.ACTION_ASYNC_COMPLETE,dispatched); + request.getCoyoteRequest().action(ActionCode.ACTION_ASYNC_COMPLETE, + dispatched); if (!dispatched.get()) doInternalComplete(false); } else { - throw new IllegalStateException("Complete not allowed. Invalid state:"+state.get()); + throw new IllegalStateException( + "Complete not allowed. Invalid state:"+state.get()); } } @@ -296,10 +302,14 @@ public class AsyncContextImpl implements } public void doInternalDispatch() throws ServletException, IOException { - if (this.state.compareAndSet(AsyncState.TIMING_OUT, AsyncState.COMPLETING)) { + if (this.state.compareAndSet(AsyncState.TIMING_OUT, + AsyncState.TIMING_OUT_NEED_COMPLETE)) { log.debug("TIMING OUT!"); boolean listenerInvoked = false; - for (AsyncListenerWrapper listener : listeners) { + List listenersCopy = + new ArrayList(); + listenersCopy.addAll(listeners); + for (AsyncListenerWrapper listener : listenersCopy) { listener.fireOnTimeout(event); listenerInvoked = true; } 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=990342&r1=990341&r2=990342&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java (original) +++ tomcat/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java Sat Aug 28 11:07:39 2010 @@ -17,9 +17,12 @@ package org.apache.catalina.core; +import java.io.File; import java.io.IOException; import javax.servlet.AsyncContext; +import javax.servlet.AsyncEvent; +import javax.servlet.AsyncListener; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -308,4 +311,70 @@ public class TestAsyncContextImpl extend } } + public void testTimeout() throws Exception { + // Setup Tomcat instance + Tomcat tomcat = getTomcatInstance(); + + // Must have a real docBase - just use temp + File docBase = new File(System.getProperty("java.io.tmpdir")); + + // Create the folder that will trigger the redirect + File foo = new File(docBase, "async"); + if (!foo.exists() && !foo.mkdirs()) { + fail("Unable to create async directory in docBase"); + } + + Context ctx = tomcat.addContext("/", docBase.getAbsolutePath()); + + TimeoutServlet timeout = new TimeoutServlet(); + + Wrapper wrapper = Tomcat.addServlet(ctx, "time", timeout); + wrapper.setAsyncSupported(true); + ctx.addServletMapping("/async", "time"); + + tomcat.start(); + ByteChunk res = getUrl("http://localhost:" + getPort() + "/async"); + assertEquals("OK", res.toString()); + } + + private static class TimeoutServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + if (req.isAsyncSupported()) { + resp.getWriter().print("OK"); + final AsyncContext ac = req.startAsync(); + ac.setTimeout(2000); + + ac.addListener(new TimeoutListener()); + } else + resp.getWriter().print("FAIL: Async unsupported"); + } + } + + private static class TimeoutListener implements AsyncListener { + + @Override + public void onComplete(AsyncEvent event) throws IOException { + // NO-OP + } + + @Override + public void onTimeout(AsyncEvent event) throws IOException { + event.getAsyncContext().complete(); + } + + @Override + public void onError(AsyncEvent event) throws IOException { + // NOOP + } + + @Override + public void onStartAsync(AsyncEvent event) throws IOException { + // NOOP + } + + } } Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=990342&r1=990341&r2=990342&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Sat Aug 28 11:07:39 2010 @@ -52,6 +52,10 @@ refactoring. (markt) + 49698: Allow a listener to complete an asynchronous request + if it times out. (markt) + + 49714: The annotation process of Jar doesn't influence distributable element of web.xml. (kfujino) --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org For additional commands, e-mail: dev-help@tomcat.apache.org