Tutorial: Understanding the New Features of JSP 2.0
Discuss this tutorial. Printable version (PDF).
This is the Contents page. No previous page. Go up a level. Go to next page.

 

 

Simple Tag Handlers


In this section, we will look at another new and interesting feature of JSP 2.0, Simple Tag Handlers. Specifically, we will look at the following:

Using Simple Tag Extensions
Simple Tag Interface
SimpleTag Syntax
Simple Tag Handler Lifecycle

Using Simple Tag Extensions

The API and invocation protocol for classic tag handlers is necessarily somewhat complex because scriptlets and scriptlet expressions in tag bodies can rely on surrounding context defined using scriptlets in the enclosing page.With the introduction of the Expression Language (EL) and JSP Standard Tag Library (JSTL), JSP page authors can now develop JSP pages that do not need scriptlets or scriplet expressions. This also has an implication on the requirements that classic tag handlers need to take into consideration, with many of them being irrelevant in most cases. This allows for a definition of a tag invocation protocol that is easier to use for many use cases. The introduction of the simple tag extension in JSP 2.0 signalled an easier way to implement custom actions with a lifecycle that is as easier to work with.

Outside of the fact that simple tag extensions made work easier, they also do not directly depend upon any Servlet APIs, which meant that they opened up a whole new space for further integration with other technologies. This is accomplished because PageContent now extends JspContext. JspContext provides generic services such as storing the JspWriter and keeping track of scoped attributes, whereas PageContext has functionality specific to serving JSPs in the context of Servlets. The Tag interface relies on PageContext, whereas SimpleTag only relies on JspContext.

Simple Tag Extensions can be written in one of two ways:

  • In Java, by defining a class that implements the javax.servlet.jsp.tagext.SimpleTag interface. This class is intended for use by advanced page authors and tag library developers who need the flexibility of the Java language in order to write their tag handlers. The javax.servlet.jsp.tagext.SimpleTagSupport class provides a default implementation for all methods in SimpleTag.

  • In JSP syntax, using tag files. With the ability to write custom actions in JSP syntax, page authors (with no prior knowledge of Java), advanced page authors or tag library developers ( who know Java but are producing tag libraries that are primarily template based presentation) have been benefitted.

SimpleTag Interface

Simple tag handlers are those that implement the SimpleTag interface. It is worth noting that this interface is provided for situations when the flexibility of the Java language in needed in order to write the tag handler.

The invocation protocol used by SimpleTag is simplified from the one used for Classic tag handlers. The javax.servlet.jsp.tagext.SimpleTagSupport class provides a default implementation for all methods in SimpleTag. The complete interface definition is shown below:

public interface SimpleTag extends JspTag {
public void doTag()throws JspException, java.io.IOException;
public void setParent(JspTag parent);
public JspTag getParent();
public void setJspContext(JspContext pc);
public void setJspBody(JspFragment jspBody);
}

It is important to note that that the SimpleTag interface extends directly from JspTag and doesn't extend Tag. This implies the fact that SimpleTag doesn't have any inherent JSP/Servlet knowledge embedded within it. Another difference that is worth noticing is that SimpleTag only has one lifecycle method, doTag() defined as:

public void doTag()throws JspException, java.io.IOException

The doTag() method is called only once for any given tag invocation. This means that all code (includes tag logic, iteration, or body evaluations) related to this tag is contained in one nice and trim method. If you compare this to the IterationTag interface, you will notice how considerably easier it is to get the job done.

The setJspBody() method is provided to support body content. The container invokes the setJspBody() method with a JspFragment object encapsulating the body of the tag. The tag handler implementation can call invoke() on that fragment to evaluate the body. The SimpleTagSupport convenience class provides getJspBody() and other useful methods to make this even easier.

Most SimpleTag handlers should extend javax.servlet.jsp.tagext.SimpleTagSupport. This is the convenience class, similar to TagSupport or BodyTagSupport. There are also some helpful methods included in this class that include:

  • public JspFragment getJspBody() which returns the body passed in by the container via setJspBody. The JspFragment encapsulates the body of the tag. If the JspFragment is null, it indicates that tag has a body content type of empty.

  • public static final JspTag findAncestorWithClass(JspTag from, java.lang.Class klass) which finds the instance of a given class type that is closest to a given instance. This method uses the getParent() method from the Tag and/or Simple Tag interfaces. This method is used for coordination among cooperating tags. While traversing the ancestors, for every instance of TagAdapter (used to allow collaboration between classic Tag handlers and SimpleTag handlers) encountered, the tag handler returned by TagAdapter.getAdaptee() is compared to klass. In a case where the tag handler matches this class, and not its TagAdapter, is returned.

SimpleTag Syntax

The basic syntax for a SimpleTag is:

public interface SimpleTag extends JspTag

The above syntax defines an interface for Simple Tag Handlers. Simple Tag Handlers differ from Classic Tag Handlers in that instead of supporting doStartTag() and doEndTag(), the SimpleTag interface provides a simple doTag() method, which is called once and only once for any given tag invocation.All tag logic, iteration, body evaluations, etc. are to be performed in this single method. Thus, simple tag handlers have the equivalent power of BodyTag, but with a much simpler lifecycle and interface.

To support body content, the setJspBody() method is provided. The container invokes the setJspBody() method with a JspFragment object encapsulating the body of the tag. The tag handler implementation can call invoke() on that fragment to evaluate the body as many times as it needs.

It is worth noting that a SimpleTag handler must have a public no-args constructor. Most SimpleTag handlers should extend SimpleTagSupport.

Simple Tag Handler Lifecycle

When a simple tag handler is required on a JSP, it is instantiated by the container, it is executed, and then it is discarded. There are no complicated caching semantics when using this interface since nothing is cached or reused. It was decided by the expert group that performance gains that might be made using caching mechanisms dramatically increased the difficulty in writing portable tag handlers and made the handlers error prone.

If performance concerns are critical, I would suggest first implementing your tag handler as a simple tag and then taking some performance metrics to see if your criteria are met before embarking on the more complicated and time-consuming path of writing a Classic handler.

The following lifecycle events take place for the simple tag handler (in the same order):

1. A new tag handler instance is created each time the tag is encountered by the container. This is done by calling the zero argument constructor on the corresponding implementation class. It is important to note that a new instance must be created for each tag invocation.

2. The setJspContext() and setParent() methods are invoked on the tag handler. If the value being passed is 'null', then the setParent() method need not be called. In the case of tag files, a JspContext wrapper is created so that the tag file can appear to have its own page scope. Calling getJspContext() must return the wrapped JspContext..

3. The container calls the setters for each attribute defined for this tag in the order in which they appear in the JSP page or Tag File. If the attribute value is an expression language expression or a runtime expression, it gets evaluated first and is then passed on to the setter. On the other hand if the attribute is a dynamic-attribute then setDynamicAttribute() is called.

4. The setJspBody() method is called by the container to set the body of this tag, as a JspFragment. A value of null is passed to setJspBody() if the tag is declared to have a <body-content> of empty.

5. The doTag() method is called by the container. All tag logic, iteration, body evaluations,etc. occur in this method.

6. All variables are synchronized after the doTag() method returns.


Discuss this tutorial. Printable version (PDF).
This is the Contents page. No previous page. Go up a level. Go to next page.
E-mail this page
Printer View Printer View
Oracle Is The Information Company About Oracle | Oracle RSS Feeds | Careers | Contact Us | Site Maps | Legal Notices | Terms of Use | Privacy