*
The moose likes Web Component Certification (SCWCD/OCPJWCD) and the fly likes Doubt on RequestDispatcher Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Web Component Certification (SCWCD/OCPJWCD)
Bookmark "Doubt on RequestDispatcher" Watch "Doubt on RequestDispatcher" New topic
Author

Doubt on RequestDispatcher

Ana Nava
Greenhorn

Joined: May 25, 2004
Posts: 24
HF -> Page 209 -> Chapter 5 -> Coffee Cram Question no : 1.

Following is the Question along with its options.

When using a RequestDispatcher, the use of which methods often lead to an IllegalStateException.

  • A. read
  • B. flush
  • C. write
  • D. getOutputStream
  • E. getResourceAsStream

  • Although the answer in page 215 has just option B (flush) selected, in the errata they have stated to include option C (write) as well.

    When I tried an example in Tomcat 5.0, I used getWriter and println method before calling forward method, it did not cause any error. But when I tried with getOutStream and write, before calling forward method following was the error message I got.

    java.lang.IllegalStateException: getOutputStream() has already been called for this response


    Above error occurred when I just called getOutStream without write method.

    Did NOT use flush method in any case.

    In Spec Servlet 2.4 page 167, following is stated.

    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.


    What I understand from the spec is that, only calling flush method should cause an error.

    So these are my questions.

    1.In the errata, it has stated to include option C (write) but not option D (getOutStream). Should option D (getOutputStream) be included as well?

    2.Is this behavior vendor-specific that is, does all servlet-containers throw error when getOutputStream or write method is called before forward method?

    3.If this question is in exam, what option(s) should I select?

    Thanks.
    John Wolf
    Ranch Hand

    Joined: Feb 18, 2002
    Posts: 64
    Ana,

    Here's my attempt to answer your questions...

    1.In the errata, it has stated to include option C (write) but not option D (getOutStream). Should option D (getOutputStream) be included as well?

    No. This is not directly related to the RequestDispatcher question. You have to remember that you get the IllegalStateException because you cannot invoke both getWriter() and getOutputStream on the same response object. (Nothing to do with RequestDispatcher in this case.)

    2.Is this behavior vendor-specific that is, does all servlet-containers throw error when getOutputStream or write method is called before forward method?

    Its not vendor specific based on Answer 1

    3.If this question is in exam, what option(s) should I select?

    You should select B) flush and C) write. Calling either flush or write means the response is committed
    Ana Nava
    Greenhorn

    Joined: May 25, 2004
    Posts: 24
    No. This is not directly related to the RequestDispatcher question. You have to remember that you get the IllegalStateException because you cannot invoke both getWriter() and getOutputStream on the same response object. (Nothing to do with RequestDispatcher in this case.)


    Thanks for the response. Sorry for not being clear with my example.

    I did the following :-

    Servlet 1 : Used getWriter and println method, followed by forward method. This did NOT throw any error.

    Servlet 2 : Used getOutputStream and write method (no flush method), followed by forward method. This threw the above stated error.

    Servlet 3 : Used just getOutputStream (no write and no flush method), followed by forward method. This threw the above stated error as well.

    I did NOT invoke both getWriter() and getOutputStream on the same response object as they were in two "DIFFERENT" servlets.

    The error is due to RequestDispatcher, because calling both getOutputStream and forward method in the same service method causes this exception.

    so my question still remains

    Thanks.
    Luis Torres
    Greenhorn

    Joined: May 02, 2008
    Posts: 20
    so my question still remains


    I agree with Ana.

    Also I tried this:

    Servlet 5: Used getWriter and write method, followed by forward method. This did NOT throw any error.


    some answer?

    Thanks.
    [ May 19, 2008: Message edited by: Luis Torres ]

    SCJP5 90%
    imaya Munusamy
    Greenhorn

    Joined: May 19, 2008
    Posts: 20
    Hi Its not problem with RequestDispatcher. if you call getOutputStream() and
    getWriter() for same response it will fail

    Problem might be you would have forwarded to jsp page. i assume it 'll call getWriter to update content so if you already called getOutputStream() it will fail.

    Try to fwd to a servlet and call getOutputStream() again it will work fine
    Pavan Sambare
    Greenhorn

    Joined: Aug 21, 2006
    Posts: 23
    I feel the thing is more to do with buffering. The getWriter() method returns a PrintWriter which actually wraps the OutputStream. It buffers the things you put in writer.println() before actually pushing them to the output stream. Hence if you do a forward before the stream is flushed/buffer is full, you will not get an IllegalStateException.
    Whereas if you directly write to an OutputStream, the response is sent immediately and that is why you get the IllegalStateException.


    SCJP 1.4 -- 98%<br />SCWCD 5 -- 97%
    Satya Maheshwari
    Ranch Hand

    Joined: Jan 01, 2007
    Posts: 368
    Originally posted by Ana Nava:


    Thanks for the response. Sorry for not being clear with my example.

    I did the following :-

    Servlet 1 : Used getWriter and println method, followed by forward method. This did NOT throw any error.

    Servlet 2 : Used getOutputStream and write method (no flush method), followed by forward method. This threw the above stated error.

    Servlet 3 : Used just getOutputStream (no write and no flush method), followed by forward method. This threw the above stated error as well.

    I did NOT invoke both getWriter() and getOutputStream on the same response object as they were in two "DIFFERENT" servlets.

    The error is due to RequestDispatcher, because calling both getOutputStream and forward method in the same service method causes this exception.

    so my question still remains

    Thanks.



    I did NOT invoke both getWriter() and getOutputStream on the same response object as they were in two "DIFFERENT" servlets.

    As you are passing the same 'request' and 'response' objects while forwarding to the other servlet, you are using the same response object. Hence I do not think what you say above is correct.

    Servlet 1 : Used getWriter and println method, followed by forward method. This did NOT throw any error.
    This would not throw an error as you have not committed your response. Try calling forward after committing your response(by closing the writer), and it should throw exception.

    Servlet 2 : Used getOutputStream and write method (no flush method), followed by forward method. This threw the above stated error.
    Do you use getWriter() in your forwarded servlet. If yes, then you would obviously get this error as you have already called getOutputStream on the response object in the forwarding servlet.

    Servlet 3 : Used just getOutputStream (no write and no flush method), followed by forward method. This threw the above stated error as well.
    Same problem as for Servlet2.
    [ May 20, 2008: Message edited by: Satya Maheshwari ]

    Thanks and Regards
    Satya Maheshwari
    Ranch Hand

    Joined: Jan 01, 2007
    Posts: 368
    As for the original question, doing the following should throw IllegalStateException:

    Call getOutputStream()
    Call write
    Call close -> This commits the response
    Forward

    I do not think we should get an exception if we just 'write' and do not 'close' the output stream and 'forward' to another servlet.
    John Pearson
    Ranch Hand

    Joined: Oct 19, 2007
    Posts: 51
    Interesting question, Ana. I'm guessing that you're forwarding to a JSP. You'll always get an IllegalStateException if you call getOutputStream() in your servlet and then forward to a JSP.

    When the JSP starts up, it initializes a PageContext object which contains the objects referred to by your implicit variables, including out. The implicit variable out refers to a newly created JspWriter. Not a problem (yet), because the JspWriter object is not linked to the response object. At the very end of the JSP processing, it calls releasePageContext(). This is where it finally links the JspWriter to the response object. And guess what it calls? getWriter(). On the same response that you called getOutputStream on back in your servlet. Boom! IllegalStateException.

    If you have a stack trace for the exception, I'll bet you'll see this is where the exception is coming from. This will happen even if your JSP is empty. Forwarding to another servlet shouldn't be a problem, unless, of course, that servlet calls getWriter().

    As to your original question about the correct response, I personally think option D should be included, since it will always cause an IllegalStateException when forwarding to a JSP. But if you're working through HFSJ, you haven't reached the chapters on JSP, so you couldn't possibly know any of this. Which makes this an inherently evil question. No relection on the authors, of course.
    Srinivas Kumar
    Ranch Hand

    Joined: Jul 14, 2005
    Posts: 52
    Huh!! This discussion caused more confusion. I didn't quite get when IllegalStateException will be thrown.

    What do you mean by committing a response exactly? isn't it printWriterObject.println() or outputStreamObject.write()

    --------------------------------------------------------------------------------
    Servlet 1 : Used getWriter and println method, followed by forward method. This did NOT throw any error.
    This would not throw an error as you have not committed your response. Try calling forward after committing your response(by closing the writer), and it should throw exception.
    --------------------------------------------------------------------------------
    Generally we close the writer in finally statement but before that itself we handle the control to another servlet.So I felt that, in this case, after println followed by forward method should throw the exception, but as per the above statement it didn't throw exception. Can somebody explain in detail?


    --------------------------------------------------------------------------------
    Servlet 2 : Used getOutputStream and write method (no flush method), followed by forward method. This threw the above stated error.
    Do you use getWriter() in your forwarded servlet. If yes, then you would obviously get this error as you have already called getOutputStream on the response object in the forwarding servlet.
    --------------------------------------------------------------------------------
    Based on my understanding in the first case, it should throw exception in this case as forward method is invoked after write method. In this case again, by write method I assume that response committed and hence the exception.

    --------------------------------------------------------------------------------
    Servlet 3 : Used just getOutputStream (no write and no flush method), followed by forward method. This threw the above stated error as well.
    --------------------------------------------------------------------------------
    As per my understanding, just getting an OutputStream object does not necessarily mean committing the response, then why did we get exception in this case? Moreover, no write method and no flush method used before forwarding to the servlet. please explain
    Jan Sterk
    Ranch Hand

    Joined: Jun 06, 2008
    Posts: 139
    The question is: ..often lead to..

    If you write, you should also flush, otherwise the writing doesn't make sense, so C is correct. But I agree that the same accounts for D.


    SCJP 1.4 (81%)<br />SCWCD 5 (95%)
    Satya Maheshwari
    Ranch Hand

    Joined: Jan 01, 2007
    Posts: 368
    @Srinivas Kumar
    What do you mean by committing a response exactly? isn't it printWriterObject.println() or outputStreamObject.write()


    A response is said to be committed when you cannot roll it back and send some other response instead. A good example for this would be writing something to the writer and then doing response.sendError. If you have commited the response (by calling 'close'), then whatever has been written will be shown, otherwise if the response has not yet been committed, the specified response error will be shown.

    Generally we close the writer in finally statement but before that itself we handle the control to another servlet.So I felt that, in this case, after println followed by forward method should throw the exception, but as per the above statement it didn't throw exception. Can somebody explain in detail?

    If you immediately do a 'forward' after writing something to response and do not commit, there are 2 cases.
    Case1: You continue to use 'writer' or 'ServletOutputStream' in the forwarded servlet. Here, there will not be any exception.

    Case2: You try to use 'writer' or 'ServletOutputStream' in the forwarded servlet while your initial servlet was using 'ServletOutputStream' or 'writer' respectively. Here, there will an exception.

    Based on my understanding in the first case, it should throw exception in this case as forward method is invoked after write method. In this case again, by write method I assume that response committed and hence the exception

    You are correct in saying that an exception would be thrown but the reason you think is wrong. Just calling 'write' does not commit the response. The reason for exception here is that you use 'writer' in your initial servlet and 'ServletOutputStream' in the forwarded servlet.

    As per my understanding, just getting an OutputStream object does not necessarily mean committing the response, then why did we get exception in this case? Moreover, no write method and no flush method used before forwarding to the servlet. please explain

    Correct, the response was not committed. The exception happened because we tried to use OutputStream in the initial servlet and 'writer' in the 'forwarded' servlet.
    Anand Bhatt
    Ranch Hand

    Joined: May 30, 2007
    Posts: 189
    from mu knowledge only option "B. flush" is correct.as flush is the only method responsible for writing the respose . all others method are temp.
    Satya Maheshwari
    Ranch Hand

    Joined: Jan 01, 2007
    Posts: 368
    If you see the question, it has the word 'often'. Maybe this is the reason, 'C' is also marked as correct.
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: Doubt on RequestDispatcher
     
    Similar Threads
    HF SCJP mock exam question: flush() vs. write()
    HF SCJP mock exam question: flush() vs. write()
    RequestDispatcher
    RequestDispatcher.forward()
    Regarding request disptacher