Writing Tag Handlers





Writing Tag Handlers

The third piece in Figure is the actual Java class that provides the runtime behavior of a custom tag—the tag handler. Such a class must implement one of the three interfaces: Tag, IterationTag, or BodyTag. The interface that your class implements depends upon the context and behavior of the corresponding tag (Figure).

More often than not, tag handlers will be classes that extend one of the convenience support classes, TagSupport or TagBodySupport. Listing 11.1 shows a tag handler class:

JSP categorizing custom actions.

Characteristic

Behavior Description

Interface

Simple action

Does some logic (within the doStartTag()). May be parameterized by attribute values.

Tag

Actions with a body

Similar to Simple Action but needs to perform logic at the beginning and the end of the body (logic in both doStartTag() and doEndTag()

Tag

Conditionals

Use of return values from doStartTag()

Tag

Iterations

The doAfterBody() method is invoked to determine whether or not to reevaluate the body.

IterationTag

Actions that process their body

Needs a way of diverting the output of a body evaluation for other manipulation. Works with a BodyContent object and uses the setBodyContent() and doInitBody() methods of the BodyTag Interface

BodyTag

Cooperating actions

Interact with other (logically nested) tags—sharing data for instance. Makes use of the setParent() method and the findAncestorWithClass() helper method of TagSupport.

Any

Actions defining scripting variables

Many actions will create server-side objects and make them available to other scripting elements on the page. This is the prime use for the page context. May define implicit objects declared either via the variables element or the tageiclass element in the taglib descriptor.

Any

FormatDate tag handler class.

package com.wsbook.casestudy.tags;

// various imports omitted for brevity

public class FormatDate extends TagSupport {

       private String formatId;  // attribute with key into session for

                               // DateFormat object

       private Calendar calendar; // attribute - Date to be displayed

       /**Performs the processing of this simple action. */

       public int doStartTag() throws JspException {

              String dateString = null;

              Formatter formatter = (Formatter)pageContext.getSession().getAttribute

graphics/ccc.gif(formatId);

              if (formatter == null)

                     formatter = Formatter.getDefaultFormatter();

              if (calendar != null) {

                     dateString = formatter.format(calendar);

                     try {

                            pageContext.getOut().write(dateString);

                     } catch (IOException ioe) {

                            throw new JspException(ioe.getMessage());

                     }

              }

              return EVAL_BODY_INCLUDE;

       }

       public void setCalendar(Calendar calendar) {

              this.calendar = calendar;

       }

       public void setFormatId(String formatId) {

              this.formatId = formatId;

       }

}

This class extends TagSupport making it very easy to code. Other than declaring the two attribute fields and the corresponding setters,[2] ,all of the logic is found in the doStartTag() method. This is common for a large set of simple actions. This tag will have no body (or at least one that this tag depends upon). The method retrieves the formatting object from the session using the key value supplied via the formatId attribute. There is some logic to handle the case where no such formatter object exists on the session. It then generates the formatted date string using the format object and the other attribute calendar. Next, the logic gets access to the output stream and inserts the formatted date string into this stream.

[2] Setter methods are called by the framework before doStartTag() is invoked.

The return value indicates whether or not to continue evaluating the body of the tag (if it exists). This tag does not create or manipulate any scripting variables, making it very simple indeed.

Different return values are available for each of the methods of the tag interfaces. These can cause the tag body to be skipped, evaluated, or reevaluated. There are others that indicate that processing should not continue on the page or that processing should continue.


     Python   SQL   Java   php   Perl 
     game development   web development   internet   *nix   graphics   hardware 
     telecommunications   C++ 
     Flash   Active Directory   Windows