The Java EE 5 Tutorial

Tag Handlers for Tags That Define Variables

Similar communication mechanisms exist for communication between JSP page and tag handlers as for JSP pages and tag files.

To emulate IN parameters, use tag attributes. A tag attribute is communicated between the calling page and the tag handler when the tag is invoked. No further communication occurs between the calling page and the tag handler.

To emulate OUT or nested parameters, use variables with availability AT_BEGIN, AT_END, or NESTED. The variable is not initialized by the calling page but instead is set by the tag handler.

For AT_BEGIN availability, the variable is available in the calling page from the start tag until the scope of any enclosing tag. If there’s no enclosing tag, then the variable is available to the end of the page. For AT_END availability, the variable is available in the calling page after the end tag until the scope of any enclosing tag. If there’s no enclosing tag, then the variable is available to the end of the page. For nested parameters, the variable is available in the calling page between the start tag and the end tag.

When you develop a tag handler you are responsible for creating and setting the object referenced by the variable into a context that is accessible from the page. You do this by using the JspContext().setAttribute(name, value) or JspContext.setAttribute(name,value,scope) method. You retrieve the page context using the getJspContext method of SimpleTag.

Typically, an attribute passed to the custom tag specifies the name of the variable and the value of the variable is dependent on another attribute. For example, the iterator tag introduced in Chapter 5, JavaServer Pages Technology retrieves the name of the variable from the var attribute and determines the value of the variable from a computation performed on the group attribute.

public void doTag() throws JspException, IOException {
    if (iterator == null)
        return;
    while (iterator.hasNext()) {
        getJspContext().setAttribute(var, iterator.next());
        getJspBody().invoke(null);
    }
}
public void setVar(String var) {
    this.var = var;
}
public void setGroup(Collection group) {
    this.group = group;
    if(group.size() > 0)
        iterator = group.iterator();
}

The scope that a variable can have is summarized in Table 8–13. The scope constrains the accessibility and lifetime of the object.

Table 8–13 Scope of Objects

Name 

Accessible From 

Lifetime 

page

Current page 

Until the response has been sent back to the user or the request is passed to a new page 

request

Current page and any included or forwarded pages 

Until the response has been sent back to the user 

session

Current request and any subsequent request from the same browser (subject to session lifetime) 

The life of the user’s session 

application

Current and any future request in the same web application 

The life of the application 

TagExtraInfo Class

Declaring Tag Variables for Tag Handlers discussed how to provide information about tag variables in the tag library descriptor. This section describes another approach: defining a tag extra info class. You define a tag extra info class by extending the class javax.servlet.jsp.tagext.TagExtraInfo. A TagExtraInfo must implement the getVariableInfo method to return an array of VariableInfo objects containing the following information:

The web container passes a parameter of type javax.servlet.jsp.tagext.TagData to the getVariableInfo method, which contains attribute-value tuples for each of the tag’s attributes. These attributes can be used to provide the VariableInfo object with an EL variable’s name and class.

The following example demonstrates how to provide information about the variable created by the iterator tag in a tag extra info class. Because the name (var) and class (type) of the variable are passed in as tag attributes, they can be retrieved using the data.getAttributeString method and can be used to fill in the VariableInfo constructor. To allow the variable var to be used only within the tag body, you set the scope of the object to NESTED.

package iterator;
public class IteratorTEI extends TagExtraInfo {
    public VariableInfo[] getVariableInfo(TagData data) {
        String type = data.getAttributeString("type");
        if (type == null)
            type = "java.lang.Object";
        return new VariableInfo[] {
            new VariableInfo(data.getAttributeString("var"),
            type,
            true,
            VariableInfo.NESTED)
        };
    }
}

The fully qualified name of the tag extra info class defined for an EL variable must be declared in the TLD in the tei-class subelement of the tag element. Thus, the tei-class element for IteratorTei would be as follows:

<tei-class>
    iterator.IteratorTEI
</tei-class>