Bug 16001 - Tag.release() not invoked
Summary: Tag.release() not invoked
Status: RESOLVED INVALID
Alias: None
Product: Tomcat 4
Classification: Unclassified
Component: Jasper 2 (show other bugs)
Version: 4.1.12
Hardware: PC other
: P3 critical (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
: 16031 16071 16171 17130 18349 26527 32957 34986 (view as bug list)
Depends on:
Blocks:
 
Reported: 2003-01-12 06:43 UTC by Chunsheng Chen
Modified: 2005-05-23 04:34 UTC (History)
11 users (show)



Attachments
A war containing an example of the scenario in which the bug is exposed (3.69 KB, application/octet-stream)
2003-01-16 16:13 UTC, Fabio Ambrosanio
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Chunsheng Chen 2003-01-12 06:43:02 UTC
I have a simple jsp page with a customer tag. During jsp execution, the release 
method of the tag did not get invoked, which conflicts with J2EE spec.
Comment 1 william.barker 2003-01-12 07:37:36 UTC
The JSP spec requires that the release method is called before the tag is 
allowed to pass to GC.  With the default settings to enable tag-pooling, the 
tag is returned to the pool, so the release method can't be called. 

To get the behavior that you want, disable tag-pooling in 
$CATALINA_HOME/conf/web.xml.  
Comment 2 william.barker 2003-01-13 18:40:34 UTC
*** Bug 16031 has been marked as a duplicate of this bug. ***
Comment 3 Jan Luehe 2003-01-13 18:52:53 UTC
The following is regarding bug 16031:

I assume you are referring to the tag handler's release() method when you talk
about resetting its state?

Note that according to the spec, the release() method is guaranteed to
be called on any tag handler, "but there may be multiple invocations
on doStartTag() and doEndTag() in between."

Therefore, your tag handler should not rely on its release() method to
reset any private invocation-specific state. This state is best
initialized in doStartTag(). This means that in your specific example, you
should clear your "key" and "value" objects in your tag handler's doStartTag()
method.

See important tips for tag-handler lifecycle management at

 http://jakarta.apache.org/taglibs/guidelines.html


Comment 4 Chunsheng Chen 2003-01-13 19:42:40 UTC
According to the spec, the release() method is guaranteed to be called on any 
tag handler, this is to say, even when the tag handler instance is pooled, it 
still should invoke release() to release any state the tag handler may posess.

In my case, I have a tag handler super class that needs to get a state value 
from session and set it for the child class to construct business view object. 
I agree that it is feasible to clean it up in doStartTag() since my tag is not 
an iteration tag. But still it would be ideal to use release() to clean up 
private invocation-specific state.
Comment 5 william.barker 2003-01-14 18:08:18 UTC
*** Bug 16071 has been marked as a duplicate of this bug. ***
Comment 6 Fabio Ambrosanio 2003-01-16 16:13:59 UTC
Created attachment 4464 [details]
A war containing an example of the scenario in which the bug is exposed
Comment 7 Fabio Ambrosanio 2003-01-16 16:25:16 UTC
I think that Tag.release is not invoked between two uses of the same tag, now
that it is extracted from the pool.

If the tag store a value in an internal variable, depending on a required
attribute, you'll find the previuos value in the next use even if you set it to
null in release.

I don't know if the life-cycle model of custom tags is changed in last
specifications, but I expect to have a clean instance of the object every time I
use it, especially if I've implemented release.

I've posted an attachment containing a small war with a simple tag and a page of
example. Try it. 
Comment 8 Ismael Blesa 2003-01-16 16:42:36 UTC
You cannot put it to null. You have to make a call to removeValue(). Really you
SHOULD NOT do this, because we think that has to be done automatically :P
Comment 9 Martin Algesten 2003-01-16 16:55:19 UTC
Lets see if I can get through to you guys, Jan Luehe's fine post was 
apparently not enough.

From the Tag.release() javadoc:
"...there may be multiple invocations on doStartTag and doEndTag in between."

This is plain english and means that on the same page the tag can be taken out 
of the pool, and then used several times _WITHOUT_ .release() being called in 
between AND THIS IS NOT A BUG. Ergo, Tag.release can NOT be used for resetting 
states between uses of tags.

If you need to reset your internal values that SHOULD be done in doEndTag for 
instance.
Comment 10 Ismael Blesa 2003-01-16 17:23:10 UTC
I think that from a progammers view :

The programmers should not care about how internal things are done. That is, if
tomcat uses pools of objects for performance improvements or any other approach,
programmer should not care about it, it should only use a tag and if later it is
reused, asume a initial state.



Should not be this the right approach as done on other servers ?
Comment 11 Martin Algesten 2003-01-16 17:41:12 UTC
As with any API, the programmer is supposed to understand how it works. I 
didn't write the spec, but it is pretty obvious to me that it is working as 
intended.
Comment 12 william.barker 2003-01-16 18:21:32 UTC
*** Bug 16171 has been marked as a duplicate of this bug. ***
Comment 13 Ismael Blesa 2003-01-17 08:13:31 UTC
As I understand the api, it does not talk about custom tag pools, it only speaks
about tags, if you use a pool, it should be transparent.

And in other servers it works as we think it should work.
Comment 14 Remy Maucherat 2003-01-17 14:19:03 UTC
Your tag does not comply with the JSP specification, and, as a result it may or
may not work. This issue WILL NOT be fixed in Tomcat.
Thanks, and DO NOT REOPEN THIS BUG.
Comment 15 Richard Backhouse 2003-01-17 14:37:46 UTC
Ismael,

Please take a look at section 10.5 in the 1.2 spec and section 12.4 in the 2.0
spec :

"Below is a somewhat complete example of the way one JSP container could
choose to do some tag handler management. There are many other strategies that
could be followed, with different pay offs.
The example is as below. In this example, we are assuming that x:iterate is an
iterative tag, while x:doit and x:foobar are simple tag. We will also assume that
x:iterate and x:foobar implement the TryCatchFinally interface, while x:doit does
not.
<x:iterate src=“foo”>
<x:doit att1=“one” att2=“<%= 1 + 1 %>” />
<x:foobar />
<x:doit att1=“one” att2=“<%= 2 + 2 %>” />
</x:iterate>
<x:doit att1=“one” att2=“<%= 3 + 3 %>” />
The particular code shown below assumes there is some pool of tag handlers
that are managed (details not described, although pool managing is simpler when
there are no optional attributes), and attemps to reuse tag handlers if
possible. The
code also “hoists” setting of properties to reduce the cost when appropriate, e.g.
inside an iteration."

As you can see pooling IS Mentioned. If you take a look at the example code that
follows this section you will see that release() is NOT called between tag
invocations. 

The only thing that the spec says has to happen is that release() is called
before the tag is gc'd. This could potentialy only occur when an webcontainer is
shutdown. 

I would suggest you take a look at a custom tag library like struts that
demontrates how custom tags should cleanup when used in a pooled environment. 
Comment 16 Martin Algesten 2003-01-17 15:29:06 UTC
Consider reading the rest of the spec as well...
Yes tags are meant to be pooled. However .release() is NOT intended to be 
called between reuses of a tag... as the javadoc clearly states.

Even the name "release" tells us that this is not a "reinit".
Comment 17 Fabio Ambrosanio 2003-01-17 16:39:44 UTC
Ok guys. You're right.

I found the book (about JSP 1.1) in which a flow-chart of the life-cycle of a
tag has driven me in error.

More, there are some JSP engine (such as Weblogic that has implemented the pool
before Tomcat) where release is invoke just after the return of doEndTag, even
if specification says different.

But specs rule!

Comment 18 Martin van den Bemt 2003-01-17 19:43:01 UTC
A note from Hans Bergsten, for reference.

I'm in the EG and we had a long discussion about this again for JSP 2.0.
The end result is that the current behavior (do _not_ call release()
between invocations) will stay. A confusing arrow from the "released"
state to the "initialized" state in the state diagram will be removed,
however. This state transition came with lots and lots of restrictions,
but it seems like some vendor (and developers) saw it as a requirement
to call release() between invocations, even though the text clearly
state that that's not the case.

This is being discussed pretty much everywhere these days and I hope
people eventually will get it. I wrote about it in an article just
after JSP 1.2 was released. Feel free to point people to it if you
get tired of rehashing the same arguments over and over ;-)

  <http://www.onjava.com/pub/a/onjava/2001/11/07/jsp12.html>
  Page 2, the "Tag handler life cycle and instance reuse" section
