You are viewing a plain text version of this content. The canonical link for it is here.
Posted to taglibs-user@tomcat.apache.org by Craig Longman <cr...@begeek.com> on 2002/09/18 21:26:38 UTC

different EVAL_BODY_XXX return types

i having some complicated problems in the doEndTag() processing that are
primarily related to the bodyContent member.

according to the javadocs, if EVAL_BODY_INCLUDE is returned,
setBodyContent() and doInitBody() are not invoked.  the upshot of this
is that the bodyContent member variable is potentially not configured
for each tag invocation.  the place that this seems to hurt me, is when
i'm using a tag that can return different responses to the doStartTag()
method, sometimes i want to have it simply processed 'inline' with
INCLUDE, sometimes i need to buffer it and process it differently at the
end.

the reason i'm doing this, is i assume it is more efficient to simply
have the contents processed with EVAL_BODY_INCLUDE.  i think it is
streamed back to the client as available, right?  if its buffered, then
nothing can go back until the entire tag is finished (because it isn't
available until the doEndTag() writes it out).

the problem i was having, now that i've figured it out, is that the
bodyContent member was not being set if the EVAL_BODY_INCLUDE value was
used. normally, this is ok, i check for bodyContent==null in
doEndTag().  but sometimes the tag appeared twice in one page, and it
was returning EVAL_BODY_BUFFERED the first time, then EVAL_BODY_INCLUDE
the second time, and then the bodyContent was not reset, which was
causing problems (duplicate output, the contents of the first tag body
would be written again).

question time...
1) is this resetting of bodyContent the responsibility of the
implementing tag?  seeing as the return from doStartTag() doesn't seem
to be included in the AttrSet that decides if a tag can be reused or
not, i guess it is?  (the BodyTagSupport.doStartTag(), but it returns
EVAL_BODY_BUFFERED by default so it can assume that setBodyContent() is
called)
2) is the goal of using EVAL_BODY_INCLUDE when possible an admirable
one?  considering that the included body _might_ be very big, i think it
is, but i'd like confirmation.
3) is returning different values from doStartTag() a
stupid/dangerous/illegal thing to do?

this seems awfully confusing now that i read it over, hopefully it is
manageable, if i need to clarify anything just lemme know.

-- 

    CraigL->Thx();
    Be Developer ID: 5852


Re: different EVAL_BODY_XXX return types

Posted by Craig Longman <cr...@begeek.com>.
On Thu, 2002-09-19 at 22:22, Shawn Bayern wrote:
> On 18 Sep 2002, Craig Longman wrote:
> 
> > 1) is this resetting of bodyContent the responsibility of the
> > implementing tag?  seeing as the return from doStartTag() doesn't seem
> > to be included in the AttrSet that decides if a tag can be reused or
> > not, i guess it is?  (the BodyTagSupport.doStartTag(), but it returns
> > EVAL_BODY_BUFFERED by default so it can assume that setBodyContent()
> > is called)
> 
> Short answer:  yes, the behavior you're describing is consistent with a
> container acting legally.  The tag is responsible for adapting
> appropriately.

k.  it took me a while to figure out HOW to write things back to the
response when there was no bodyContent member to toy with, and was
beginning to think i couldn't.  but eventually i stumbled across
pageContext.getOut()...

> (I should say, just for completeness, that questions like this get
> intricate fast, so it's important to note that what I say extemporaneously
> isn't official or backed up by authoritative word from the JSP expert
> group.)
> 
> > 2) is the goal of using EVAL_BODY_INCLUDE when possible an admirable
> > one?  considering that the included body _might_ be very big, i think it
> > is, but i'd like confirmation.
> 
> Note that the page might be buffered anyway, which obviates your
> stream-to-the-client case.  But in general, yes:  EVAL_BODY_INCLUDE has
> the potential to be more efficient than EVAL_BODY_BUFFERED.  All things
> being equal, it should run more quickly, though of course it's nearly
> impossible to say *how* much quickly without testing.

if the page is buffered, then its likely to be a container limitation
though, right? (assuming i know that no parent tags are buffering). 
either way, i guess there's nothing i can do about it.  i like the
INCLUDE though, the really long pages can start being downloaded before
things are done, which can help when the page is 100-200K and can take a
few seconds to process and the client is on a slow connection.  i'm more
concerned about starting the stream back to the client than i am with
actual performance of writing things out is concerned, although every
nano-second of performance adds up... ;-)

> > 3) is returning different values from doStartTag() a
> > stupid/dangerous/illegal thing to do?
> 
> No, but as the logical conclusion of the issues you've raised, returning
> different codes for different invocations does require additional work on
> your part.  I typically record state in an instance variable that's under
> the control of doStartTag(), as in:
> 
>   doStartTag() {
>     // ...
>     needBody = true;
>     return EVAL_BODY_BUFFERED;
>   }
> 
>   doEndTag() {
>     if (needBody)
>       // ...
>     else
>       // ...
>   }
> 
> Hope that helps,

sure does.  my initial reason for returning different codes was to write
a tag that would output different things at the beginning depending on
what other tags it contained.  so, the first run it would buffer things
and allow the containing tags to voice their requests, a very similar
interface to jstl ParamParentI in fact.  then, it could save the
information off as an attribute for that particular page & tag instance
(although there would normally only be one per page).  for subsequent
runs, the information would be retrieved from the attribute and used
immediately, then the body could be INCLUDED.  however, i cannot figure
out how to determine if a page has been modified and recompiled, so i
think i'm going to have to give that initial idea up, for the time being
at least.

-- 

    CraigL->Thx();
    Be Developer ID: 5852


Re: different EVAL_BODY_XXX return types

Posted by Shawn Bayern <ba...@essentially.net>.
On 18 Sep 2002, Craig Longman wrote:

> 1) is this resetting of bodyContent the responsibility of the
> implementing tag?  seeing as the return from doStartTag() doesn't seem
> to be included in the AttrSet that decides if a tag can be reused or
> not, i guess it is?  (the BodyTagSupport.doStartTag(), but it returns
> EVAL_BODY_BUFFERED by default so it can assume that setBodyContent()
> is called)

Short answer:  yes, the behavior you're describing is consistent with a
container acting legally.  The tag is responsible for adapting
appropriately.

(I should say, just for completeness, that questions like this get
intricate fast, so it's important to note that what I say extemporaneously
isn't official or backed up by authoritative word from the JSP expert
group.)

> 2) is the goal of using EVAL_BODY_INCLUDE when possible an admirable
> one?  considering that the included body _might_ be very big, i think it
> is, but i'd like confirmation.

Note that the page might be buffered anyway, which obviates your
stream-to-the-client case.  But in general, yes:  EVAL_BODY_INCLUDE has
the potential to be more efficient than EVAL_BODY_BUFFERED.  All things
being equal, it should run more quickly, though of course it's nearly
impossible to say *how* much quickly without testing.

> 3) is returning different values from doStartTag() a
> stupid/dangerous/illegal thing to do?

No, but as the logical conclusion of the issues you've raised, returning
different codes for different invocations does require additional work on
your part.  I typically record state in an instance variable that's under
the control of doStartTag(), as in:

  doStartTag() {
    // ...
    needBody = true;
    return EVAL_BODY_BUFFERED;
  }

  doEndTag() {
    if (needBody)
      // ...
    else
      // ...
  }

Hope that helps,

-- 
Shawn Bayern
"JSTL in Action"   http://www.jstlbook.com


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>