[ Team LiB ] Previous Section Next Section

Adding Scripting Variables

Your custom tags can define scripting variables that are accessible to your JavaServer Pages. Variables can be declared as part of the TLD as illustrated in Listing 16.12.

Listing 16.12 An Example of How to Declare a Variable in a TLD
<tag>
...
<variable>
<name-given>myVariable</name-given>
<variable-class>String</variable-class>
<declare>true</declare>
<scope>AT_END</scope>
<description>An example variable</description>
</variable>
...
</tag>

In this example <name-given> names the variable and <variable-class> identifies the type. When the <declare> element's value is true, it indicates that the tag is creating a new variable. Otherwise, it's using an existing variable.

The <scope> element defines the lifetime of the variable. A variable is made available for use at different points depending on the declared scope. A scope of AT_BEGIN means that the variable comes into existence with the beginning of the tag. A variable whose scope is AT_END is available after the end tag. Finally, a variable can have a lifetime for the duration between the start and end tags if its scope is NESTED.

You can also comment the variable with the optional <description>.

The tag is responsible for creating and updating an attribute of the same name that is used by the container to set the value of the scripting variable. This is done by simply calling the setAttribute method of pageContext with the name and value of the variable. For example, if you wanted to set the EL variable, var, you would do something like this:


pageContext.setAttribute("var", value);

The container would take care of creating and updating the EL variable. It will also manage the scope of the variable according to the scope defined.

The Difference Between Variables and Attributes

graphics/bytheway_icon.gif

It helps to keep variables and attributes "in their places" as you consider the text. Remember that JSPs have attributes where you can store objects. JSP actions are constructed using XML elements, which also have attributes. In this book we try to distinguish between them by calling them "action element attributes." Variables are programming entities that hold values that may change during execution. Both Java and EL have them. In this hour, we will refer to scripting variables simply as variables and point out when we're talking about other types.


If you want additional flexibility, you can also dynamically name the variable using an action element attribute. Instead of using the <name-given> element in the TLD, you use the <name-from-attribute> element. When you do this, the name of the attribute will be given by the content of the <name-from-attribute> element. For example, if the <tag> element contained a variable declaration that looks like


<name-from-attribute>myName</name-from-attribute>

and the tag appears in a JSP like


<mylib:myTag myName="foo"/>

then the attribute would be named foo. The container will use a set method (as explained in the section "Accessing Tag Attributes") to store the value of the action element attribute locally, and the tag will write the attribute using setAttribute and the value of foo for the name. The following example may help clarify things:


private String myName;
// set method used by container to store the value of the
// action element attribute, myName
public void setMyName(String aName) { myName = aName; }
...
// In one of the appropriate tag methods, set an attribute
// in the page context so that the container can create and
// update the EL variable
pageContext.setAttribute(myName, value);
...

When defining scripting variables, you can also use the TagExtraInfo class. All you need to do is create a special TagExtraInfo class that describes the scripting variables your tag might define.

Listing 16.13 shows a subclass of TagExtraInfo that defines a scripting variable called scriptVar.

Listing 16.13 Source Code for ScriptExtraInfo.java
package examples.taglibs;

import javax.servlet.jsp.tagext.*;

public class ScriptExtraInfo extends TagExtraInfo
{
public VariableInfo[] getVariableInfo(TagData data)
    {
        return new VariableInfo[] {
                new VariableInfo("scriptVar", "java.lang.String",
                true, VariableInfo.AT_END) };
    }
}

VariableInfo is a class that describes a variable. Its constructor's signature includes the name of the variable, its type, whether it is a new variable, and a constant that declares the scope of the variable.

The tag itself doesn't need to know about the extra info class; the container uses it at translation time when it generates the underlying servlet. However, the custom tag needs to put the scripting variables into the page context so that the JavaServer Page can extract the value of each variable and place it in a local Java variable. Listing 16.14 shows a custom tag that puts a value into the page context.

Listing 16.14 Source Code for ScriptTag.java
package examples.taglibs;

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

public class ScriptTag extends TagSupport

{
    public int doStartTag()
        throws JspException
    {
        pageContext.setAttribute("scriptVar", "This is the script variable");

        return SKIP_BODY;
    }

    public int doEndTag()
    {
        return EVAL_PAGE;
    }
}

Listing 16.15 shows a JavaServer Page that calls the ScriptTag custom tag and then accesses scriptVar as if it were a local variable.

Listing 16.15 Source Code for TestScriptTag.jsp
<%@ taglib uri="/scripttag" prefix="xx" %>
<html>
<body>
<xx:setVar/>
<h1><%= scriptVar %></h1>
</body>
</html>

Variable Magic?

graphics/bytheway_icon.gif

You might be wondering how a value gets from the page context into a Java variable automatically. It isn't as automatic as you might think. According to the JSP specification, the JSP engine is responsible for getting the value from the page context and copying it to the local variable. If you examine the servlet generated from a JSP that uses a tag-generated scripting variable, you'll see a line that copies the value out of the page context.


To match a TagExtraInfo class to its associated tag, you must include a <teiclass> element in the Tag Library Descriptor for the custom tag. Listing 16.16 shows the TLD for the ScriptTag class.

Listing 16.16 Source Code for scripttag.tld
<?xml version="1.0" encoding="ISO-8859-1"?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation=
         "http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
      version="2.0">
   <tlib-version>1.0</tlib-version>
   <short-name>scripttag</short-name>
   <description>
       An example scripting variable tag
   </description>
   <tag>
     <name>setVar</name>
        <tag-class>examples.taglibs.ScriptTag</tag-class>
        <tei-class>examples.taglibs.ScriptExtraInfo</tei-class>
        <body-content>empty</body-content>
   </tag>
</taglib>

The choice between using a TagExtraInfo class and declaring a variable in the TLD depends on the functionality that you need. Certainly, using TagExtraInfo is more work. However, you can dynamically declare the type and scope of the variable as well as the name. If you need this functionality, use TagExtraInfo. Otherwise, declaring a variable in the TLD is a better option.

Having Trouble with the Example?

graphics/bytheway_icon.gif

If you are having trouble defining scripting variables, see the "Q&A" section at the end of this hour.


    [ Team LiB ] Previous Section Next Section