Granny's Programming Pearls
"inside of every large program is a small program struggling to get out"
JavaRanch.com/granny.jsp
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Paul Clapham
  • Tim Cooke
  • Devaka Cooray
Sheriffs:
  • Liutauras Vilda
  • paul wheaton
  • Rob Spoor
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Piet Souris
  • Mikalai Zaikin
Bartenders:
  • Carey Brown
  • Roland Mueller

Doubt on RequestDispatcher

 
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
     
    Ranch Hand
    Posts: 64
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    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
    Posts: 24
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    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.
     
    Greenhorn
    Posts: 20
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    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 ]
     
    Greenhorn
    Posts: 20
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    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
     
    Greenhorn
    Posts: 23
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    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.
     
    Ranch Hand
    Posts: 368
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    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 ]
     
    Satya Maheshwari
    Ranch Hand
    Posts: 368
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    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.
     
    Ranch Hand
    Posts: 51
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    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.
     
    Ranch Hand
    Posts: 52
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    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
     
    Ranch Hand
    Posts: 142
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    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.
     
    Satya Maheshwari
    Ranch Hand
    Posts: 368
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    @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.
     
    Ranch Hand
    Posts: 189
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    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
    Posts: 368
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    If you see the question, it has the word 'often'. Maybe this is the reason, 'C' is also marked as correct.
     
    I didn't like the taste of tongue and it didn't like the taste of me. I will now try this tiny ad:
    We need your help - Coderanch server fundraiser
    https://coderanch.com/wiki/782867/Coderanch-server-fundraiser
    reply
      Bookmark Topic Watch Topic
    • New Topic