Author: markt
Date: Sun Jun  3 15:54:28 2012
New Revision: 1345689

URL: http://svn.apache.org/viewvc?rev=1345689&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=53337
Fix RequestDispatcher.forward() to an async servlet. Includes a test case based 
on code by Rossen Stoyanchev.

Modified:
    tomcat/tc7.0.x/trunk/   (props changed)
    
tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/ApplicationDispatcher.java
    tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java
    tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml

Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
  Merged /tomcat/trunk:r1345688

Modified: 
tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/ApplicationDispatcher.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/ApplicationDispatcher.java?rev=1345689&r1=1345688&r2=1345689&view=diff
==============================================================================
--- 
tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/ApplicationDispatcher.java 
(original)
+++ 
tomcat/tc7.0.x/trunk/java/org/apache/catalina/core/ApplicationDispatcher.java 
Sun Jun  3 15:54:28 2012
@@ -402,6 +402,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/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java?rev=1345689&r1=1345688&r2=1345689&view=diff
==============================================================================
--- 
tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java 
(original)
+++ 
tomcat/tc7.0.x/trunk/test/org/apache/catalina/core/TestAsyncContextImpl.java 
Sun Jun  3 15:54:28 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");
+        }
+    }
+
 }

Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1345689&r1=1345688&r2=1345689&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Sun Jun  3 15:54:28 2012
@@ -181,6 +181,11 @@
         patch provided by Violeta Georgieva. (markt)
       </fix>
       <fix>
+        <bug>53337</bug>: Forwarding via a <code>RequestDispatcher</code> to an
+        asynchronous Servlet always failed. Includes a test case based on code
+        by Rossen Stoyanchev. (markt)
+      </fix>
+      <fix>
         <bug>53342</bug>: To avoid BindException, make startStopThreads into a
         demon thread. (kfujino)
       </fix>



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to