Win a copy of Murach's Python Programming this week in the Jython/Python forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

getParent() and SimpleTagHandler  RSS feed

 
Vishnu Prakash
Ranch Hand
Posts: 1026
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator



Output:
Tag Nested Level: 0
Attribute Name: vis1

I got three tags. But TagHandler is being called only once. Why is it so.
[ December 20, 2005: Message edited by: Vishnu Prakash ]
 
ramprasad madathil
Ranch Hand
Posts: 489
Eclipse IDE Java Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
got three tags. But TagHandler is being called only once. Why is it so


Do you mean that the tag class is instantiated only once ? Containres are allowed to pool tag objects and hence may create only one instance of the tag per page. Anyways this is very container specific and you neednt be aware of it.

What is guaranteed however, is that, the container would call the predefined life cycle methods on your tag object per each invocation of the tag in the jsp. For example, the doStart(), doEnd() etc are assuredly called per tag invocation and its this lifecycle that you should understand to effectively code tag classes.

cheers,
ram.
 
Vishnu Prakash
Ranch Hand
Posts: 1026
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Containres are allowed to pool tag objects and hence may create only one instance of the tag per page.


What you had said is correct with respect to classic tags. Not with simple tags, which is what my class extends.
 
Charles Lyons
Author
Ranch Hand
Posts: 836
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Vishnu Prakash:

Output:
Tag Nested Level: 0
Attribute Name: vis1

I got three tags. But TagHandler is being called only once. Why is it so.[/QB]



I would expect the output to be:

Tag Nested Level: 0
Attribute Name: vis1
Tag Nested Level: 1
Attribute Name: vis2
Tag Nested Level: 2
Attribute Name: vis3

The reason you are missing the 'vis2' and 'vis3' tags is because you haven't invoked the fragment for the SimpleTag's body. SimpleTags differ from classic tags in so much as their content is wrapped into a JspFragment instance. This allows the tag author to control whether (and how many times) the body is written out. Classic tag's bodies are evaluated by the container, not the tag author, and therefore simply returning EVAL_BODY_INCLUDE from doStartTag() will get the body included. In SimpleTags, you have to explicitly invoke the fragment for yourself.

If you don't invoke the fragment for the 'vis1' tag, the nested tags (and their doTag() methods) will never be executed. So, you need to ammend your code to add this line (e.g. as the last one in the doTag() method):



which invokes the body fragment once and writes its content to the current 'out' object (although you have no tag body content in this example, so here it will be nothing).


I haven't tried this example myself, so let me know if that works and clears up the mystery!

Charles.
 
Vishnu Prakash
Ranch Hand
Posts: 1026
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the response Charles.

Even though I had declared JspException in throws clause If try the code

getJspBody().invoke(null);

at the end of the doTag() method I end up getting JspException.
javax.servlet.ServletException: javax.servlet.jsp.JspException: null

Only after wrapping the statement inside a try/catch block



I get the desired results.
 
Charles Lyons
Author
Ranch Hand
Posts: 836
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Vishnu Prakash:

Even though I had declared JspException in throws clause If try the code

getJspBody().invoke(null);

at the end of the doTag() method I end up getting JspException.
javax.servlet.ServletException: javax.servlet.jsp.JspException: null




Since you declared the method to throw the exception, if the JspException occurs at all, you would expect it to be reported by the container. Catching the exception and writing it to System.out is only masking the fact that it's occuring.

Do you have the full stack trace for the exception report (probably in your server's logs if you've written to System.out)? I can't see why this should be happening...
 
Vishnu Prakash
Ranch Hand
Posts: 1026
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator



root cause

java.lang.NullPointerException
com.example.SimpleTagHandler.doTag(SimpleTagHandler.java:69)


Line number: 69 getJspBody().invoke(null);
[ December 20, 2005: Message edited by: Vishnu Prakash ]
 
Charles Lyons
Author
Ranch Hand
Posts: 836
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Okay, found it. There's a subtle point in both the SimpleTag and BodyTag interfaces' API documentation which states that:

If the action element is empty in the page, this method is not called at all. [SimpleTag]


and

This method will not be invoked for empty tags or for non-empty tags whose doStartTag() method returns SKIP_BODY or EVAL_BODY_INCLUDE. [BodyTag]



Therefore, what you should always do in your SimpleTag (or BodyTag) code, where there is the possibility that the tag is empty, is to first check if the JspFragment (or BodyContent) is null. If so, you've got an empty body so ignore it.

If you modify this line:



into this block:



it should work okay - phew, that was something I had never realised. Generally we either declare actions as EMPTY bodies, in which case we know not to invoke the body fragment, or we use SCRIPTLESS and always have body content... So I suppose I've never thought about this before.
 
