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.
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.
*** Bug 16031 has been marked as a duplicate of this bug. ***
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
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.
*** Bug 16071 has been marked as a duplicate of this bug. ***
Created attachment 4464 [details] A war containing an example of the scenario in which the bug is exposed
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.
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
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.
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 ?
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.
*** Bug 16171 has been marked as a duplicate of this bug. ***
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.
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.
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.
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".
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!
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
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 :)
*** Bug 17130 has been marked as a duplicate of this bug. ***
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; }
*** Bug 18349 has been marked as a duplicate of this bug. ***
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?
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
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.
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
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.
Yep, you are right. I guess we're left with turning tag pooling off. Many thanks!
*** Bug 26527 has been marked as a duplicate of this bug. ***
*** Bug 32957 has been marked as a duplicate of this bug. ***
*** Bug 34986 has been marked as a duplicate of this bug. ***