Comment 19 Ismael Blesa 2003-01-20 08:35:05 UTC
Ok, thank you for your responses, I misinterpretted the specification. But I was
confused because on previous version of tomcat (4.1.12 I think) it seemed to
work as I thought it should work. I also tested on another servers and I got the
same behaviour. 

Sorry, next time I will reread the specification before posting :)
Comment 20 John Trollinger 2003-02-17 15:55:28 UTC
*** Bug 17130 has been marked as a duplicate of this bug. ***
Comment 21 Vicente Salvador 2003-02-17 20:23:00 UTC
OK guys, release() method is NOT guaranteed to be called on any tag handler, so
..there may be multiple invocations on doStartTag and doEndTag in between.

But programmers needs a method to initialize the tag between uses. Initializing
it at doStartTag method is not OK because setters are called before doStartTag
so programmer could clear the setted variables.

We need a method to initialize the tag before it's called, Maybe changing the
get method get() at TagHandlerPool.java

If not, please great gurus, how can we use tag pooling without this
initialization issues. JSP spec is not clear about this!

    public synchronized Tag get(Class handlerClass) throws JspException {
        Tag handler = null;
    
        if (current >= 0) {
            handler = handlers[current--];
     
// If handler is already in the cache release it
// It cannot be done at startTag not at EndTag because closed tags can
// return a java object
            handler.release();
        } else {
            try {
                return (Tag) handlerClass.newInstance();
            } catch (Exception e) {
                throw new JspException(e.getMessage(), e);
            }
        }

        return handler;
    }
