| Sign In/My Account | View Cart |
The latest version of the JSP specification, JSP 1.2, was released on September 17, 2001. In part one of this article, I described a number of new features that have been added to the specification. In this article, I focus on the details concerning the custom tag handler API.
Custom tag developers now have two new interfaces to play with: IterationTag and TryCatchFinally.
The IterationTag interface is implemented by a tag handler that repeatedly evaluates its element body. It is located between the Tag and the BodyTag interfaces in the inheritance hierarchy: IterationTag extends Tag and BodyTag extends IterationTag. A tag handler that needs full control over error conditions may implement the TryCatchFinally interface.
The following sections describe both interfaces in detail.
The IterationTag interface contains only one method:
public int doAfterBody(): Called by the container after it has processed the action element's body.
If you think this method looks familiar, you're right. It used to be part of
the BodyTag interface. By moving this method to the new
IterationTag interface, iterators that do not need access
to the element body can be implemented without the overhead associated
with maintaining a BodyContent instance.
The doAfterBody() method can return either
EVAL_BODY_AGAIN (to iterate over the body) or
SKIP_BODY (to stop the iteration). The
EVAL_BODY_AGAIN constant is new, replacing the
confusingly-named EVAL_BODY_TAG constant used in JSP 1.1.
Here's an example of a tag handler class that implements the
IterationTag interface:
package com.foo;
import java.util.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
public class MyLoopTag extends TagSupport {
private Iterator iterator;
private String items;
private String var;
public void setItems(String items) {
this.items = items;
}
public void setVar(String var) {
this.var = var;
}
public int doStartTag() throws JspTagException {
Collection coll = (Collection)
pageContext.findAttribute(items);
if (coll == null) {
throw new JspTagException("No collection with name "
+ items + " found");
}
iterator = coll.iterator();
if (iterator.hasNext()) {
pageContext.setAttribute(var, iterator.next());
return EVAL_BODY_INCLUDE;
}
else {
return SKIP_BODY;
}
}
public int doAfterBody() {
if (iterator.hasNext()) {
pageContext.setAttribute(var, iterator.next());
return EVAL_BODY_AGAIN;
}
else {
return SKIP_BODY;
}
}
}
MyLoopTag extends TagSupport. The TagSupport class in JSP 1.2 implements the IterationTag interface instead of the Tag interface and provides default implementations for the methods in both interfaces. To implement an iteration tag, you must override the doStartTag() and the doAfterBody() methods.
|
Related Reading
|
In MyLoopTag, the doStartTag() method first retrieves the Collection specified by the items attribute and creates an Iterator for it. If the Iterator contains at least one element, the method makes the first element in the Collection available as a page scope object, with the name specified by the var attribute and returns EVAL_BODY_INCLUDE. This tells the container to add the contents of the loop element's body to the response and call doAfterBody().
The doAfterBody() does the same as doStartTag(), except that it doesn't initialize the Iterator. As long as the Iterator contains at least one more element, doAfterBody() returns EVAL_BODY_AGAIN. When all elements have been processed, it returns SKIP_BODY to stop the iteration.
You can use the loop tag with a Collection that contains beans with firstName and lastName properties like this:
<%@ taglib uri="/demolib" prefix="demo" %>
...
<ul>
<demo:myLoopTag items="myCollection" var="current">
<li>
<jsp:getProperty name="current" property="lastName" />,
<jsp:getProperty name="current" property="firstName" />
</demo:myLoopTag>
</ul>