Author: markt Date: Sun Jun 3 15:50:50 2012 New Revision: 1345688 URL: http://svn.apache.org/viewvc?rev=1345688&view=rev Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=53337 Fix RequestDispatcher.forward() to an async servlet
Modified: tomcat/trunk/java/org/apache/catalina/core/ApplicationDispatcher.java tomcat/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java Modified: tomcat/trunk/java/org/apache/catalina/core/ApplicationDispatcher.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/ApplicationDispatcher.java?rev=1345688&r1=1345687&r2=1345688&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/ApplicationDispatcher.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/ApplicationDispatcher.java Sun Jun 3 15:50:50 2012 @@ -382,6 +382,12 @@ final class ApplicationDispatcher processRequest(request,response,state); } + if (request.getAsyncContext() != null) { + // An async request was started during the forward, don't close the + // response as it may be written to during the async handling + return; + } + // This is not a real close in order to support error processing if (wrapper.getLogger().isDebugEnabled() ) wrapper.getLogger().debug(" Disabling the response for futher output"); 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=1345688&r1=1345687&r2=1345688&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java (original) +++ tomcat/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java Sun Jun 3 15:50:50 2012 @@ -22,10 +22,13 @@ import java.io.IOException; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import javax.servlet.AsyncContext; import javax.servlet.AsyncEvent; import javax.servlet.AsyncListener; +import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; @@ -1275,4 +1278,86 @@ public class TestAsyncContextImpl extend } } } + + @Test + public void testBug53337() 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")); + + Context ctx = tomcat.addContext("", docBase.getAbsolutePath()); + Wrapper a = Tomcat.addServlet(ctx, "ServletA", new Bug53337ServletA()); + a.setAsyncSupported(true); + Wrapper b = Tomcat.addServlet(ctx, "ServletB", new Bug53337ServletB()); + b.setAsyncSupported(true); + Tomcat.addServlet(ctx, "ServletC", new Bug53337ServletC()); + ctx.addServletMapping("/ServletA", "ServletA"); + ctx.addServletMapping("/ServletB", "ServletB"); + ctx.addServletMapping("/ServletC", "ServletC"); + + tomcat.start(); + + StringBuilder url = new StringBuilder(48); + url.append("http://localhost:"); + url.append(getPort()); + url.append("/ServletA"); + + ByteChunk body = new ByteChunk(); + int rc = getUrl(url.toString(), body, null); + + assertEquals(HttpServletResponse.SC_OK, rc); + assertEquals("OK", body.toString()); + } + + private static class Bug53337ServletA extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + RequestDispatcher rd = req.getRequestDispatcher("/ServletB"); + rd.forward(req, resp); + } + } + + private static class Bug53337ServletB extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(final HttpServletRequest req, + final HttpServletResponse resp) + throws ServletException, IOException { + + final AsyncContext async = req.startAsync(); + // Just for debugging + async.setTimeout(100000); + + ExecutorService executor = Executors.newSingleThreadExecutor(); + executor.submit(new Runnable() { + + @Override + public void run() { + async.dispatch("/ServletC"); + } + }); + executor.shutdown(); + } + } + + private static class Bug53337ServletC extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.setContentType("text/plain"); + resp.getWriter().print("OK"); + } + } + } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org