Comment 22 william.barker 2003-03-25 23:33:24 UTC
*** Bug 18349 has been marked as a duplicate of this bug. ***
Comment 23 Chris 2003-03-26 18:03:00 UTC
I agree that initializing variables in doStartTag() doesn't make sense, since 
the property sets are already called BEFORE doStartTag() according to the 
spec.  So, where does this leave the programmers a place to re-initialize the 
veriables (most importantly the optional custom tag variables).  I figure that 
doAfterBody() is no good because it is called multiple times for BodyTag 
handlers.  So, the only place left is to override setPageContext() and have it 
call super.setPageContext() AND release().  

This is obviously a hack and doesn't seem like a good answer, but I don't see 
any other choice.  Is there one?

Comment 24 Hans Bergsten 2003-03-26 18:33:39 UTC
If you look through the comments for this "bug", the solution is defined by the
JSP spec: a tag handler instance can _not_ be reused for occurances of the
corresponding custom action that specify different optional attributes. Hence,
there's no risk that a tag handler that has been used with an optional attribute
is   later used without that optional attribute. See this article for details:

 <http://www.onjava.com/pub/a/onjava/2001/11/07/jsp12.html>
  Page 2, the "Tag handler life cycle and instance reuse" section
Comment 25 Angus Mezick 2003-05-21 13:32:38 UTC
Chris,
#  doFinally() *is* always called for tag handlers that implement
TryCatchFinally, so this method should be used if any invocation- specific
resources need to be released

You could try using this to clear variables.
Comment 26 Pawel Zieminski 2003-08-19 02:16:34 UTC
According to the JSP 1.1 Errata published on 5/31/00
(http://java.sun.com/products/jsp/errata_1_1_a_042800.html see under "Issue 14")
the behavior exhibited by Jasper (regarding tag pooling) is not in accordance
with the specification for JSP 1.1. The errata recognizes the shortcoming of the
original spec, which did not provide any mechanism for clearing the tag
handler’s state between uses, and it states that tag instances cannot be reused
if they don't correspond to actions with the same attributes, unless release()
is called between uses. 

So, the same instance of the handler can be used for
<x:foo att1="one" att2="two"/>
<x:foo att1="HELLO" att2="BYE"/>
but for 
<x:foo att1="one" att2="two"/>
<x:foo att1="HELLO"/>
you either have to use different instances, or you have to call release() before
second use.

I would assume the same applies for JSP 1.2, unless the specification explicitly
states otherwise.

The errata is there for everyone to see right along side of the original final
specification 
http://java.sun.com/products/jsp/download.html#specs
Comment 27 william.barker 2003-08-19 04:42:44 UTC
It's true that the 1.1 errata was included in the 1.2 Spec.  However, it's not 
relevent to this report.  Jasper will use seperate instances of the "foo" tag 
handler, which you've already agreed is valid.
Comment 28 Pawel Zieminski 2003-08-19 17:25:10 UTC
Yep, you are right. I guess we're left with turning tag pooling off. 
Many thanks!
Comment 29 Tim Funk 2004-01-29 16:53:30 UTC
*** Bug 26527 has been marked as a duplicate of this bug. ***
Comment 30 Tim Funk 2005-01-06 00:39:56 UTC
*** Bug 32957 has been marked as a duplicate of this bug. ***
Comment 31 Martin Weber 2005-05-23 12:34:06 UTC
*** Bug 34986 has been marked as a duplicate of this bug. ***