Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSP tag lifecycle

I just introduced a bug into my code because I seem to have misunderstood the jsp tag lifecycle.

The tag worked like this before the bug: I pass the tag some collection as an attribute, and it displays it as a table. The collection was passed into the JSP from the controller.

After the bug: I removed the attribute which set the collection. Instead, in the tag I check if the collection is null, and then grab it by name from the request (using a naming convention).

The thing that I didn't expect: after the collection was initially set in the tag, it would never become null on subsequent executions! It was still defined as a non-requred attribute in the TLD.

I expected the tag to not hold on to previous values between executions.

like image 605
mkoryak Avatar asked Mar 05 '09 18:03

mkoryak


2 Answers

You answered the question yourself - it's pooled. See the tag tutorial for what to implement in java implementations, together with the page linked from there, containing the invocation sequence:

ATag t = new ATag();
t.setPageContext(...);
t.setParent(...);
t.setAttribute1(value1);
t.setAttribute2(value2);
t.doStartTag();
t.doEndTag();
t.release();

That is, re-initialize your tag instance in doEndTag() as the API requires. (changed as of comment by Julien Kronegg, thanks)

Note that pooling probably is container dependent, but well legal (and, due to the API setup, probably done everywhere).

like image 163
Olaf Kock Avatar answered Oct 12 '22 11:10

Olaf Kock


The short answer: You are not supposed to write to attribute properties yourself. By doing so, you make cleaning the state your responsibility.

For a longer answer, the JSP 2.0 Spec dictates the following (page 2-51):

  • Setters get called for all specified attributes of a specific occurrence of a tag
  • Setters are not called for omitted attributes (leaving default values intact and, in your case, an illegal value in the internal state)
  • Tag handlers may only be reused by occurrences with the same set of specified attributes

These three points together guarantee that attribute properties are always correctly initialized, while still retaining default values (defined in a constructor or a properties' declaration). In return, it only works on the assumption that only the container manipulates attribute properties (by calling the setters).

For the sake of completeness:

  • release() should not be used to reset internal state between calls of a tag handler. It is only guaranteed to be called before GC and should be used to free long-term resources.
  • If you want to initialize instance variables in doStartTag(), be careful not to overwrite attributes, because the setters have already been called by the container at this point.
  • doEndTag() should be safe to use for initialization because tags should never be reused in case of an exception (see page 2-54 [2])
like image 25
user196621 Avatar answered Oct 12 '22 09:10

user196621