Charles Lyons
Author
Ranch Hand
Posts: 836
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry, forgot to mention that those API comments applied to the setJspBody() method of SimpleTag and the setBodyContent() method of BodyTag. The container doesn't set the fragment or BodyContent for an empty tag, that's why it's null when you try to use it later (by invoking getJspBody() or getBodyContent()).
 
Vishnu Prakash
Ranch Hand
Posts: 1026
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the response Charles Lyons.

I got more doubts.

What is a fragment. Is it the body of the tag that invokes setJspBody() method.


If the action element is empty in the page, this method is not called at all.


what is action element?


The container doesn't set the fragment or BodyContent for an empty tag, that's why it's null when you try to use it later (by invoking getJspBody() or getBodyContent()).


I had set <body-content> element as scriptless. The tag is NOT a empty tag and NOT invoked with empty body.



I couldn't understand why setBodyContent(JspFragment) is not being invoked.
 
Charles Lyons
Author
Ranch Hand
Posts: 836
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What is a fragment. Is it the body of the tag that invokes setJspBody() method.


Okay, basic SimpleTag stuff... When the container encounters a tag in the page which is implemented by a SimpleTag (rather than classic Tag) handler, it wraps the body of the tag into a JspFragment instance. This fragment is the unevaluated form of the body content (so it includes code to invoke other actions and evaluate EL/scripting expressions, and not the pre-evaluated textual result of the body). This allows a SimpleTag to repeatedly invoke its body fragment, perhaps during an iteration, and for expressions in the body to change before each iteration - in case scripting variables or other actions change their state/behaviour during the loop.

The setJspBody() method is invoked by the container to set-up the JspFragment for the tag at request-time; this method is called before doTag(), so we can be sure to grab the JspFragment instance when we need it. However, if the tag is empty in the page, there is no body by definition. It is therefore pointless having a JspFragment, because there is no body (fragment) content! So, the container guarantees never to call JspFragment if the tag is empty; hence the fragment is never initialised and getJspBody() returns null.

This is actually only applicable to your 'vis3' tag, which is the only empty one (all others contain the other actions as body content). So this code:



and this code:



are both treated as empty. However, this:



is not empty because there is a space (treated as body content) between the opening and closing tags. The container will therefore create a JspFragment for this tag if it encounters this code.


There are several ways to name a tag: "tag" and "action" are perhaps the most common. Custom tags are also known as "custom actions" and "tag extensions". So, the "action element" the API refers to is just the XML element for the action (tag) in the page.


Using standard tags and creating custom tags, along with tag deployment, are covered fully in my new book, hopefully to be available at the end of January 2006 [just trying to get a promo in there if anyone notices!] It is an exam study guide (for the SCWCD 1.4), but I'm told it's got some good introductory discussions to the newer or more complex topics like EL and tags. Details are in my signature.


Let me know if that clears it up or not,
Charles.
 
Charles Lyons
Author
Ranch Hand
Posts: 836
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry, details of book now in signature...
 
Vishnu Prakash
Ranch Hand
Posts: 1026
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Okay, basic SimpleTag stuff... When the container encounters a tag in the page which is implemented by a SimpleTag (rather than classic Tag) handler, it wraps the body of the tag into a JspFragment instance.


I was aware of this. Hence a fragment is nothing but the body of the tag thats wrapped as JspFragment instance.


(so it includes code to invoke other actions and evaluate EL/scripting expressions, and not the pre-evaluated textual result of the body).


I believe "scripting expressions" as NOT allowed as part of the body of a SimpleTag.


There are several ways to name a tag: "tag" and "action" are perhaps the most common. Custom tags are also known as "custom actions" and "tag extensions". So, the "action element" the API refers to is just the XML element for the action (tag) in the page.


I am pretty new to Tags and I never knew this before. Thank you very much.


Using standard tags and creating custom tags, along with tag deployment, are covered fully in my new book, hopefully to be available at the end of January 2006 [just trying to get a promo in there if anyone notices!]


So you are an author too. I feel privileged to get a authors reply.


It is an exam study guide (for the SCWCD 1.4), but I'm told it's got some good introductory discussions to the newer or more complex topics like EL and tags.


My Humble Request
I highly appreciate if you can make those chapters as sample free E-Chapters

God Bless U
 
Charles Lyons
Author
Ranch Hand
Posts: 836
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Vishnu Prakash:
I believe "scripting expressions" as NOT allowed as part of the body of a SimpleTag


That is correct - sorry, my mistake (I was probably thinking more generally about BodyContent for a BodyTag at the time!)
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!