Processing Attributes
Our simple example is all very well, but it doesn't take advantage of the dynamic potential of custom tags. We could interrogate the PageContext to implement context-specific behavior, but there are far better alternatives.
The easiest way to parameterize tags is to pass in XML attributes.
How do we make our tags handle attributes? The answer, not surprisingly, is that attributes in a TLD tag element map onto bean properties of the corresponding tag handlers. The mapping of attributes onto tag handler properties is, as we might expect, handled by the JSP engine using reflection and not only does it work with primitive types, we can pass any type to a tag handler. (Draft versions of the JSP 1.1 specification included a type subelement of the attribute TLD element; this has now been removed.)
Attributes can be either required or optional. This is specified in the TLD, as is whether attributes can take the value of JSP expressions at runtime, as we mentioned earlier.
Let's suppose we decide to pass a name as an attribute, and change our simple example to display the following:

First, we need to write a tag handler with a name property. With this minor change, it's pretty much like HelloTag:
package tagext;
import java.io.IOException;
import java.util.Date;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
// Hello tag accepting a name attribute.
public class AttribHelloTag extends TagSupport
{
private String name;
// Property getter for name
public String getName() {
return name;
}
// Property setter for name
public void setName(String name) {
this.name = name;
}
public int doEndTag() throws JspTagException {
String dateString = new Date().toString();
try {
pageContext.getOut().write("Hello <b>" + name + "</b>.<br/>");
pageContext.getOut().write("My name is " + getClass().getName() +
" and it's " + dateString + "<p/>");
}
catch (IOException ex) {
throw new JspTagException("Hello tag could not write to JSP out");
}
return EVAL_PAGE;
}
}
You should save this in WEB-INF/classes/tagext. Don't be tempted to omit the property 'getter', which at first sight seems unnecessary. The JavaBeans specification requires both getter and setter for a bean property, and some JSP engines may rely on the presence of both methods at translation time. (JRun 3.0, unlike Tomcat, seems to rely on getters to determine property types.)
Now we must add a tag entry to our TLD describing the new tag, and specifying that it requires an attribute, name:
<tag>
<name>helloAttrib</name>
<tagclass>tagext.AttribHelloTag</tagclass>
<bodycontent>JSP</bodycontent>
<info>Simple example with attributes</info>
<attribute>
<name>name</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
The JSP container will throw an exception if the required name attribute is not specified, and the attribute can be set with the runtime value of an expression, as well as with a static string (the value of rtexprvalue being true).
The calling JSP, hello2.jsp, is identical to hello.jsp, except for the way in which we invoke the tag itself:
<%@ taglib uri="/hello" prefix="examples" %>
<html>
<head>
<title>Simple tag with attributes</title>
</head>
<body>
This is static output.
<p />
<i>
<examples:helloAttrib name="Rod">
</examples:helloAttrib>
</i>
This is static output again.
</body>
</html>
Attributes are an excellent way of controlling tag behavior at runtime, and are especially valuable in ensuring that tags are generic and reusable.
Elegant as the attribute/property mechanism is, there is one annoying problem with passing String attributes to tags. Specifying some characters in attributes is messy. The double quote character, for example, is (for obvious reasons) illegal in an attribute, and we must use the entity reference " if we want to include it. This rapidly becomes unreadable if the data includes multiple quotation marks. Attributes are also unsuited to handling lengthy values, for reasons of readability.
So there are limits to what can sensibly be achieved with attributes. Where complicated markup is concerned, consider the alternatives:
- Processing markup and expressions in the body of the tag, possibly repeatedly
- Defining a subtag that configures its ancestor. This is an advanced strategy, which we'll look at later in the following chapter
- Implementing the tag to read its markup from a template file or URL
The most elegant of these solutions, where feasible, is to manipulate the tag body. This will only be useful if the tag defines scripting variables that the tag body can use.
There is a curious and confusing inconsistency in JSP syntax when non-String tag attributes are the results of JSP expressions. Let's suppose we want to pass an object of class examples.Values (a kind of list) to a tag extension. The syntax:
<wrox:list values="<%=values%>"
is problematic, because we know from the JSP specification that an expression "is evaluated and the result is coerced to a String which is subsequently emitted into the current out JspWriter object". In the case of the custom tag above, however, the value of the expression is not coerced to a String, but passed to the tag handler as its original type.
Body Content
So far we have used tags only to generate markup, we haven't considered what custom tags may do to their body content (anything found between their start and end tags).
Let's suppose we modify hello.jsp to add some code inside one of the tags, like this:
<examples:hello>
This is tag content!
</examples:hello>
The result, shown by tagcontent.jsp, is that the content we have added is output in addition to any output generated by the tag. Whether the content appears before or after the tag's output depends on whether we chose to do tag output in the doStartTag() or doEndTag() methods. In the case of the HelloTag, the output will appear before the tag's own output, as shown in tagcontent.jsp:

Tag content will be treated at run time as JSP (so long as the body content is set in the TLD to be JSP), so it may include expressions. Try modifying the last example like this:
<examples:hello>
This is tag content containing an expression: 37 * 16 = <%= 37 * 16 %>
</examples:hello>
Scriptlets are also legal, as is any other valid JSP content. The following will produce the same result:
<examples:hello>
<% int a = 37; %>
<% int b = 16; %>
This is tag content containing expressions and scriptlets:
<%=a%> * <%=b%> = <%= a * b %>
</examples:hello>
The output in either case as shown in tcexpr.jsp is:

To do anything really useful with body content, however, we need to make our tags define scripting variables, or manipulate body content.
Continued...