In a scenario that involves a forward, a call to startAsync, and then dispatch(path), the properties of the request after the dispatch do not match the path and query params used to send the dispatch. A project demonstrating the issue: https://github.com/rstoyanchev/dispatch-test Build and deploy the sources in the 'tomcat-issue-repro' branch. From the home page of the deployed application, select the "Dispatch via AsyncContext" scenario. The scenario involves a couple of forwards from ServletA to Servlet B and then ServletC, which in turn starts a thread and dispatches to Servlet D that forwards to a JSP. See WebAppInitializer.setupDispatchScenario(ServletContext) for details on the setup. The log output shows the content of the request as each Servlet is entered. It all looks as expected until after the dispatch to ServletD where the requestUri, servletPath, and pathInfo are for ServletC. --- The second scenario on the home page, "Dispatch via AsyncContext and wrap request", wraps the request and that yields slightly different (but also incorrect) results. The requestUri/servletPath/pathInfo and also the parameterMap, in the application thread and after dispatch, both match the state of the request in ServletA. --- FWIW there are also a couple of similar scenarios that use forwarding instead of dispatching. The "Forward via RequestDispatcher" scenario appears to work all the way through while the "Forward via RequestDispatcher and wrap request" almost works except the state of the request in the async thread only matches that of ServletA.
Thanks for the excellent test case. Very easy to work with. I have the bug in the first scenario fixed. I'll look at the second scenario next. It looks like the bug in the second and fourth scenario are related. I'll commit the fixes once all the scenarios are working.
*** Bug 53632 has been marked as a duplicate of this bug. ***
This has been fixed in trunk and 7.0.x and will be included in 7.0.30 onwards. The root cause was that Tomcat used the RequestDispatcher.include() to perform async dispatches with some trickery to differentiate an include and a dispatch. Wrapping the request (which also happens on a forward) was enough to break the mechanism. A new, hopefulyl more robust, approach has been implemented and all the provided tests (including those in the duplicate) now pass.
Thanks for the quick turnaround!