tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bugzi...@apache.org
Subject DO NOT REPLY [Bug 38361] New: - RD.forward() does not flush and causes problems with error pages
Date Tue, 24 Jan 2006 00:42:27 GMT
DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG·
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=38361>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND·
INSERTED IN THE BUG DATABASE.

http://issues.apache.org/bugzilla/show_bug.cgi?id=38361

           Summary: RD.forward() does not flush and causes problems with
                    error pages
           Product: Tomcat 5
           Version: 5.5.14
          Platform: Other
        OS/Version: other
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Catalina
        AssignedTo: tomcat-dev@jakarta.apache.org
        ReportedBy: jan.luehe@sun.com


Consider the following code snippet of a servlet's service() method:

  public class DispatcherServlet extends HttpServlet {

    public void service(HttpServletRequest req, HttpServletResponse res)
        throws IOException, ServletException {

      request.getRequestDispatcher("/target").forward(request, response);

      try {
          Thread.currentThread().sleep(60000);
      } catch (Exception ex) { }
    }

where "target" prints some output to the response.

The code currently returns the output printed by "target" only after
DispatcherServlet's service() method has finished, instead of right
before RD.forward() returns.

This seems to be in violation of the Servlet Spec, which has this:

SRV.8.4 ("The Forward Method"):

  Before the forward() method of the RequestDispatcher interface
  returns, the response content must be sent and committed, and closed
  by the servlet container.

The code at the end of o.a.c.core.ApplicationDispatcher.doForward()
looks like this:

        // This is not a real close in order to support error processing
        if ( log.isDebugEnabled() )
            log.debug(" Disabling the response for futher output");

        if  (response instanceof ResponseFacade) {
            ((ResponseFacade) response).finish();
        } else {
            // Servlet SRV.6.2.2. The Resquest/Response may have been
wrapped
            // and may no longer be instance of RequestFacade
            if (log.isDebugEnabled()){
                log.debug( " The Response is vehiculed using a wrapper: "
                           + response.getClass().getName() );
            }

            // Close anyway
            try {
                PrintWriter writer = response.getWriter();
                writer.close();
            } catch (IllegalStateException e) {
                try {
                    ServletOutputStream stream = response.getOutputStream();
                    stream.close();
                } catch (IllegalStateException f) {
                    ;
                } catch (IOException f) {
                    ;
                }
            } catch (IOException e) {
                ;
            }
        }

In the above code sample, response will be an instance of
ResponseFacade, meaning it will be suspended instead of being flushed
and closed right away.

This approach has a couple of problems:

- An attempt by servlet code to flush the response after RD.forward()
  has returned will have no effect, because a response in suspended
  state ignores any calls to it.

- Consider the case where a request has been
  forward-dispatched into a foreign context. If the target servlet in
  the foreign context has set an error code on the response, and the
  response is suspended before returning from the RD.forward(),
  the error code will be mapped to an error page using the mappings of
  the *origin* context as the response travels through the origin
  context's pipeline (and error valve) on the way out.
  The origin and target contexts may map the same status code to
  different error pages, or the origin context may not even contain any
  mapping for the given status code. In any case, it is
  confusing for the origin context's mappings to be used, since a
  RD.forward() is supposed to transfer control to the target (context).

-- 
Configure bugmail: http://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.

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


Mime
View raw message