This week's book giveaway is in the OCAJP forum.
We're giving away four copies of Programmer's Guide to Java SE 8 Oracle Certified Associate (OCA) and have Khalid A Mughal & Rolf W Rasmussen on-line!
See this thread for details.
Win a copy of Programmer's Guide to Java SE 8 Oracle Certified Associate (OCA) this week in the OCAJP forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

EVAL_BODY_BUFFERED question

 
Christophe Verré
Sheriff
Posts: 14691
16
Eclipse IDE Ubuntu VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


1. When returning EVAL_BODY_INCLUDE in doStartTag(),
"IN doAfterBody()" will be output in both the log file and the browser.


2. When returning EVAL_BODY_BUFFERED in doStartTag(),
"IN doAfterBody()" will be output only in the log file.

3. In doEndTag(), out.println(body.getString()); will actually print "IN doAfterBody()".
So the outstream (pageContext.getOut()) I used in doAfterBody was actually the bodyContent buffer.

I'm getting confused about this buffer thing. Could anybody explain ?

getPreviousOut() seems to have something to do with this.
Or even getEnclosingWriter().
I don't understand how to use them. If anybody could explain.

[ December 22, 2005: Message edited by: Satou kurinosuke ]
[ December 22, 2005: Message edited by: Satou kurinosuke ]
 
Charles Lyons
Author
Ranch Hand
Posts: 836
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It would have helped if you had provided the complete handler implementation code, and not just the doAfterBody() method, but I think I've guessed correctly what you mean...

The buffer is a BodyContent instance. When using the buffer (signalled by returning EVAL_BODY_BUFFERED from doStartTag()), the first thing the container does is invoke the pageContext.pushBody() method, which causes the current 'out' Writer (perhaps of the parent buffered BodyTag or of the JSP page itself if there is no parent buffered BodyTag) to be stored on the stack, and a new BodyContent to be returned. The push/pop stack facility is used to provide Writers distinct from the actual response stream which can be used to control the flow of content to the response.

Now, recall that for content of a buffered BodyTag to be written to the response, you need to explicitly write it using methods on BodyContent (such as writeOut(getEnclosingWriter()) which will write the entire contents to the parent's BodyContent or 'out' if there is no parent BodyContent).

1. In your code, if you return EVAL_BODY_INCLUDE from doStartTag(), then by the time you get to doAfterBody(), no BodyContent buffer exists in your handler (because you didn't return EVAL_BODY_BUFFERED). Hence, the 'out' object is the actual page's JspWriter (or the BodyContent of a parent tag which has been invoked). So, calling out.println(...) will write the contents directly to the JspWriter for the page, which is in turn written to the response (and shown in the browser).

2. If you return EVAL_BODY_BUFFERED from doStartTag(), the BodyContent buffer is initialised by calling PageContext.pushBody(). The new 'out' object returned by getOut() is the BodyContent buffer and NOT the original JspWriter for the page. So, now invoking out.println(...) writes to the BodyContent for the tag and not directly to the JspWriter for the page. BUT, since you never write the contents of the BodyContent explicitly to the page, this will never be written to the page or the response stream, so it is lost forever (which is why it appears only in the logs).

3. Now, assuming the buffer was initialised (in the 'body' variable), invoking body.getString() returns the String contents of the BodyContent buffer. You then write that explicitly to an output stream, thus flushing the buffer (containing the data you wrote in doAfterBody()) into another stream. What you haven't specified is where the 'out' variable here points to - is it the System.out or the pageContext.getOut()? I assume it is System.out, since pageContext.getOut() actually still refers to the BodyContent buffer - writing the buffer into itself isn't the best thing to do (and won't give you any output).

BodyContent.getEnclosingWriter() returns the parent JspWriter - either the parent buffered BodyTag's BodyContent, or the page's JspWriter. BodyTagSupport.getPreviousOut() is synonymous to invoking BodyContent.getEnclosingWriter().


NOTE: I've avoided a discussion of SimpleTags here. A SimpleTag has its own JspFragment buffering mechanism which is distinct from the classic model, and is not actually (and neither does contain) a JspWriter.
[ December 22, 2005: Message edited by: Charles Lyons ]
 
Christophe Verré
Sheriff
Posts: 14691
16
Eclipse IDE Ubuntu VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I did not understand about the 'out' stream being pushed.
Now it's all clear.

Thank you very much for the very detailed explanations.

I wished the explanations in Manning's book were clear like yours
[ December 22, 2005: Message edited by: Satou kurinosuke ]
 
Charles Lyons
Author
Ranch Hand
Posts: 836
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Satou kurinosuke:
I wished the explanations in Manning's book were clear like yours


Well, I hope my SCWCD book (see my signature) will be available for purchase in January next year, so if you're studying for the SCWCD, I'd be grateful if you'd take a look!
 
Christophe Verré
Sheriff
Posts: 14691
16
Eclipse IDE Ubuntu VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I passed the exam on Saturday !
Wish you good luck for your book.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic