Thursday, April 28, 2011

Chapter 45: Custom Tags

In the previous chapter, we saw what Tag Libraries are and how to use them. In this chapter, we are going to see how to create and use Custom Tags.

So, lets get started!!!

What is a Custom Tag?

The custom tag is a convention that allows you to have the container call the tag library life cycle event methods (for example, doStartTag), including the attribute get/set calls automatically invoked when attributes are declared in the custom tag. doStartTag and doEndTag methods are called when the JSP page request is processed.

Ex:
< tagHandlerPrefix:customTagName / >

The above is a simple custom tag with no tag body.

Ways to use Custom Tags:


There are 4 ways of using Custom tags. They are:

1. < libraryPrefix : handlerName />
The custom tag with no body, said to be an empty custom tag.

2. < libraryPrefix : handlerName parameterName="value" >
This tag causes the container to call the setParameterName method and pass the “value” to it.

3. < libraryPrefix : handlerName parameterName="value" >
< % = 23 * counter % >
< b > Congratulations ! < / b >
< / libraryPrefix : handlerName >
A custom tag with a body. The body can contain core tags, scripting elements, HTML text, and tag-dependent body content between the start and end tags.

4. < library : outerTag >
< library : innerTag >
< / library : innerTag > < / library : outerTag >
This syntax is how you nest custom tags. The XML is easy, but the handler is more involved. Note that the following is wrong: .


Attributes of a Custom Tag:

A custom tag has many attributes. They are:

1. name – This element is the name of the attribute in a tag.
Ex: < name > attribName < / name >

2. required – This optional element tells the container whether you must specify a value for this attribute when you use the custom tag in a JSP Page.
Ex: < required > true | false < / required>

3. rtexprvalue = This element tells the container whether the attribute can take a scriptlet expression as a value
Ex: < rtexprvalue > true | false < / rtexprvalue>


Custom Tag Body

A Custom Tag can also contain stuff in its body. It is specified in the bodycontext TLD element. It can be of 3 types:

1. Empty
Ex: < bodycontent > empty < / bodycontent > will be the bodycontext tag for the below tag library
< tagLibrary : myTag firstName="Anand" lastName="Vijayakumar" ... / >

2. Custom Tag that surrounds other JSP Code
Ex: < bodycontent > JSP < / bodycontent > will be the bodycontext tag for the below tag library
< tagLibrary : myTag > < % = 23 * counter % > < / tagLibrary : myTag >

3. Custom tag that surrounds contents that is used only by the tag handler.
Ex: < bodycontent > tagdependent < / bodycontent > will be the bodycontext tag for the below tag library
< tagLibrary : myTag > SELECT * FROM STUDENT < / tagLibrary : myTag >

The empty (tag has no body) and JSP options (default and interpreted if present) are straightforward. The tagdependent option is a bit different. This means the text is sent to the tag handler, but the text is not sent to the output stream, unless the tag prints it to the stream.

Tag Event Methods

There are various events that are associates with tags and we have methods that help us catch and handle them.

Basically, this part covers the event methods that the container triggers when processing your custom tags along with these method return constants. There are only four methods that you have to study and a few constants.

The various Events of a Custom Tag are:

1. EVAL_BODY_INCLUDE – Evaluate body into existing output stream
2. EVAL_BODY_AGAIN – Evaluate body again
3. EVAL_PAGE – Continue Evaluating the Page
4. SKIP_BODY – Skip body Evaluation. Stop processing the JSP after the current custom tag
5. SKIP_PAGE – Stop processing the JSP after the current custom tag.

Each of these actions have a corresponding method that will get invoked:

1. EVAL_BODY_INCLUDE – doStartTag()
2. EVAL_BODY_AGAIN – doAfterBody()
3. EVAL_PAGE – doEndTag()
4. SKIP_BODY – doStartTag(), doAfterBody()
5. SKIP_PAGE – doEndTag()


Let us now look at what each of these methods is supposed to do.

1. doStartTag() - This method is called when the container first starts to process the tag. Notice that when this method is invoked, the body has not yet been evaluated. It can return either the EVAL_BODY_INCLUDE or SKIP_BODY field.
2. doEndTag() - This method is called after the container completes the doStartTag() method. Notice that the body of your custom tag may not have been evaluated, depending on the return value of doStartTag(). It can return either the EVAL_PAGE or SKIP_PAGE field.
3. doAfterBody() - This method is used for iterations (IterationTag). It is called after every body evaluation to control whether the body will be reevaluated or not. If this method returns EVAL_BODY_AGAIN, the body will be reevaluated. If it returns SKIP_BODY, the body will be skipped and doEndTag() will be invoked next.

Custom Tag Handler Methods

If you want to write a custom tag handler that can handle your custom tags, you need to be able to access the varios JSP Implicit Objects and attributes of the JSP Page. Below are the various methods that you can use to do the same:

You can get the implicit objects with the following methods:
getOut()- This method returns the current JspWriter stream being used for the client response.
getException()- This method returns any exception passed to this as an error page.
getPage()- This method returns the page implementation class instance (Servlet) associated with this JSP page request. Notice that the PageContext object encapsulates that state of a request upon a JSP page.
getRequest()- This method returns the ServletRequest for this JSP page request.
getResponse()- This method returns the ServletResponse for this JSP page request.
getSession()- This method returns the HttpSession for this JSP page request or null.
getServletConfig()- This method returns the ServletConfig for this JSP page request.
getServletContext()- This method returns the ServletContext for this JSP page request.

The following methods are used to access the attributes in your tag handler for a given JSP page:
setAttribute() - This method registers the name and object specified with appropriate scope semantics.
getAttribute() - This method returns the object associated with the name in the page scope or null if not found.
findAttribute() - This method searches for the named attribute in the page, request, session (if valid), and application scope(s) respectively and returns the associated value or null.
removeAttribute() - This method removes the object reference associated with the given name by looking in all scopes in the scope order.

The following methods provide support for forwarding, inclusion, and error:
forward() - This method is used to redirect, or “forward” the current ServletRequest and ServletResponse to another active component in the application. The URL is assumed to be a relative URL; however, if the path begins with a /,the URL specified is calculated relative to the DOCROOT of the ServletContext for this JSP. Be careful, as once this method has been called successfully, it is illegal for the calling thread to attempt to modify the ServletResponse object. You cannot generate further output to the browser once the forward() method has been called.
include() - This method causes the specified resource to be processed as part of the current ServletRequest and ServletResponse being processed by the calling thread. The output of the target resource's processing of the request is written directly to the ServletResponse output stream. Notice that the current JspWriter (out) for this JSP is flushed as a side effect of this call, prior to processing the include.

Using Outer-Inner Custom Tags

As mentioned at the beginning of the previous chapter, you can also nest custom tags. When you do that, you need to be able to access one tag from another. The following methods are most helpful when trying to reach another tag from an inner tag:
getParent()- This method finds the parent (closest enclosing tag handler) for this tag handler. You might do this to navigate the nested tag handler structure at runtime.
findAncestorWithClass()- This method finds the instance of a given class type. This method uses the getParent() method from the tag interface.


An Example Tag Handler:

To wrap up custom tags, lets take a look at a simple Abstract Tag Handler that gets shipped with tomcat.

package examples;

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

public abstract class ExampleTagBase
extends BodyTagSupport
{
public void setParent(Tag parent)
{
this.parent = parent;
}

public void setBodyContent(BodyContent bodyOut)
{
this.bodyOut = bodyOut;
}

public void setPageContext(PageContext pageContext)
{
this.pageContext = pageContext;
}

public Tag getParent()
{
return this.parent;
}

public int doStartTag() throws JspException
{
return SKIP_BODY;
}

public int doEndTag() throws JspException
{
return EVAL_PAGE;
}


// Default implementations for BodyTag methods,
// just in case a tag decides to implement BodyTag.
public void doInitBody() throws JspException
{
}

public int doAfterBody() throws JspException
{
return SKIP_BODY;
}

public void release()
{
bodyOut = null;
pageContext = null;
parent = null;
}

protected BodyContent bodyOut;
protected PageContext pageContext;
protected Tag parent;
}

Previous Chapter: Chapter 44 - JSP Tag Libraries

Next Chapter: Quick Recap - Chapters 44 & 45

No comments:

Post a Comment

© 2013 by www.inheritingjava.blogspot.com. All rights reserved. No part of this blog or its contents may be reproduced or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without prior written permission of the Author.

ShareThis

Google+ Followers

Followers