1

I have the following code snippet in my web app:

if (request.getParameter("user").equals("luke")||session == null && !(uri.endsWith("html") || uri.endsWith("LoginServlet"))) {  
    System.out.println("<<<----------denied------------->>>>");  
    pw.println("zzzzzzzzzz");  
    this.context.log("Unauthorized access request");  
    pw.flush(); 

    try {  
        Thread.sleep(5000);  
    } catch (InterruptedException e) {  
        // TODO Auto-generated catch block  
        e.printStackTrace();  
    }  

    //res.sendRedirect("login.html");  
    req.getRequestDispatcher("login.html").include(request,response);  
} 

When I am using flush before Forward(), it's throwing IllegalStateException (since the response is sent the moment we call flush and later we are trying to resend the response using forward) but the code works fine even after I provided flush before the rd.include(). Why doesn't it throw the exception here?

TIA

Tiny
  • 27,221
  • 105
  • 339
  • 599
jayendra bhatt
  • 1,337
  • 2
  • 19
  • 41

2 Answers2

1

This behavior is explained in the Servlet Specification for the forward method in chapter 9.4 and for the include method in chapter 9.3.

The javadoc also explains this in a little detail.

The javadoc entry of HttpServletResponse#getWriter() states

Calling flush() on the PrintWriter commits the response.

Committing the response means writing the status line and headers and flushing whatever part of the response body is in the buffer.

The javadoc of forward states

Forwards a request from a servlet to another resource (servlet, JSP file, or HTML file) on the server. This method allows one servlet to do preliminary processing of a request and another resource to generate the response.

So the forward to resource must take care of generating and committing the response. It can't do that if the response has already been committed.

The javadoc of include states

The included servlet cannot change the response status code or set headers; any attempt to make a change is ignored.

This method just takes the content of another resource and writes it to the response. It can't do anything to headers or the status code. As such, committing before or after makes no difference.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • thats right but flush commits the state of outputstream and response is sent to the client , then why in the case of include the exception is not thrown when the response is sent again by rd.include(). – jayendra bhatt Sep 04 '14 at 19:39
  • @jayendrabhatt It's not sent _again_. The content of the `include` is added (appended) to the response **body**. – Sotirios Delimanolis Sep 04 '14 at 20:21
  • Apologies for my ignorance but by the time we are trying to append the information using include to the response, the response was already gone(due to flush).then how the page gets included?please correct me if i am wrong – jayendra bhatt Sep 05 '14 at 04:29
  • @jayendrabhatt Ok. HTTP is built on top of TCP which is a streaming protocol. The response status code and headers are what is definitely sent in the call to `flush()`. In addition to that, whatever is currently buffered will also be sent. You can continue to stream response content while the underlying (Socket)`OutputStream` is still open. – Sotirios Delimanolis Sep 05 '14 at 04:32
0

The forward and the include are different methods, the include method allows you to add content to the response, you have a include tag in jsp, the include method is the similar but in the server.

The forward method transfer the request processing to another process (servlet, jsp) and that process must change the response, that is why you get that exception, you can't change the response before forward it.

You could check the documentation for those methods here.

Cesar Loachamin
  • 2,740
  • 4
  • 25
  • 33