7

I'm writing some basic code as I learn about the RequestDispatcher. I understand that when rd.forward() is called, control (and response handling) is forwarded to the resource named in the path - in this case another servlet. But why doesn't this code throw an IllegalStateException (not that I want one) due to the out.write() statements earlier in the code?

I guess what I'm really asking is, how or when would these out.write() statements be committed?

Thanks, Jeff

public class Dispatcher extends HttpServlet{
  public void doGet(HttpServletRequest request, HttpServletResponse response)
           throws IOException, ServletException{

    response.setContentType("text/plain");
    PrintWriter out = response.getWriter();
    out.write("In Dispatcher\n");

    String modeParam = request.getParameter("mode");
    String path = "/Receiver/pathInfo?fruit=orange";
    RequestDispatcher rd = request.getRequestDispatcher(path);
    if(rd == null){
        out.write("Request Dispatcher is null. Please check path.");
    }
        if(modeParam.equals("forward")){
            out.write("forwarding...\n");
            rd.forward(request, response);
        }
        else if(modeParam.equals("include")){
            out.write("including...\n");
            rd.include(request, response);
        }
    out.flush();
    out.close();
}

}

Jeff Levine
  • 1,865
  • 9
  • 24
  • 36

3 Answers3

4

Because you haven't called flush.

Everything will be cleared out before forwarding if you haven't flushed. Otherwise, you'll get an excpetion you expect.

As in the docs:

For a RequestDispatcher obtained via getRequestDispatcher(), the ServletRequest object has its path elements and parameters adjusted to match the path of the target resource.

forward should be called before the response has been committed to the client (before response body output has been flushed). If the response already has been committed, this method throws an IllegalStateException. Uncommitted output in the response buffer is automatically cleared before the forward.

Tala
  • 8,298
  • 4
  • 30
  • 35
3

Read the docs.

Calling flush() on the PrintWriter commits the response.

Now, as per your curiosity that why there is no IllegalStateException thrown. It's simply because PrintWriter.flush() doesn't throw this or any checked exception. And, we know that the response was not committed when rd.forward() is invoked, since flush() comes later in the method.

Adeel Ansari
  • 38,068
  • 12
  • 89
  • 127
  • Got it. Why, then, is no exception thrown if I modify the end of the code as follows: `out.flush(); out.write("exception code?"); out.close();` – Jeff Levine Aug 14 '13 at 09:40
  • 2
    Exception is thrown in `forward` method if flush was called before that – Tala Aug 14 '13 at 09:41
  • Precisely. Thanks, Tala. And don't forget everything has already been cleared, when it gets forwarded. See, Tala's post. – Adeel Ansari Aug 14 '13 at 09:49
1

You did not make call to flush() before forward. So it does not shows any exception. If you write flush() before request is forwarded then it will throw exception.

When We call flush(), then all what was in buffer is sent to the browser and buffer is cleared.

In following scenario we will get exception.

response.getWriter().print('hello...');  
response.getWriter().flush();  
request.getRequestDispatcher("/index.").forward(request, response);
Balakrishna
  • 166
  • 1
  • 12