2 Understanding and Creating Custom JSP Tags

The following topics provide an overview of custom JSP tag functionality, format, and components, as well as procedures for creating and configuring a tag library.

Tag Handler API and Implementation

You write a custom JSP tag by writing a Java class that is called a tag handler.

The Jakarta Pages 4.0 API defines the classes and interfaces for custom tag handlers. See the Jakarta Pages 4.0 Specification at https://jakarta.ee/specifications/pages/4.0/jakarta-server-pages-spec-4.0.html and the jakarta.servlet.jsp.tagext API reference at https://jakarta.ee/specifications/pages/4.0/apidocs/jakarta.servlet.jsp/jakarta/servlet/jsp/tagext/package-summary.html.

A custom tag handler is either a classic tag handler or a simple tag handler:

  • Classic tag handlers use the Tag, IterationTag, or BodyTag interface. Tag defines the basic start/end lifecycle and can include a body without buffering it. IterationTag extends Tag and adds doAfterBody() to decide whether to evaluate the body again. BodyTag extends IterationTag and adds access to buffered body content through BodyContent. Use BodyTag only when the handler needs to inspect or transform buffered body content.
  • Simple tag handlers use the SimpleTag interface. SimpleTag does not extend Tag. Its doTag() method runs once per tag invocation; the handler can evaluate its body, if present, through the JspFragment supplied by the container.

Implement the appropriate interface directly, or extend a support class that supplies default implementations. SimpleTagSupport implements SimpleTag; TagSupport implements IterationTag (and therefore Tag); BodyTagSupport implements BodyTag. These support classes are concrete classes, not abstract base classes. Choose Tag when no body iteration or buffering is needed, IterationTag when the body may repeat without buffering, BodyTag when the handler needs buffered body content, or SimpleTag for the simpler doTag() lifecycle.

You can include one or more custom JSP tags in a tag library. You define a tag library by a tag library descriptor (.tld) file. The TLD describes the syntax for each tag and ties it to the Java classes that execute its functionality.

Custom Tag Library

JSP tag libraries include one or more custom JSP tags and are defined in a tag library descriptor (.tld) file. To use a custom tag library from a JSP page, reference its tag library descriptor with a <%@ taglib %> directive.

For example:

<%@ taglib uri="myTLD" prefix="mytaglib" %>
  • uri

    The uri value in a taglib directive identifies the tag library. In this example, the directive uses myTLD:

    <%@ taglib uri="myTLD" prefix="mytaglib" %>

    Note:

    If /WEB-INF/library.tld contains <uri>myTLD</uri>, the JSP container discovers that TLD automatically; no taglib entry in web.xml is required. Ordinary TLD files may be placed under /WEB-INF, but not under /WEB-INF/tags, which is reserved for tag files and an optional implicit.tld. A TLD inside a JAR in /WEB-INF/lib is discovered when it is under META-INF in that JAR.

    An explicit mapping is also allowed. If you use one, place this fragment inside the existing <web-app> element in /WEB-INF/web.xml:

    <jsp-config>
      <taglib>
        <taglib-uri>myTLD</taglib-uri>
        <taglib-location>/WEB-INF/library.tld</taglib-location>
      </taglib>
    </jsp-config>
  • prefix

    The prefix attribute assigns a label to the tag library. You use this label to reference its associated tag library when writing your pages using custom JSP tags.

    For example, if the library (called mytaglib) from the example above defines a new tag called newtag, you would use the tag in your JSP page like this:

    <mytaglib:newtag>

See Creating a Tag Library Descriptor.

Custom Tag Format

A custom tag format can be empty, called an empty tag, or can contain a body, called a body tag. Both types of tags can accept a number of attributes that are passed to the Java class that implements the tag.

See Handling Exceptions within a Tag Body for more information.

An empty tag takes the following form:

<mytaglib:newtag attr1="aaa" attr2="bbb" ... />

A body tag takes the following form:

<mytaglib:newtag attr1="aaa" attr2="bbb" ... >
  body
</mytaglib:newtag>

A tag body can include more JSP syntax, and even other custom JSP tags that also have nested bodies. Tags can be nested within each other to any level.

For example:

<mytaglib:tagA>
   <h2>This is the body of tagA</h2>
   You have seen this text <mytaglib:counter /> times!
  <p>
  <mytaglib:repeater repeat=4>
     <p>Hello World!
  </mytaglib:repeater>
</mytaglib:tagA>

The preceding example uses three custom tags to illustrate the ability to nest tags within a body tag. The tags function like this:

  • The body tag <mytaglib:tagA> only sees the HTML output from its evaluated body. That is, the nested JSP tags <mytaglib:counter> and <mytaglib:repeater> are first evaluated and their output becomes part of the evaluated body of the <mytaglib:tagA> tag.

  • The body of a body tag is first evaluated as JSP and all tags that it contains are translated, including nested body tags, whose bodies are recursively evaluated. The result of an evaluated body can then be used directly as the output of a body tag, or the body tag can determine its output based on the content of the evaluated body.

  • The output generated from the JSP of a body tag is treated as plain HTML. That is, the output is not further interpreted as JSP.

What Can You Do with Custom Tags?

Custom tags can perform the following tasks:

  • An empty tag can perform presentation-related server-side work based on its attributes, such as selecting a display option. Do not use a tag running inside a JSP as the only login or permission check for that page. Protect the JSP URL and other relevant resources through the web application's authentication and authorization configuration, such as Servlet security constraints for the URL patterns.

    • If the tag is included directly in the JSP page, then the surrounding scope is the JSP page output.

    • If the tag is nested within another parent tag, then the output becomes part of the evaluated body of its parent tag.

  • Define new objects that can be referenced and used as scripting variables in the JSP page. A tag can introduce fixed-named scripting variables, or can define a dynamically named scripting variable with the id attribute.

  • Iterate over body content of the tags until a certain condition is met. Use iteration to create repetitive output, or to repeatedly invoke a server side action.

  • Determine whether the rest of the JSP page should be processed as part of the request, or skipped.

  • An empty tag can perform server-side work based on the tag's attributes. The action that the tag performs can determine whether the rest of the page is interpreted or some other action is taken, such as a redirect. This function is useful for checking that users are logged in before accessing a page, and redirecting them to a login page if necessary.

  • An empty tag can insert content into a page based on its attributes. You can use such a tag to implement a simple page-hits counter or another template-based insertion.

  • An empty tag can define a server-side object that is available in the rest of the page, based on its attributes. You can use this tag to create a reference to an EJB, which is queried for data elsewhere in the JSP page.

  • A body tag has the option to process its output before the output becomes part of the HTML page sent to the browser, evaluate that output, and then determine the resulting HTML that is sent to the browser. This functionality could be used to produce "quoted HTML," reformatted content, or used as a parameter that you pass to another function, such as an SQL query, where the output of the tag is a formatted result set.

  • A body tag can repeatedly process its body until a particular condition is met.

Creating and Configuring a JSP Tag Library: Example Procedures

To create and use a custom JSP tag:

  1. Write the tag handler class. It implements SimpleTag, Tag, IterationTag, or BodyTag, or extends the corresponding support class described above.
  2. Write a Jakarta Pages 4.0 TLD that declares the tag, names the handler class, and contains <uri>myTLD</uri>. See Creating a Tag Library Descriptor.
  3. Put the TLD at /WEB-INF/library.tld and the compiled handler class files under /WEB-INF/classes in directories matching their Java package names. Chapter 5 also explains how to package both in a JAR under /WEB-INF/lib.
  4. At the top of the JSP page, add <%@ taglib uri="myTLD" prefix="mytaglib" %>.
  5. Use a tag declared by the TLD, for example <mytaglib:code>text to format</mytaglib:code> when using the code tag in the Chapter 3 sample TLD.
  6. Deploy the web application. No explicit web.xml taglib mapping is needed for the /WEB-INF/library.tld example because the TLD declares the same URI, myTLD. For an explicit mapping, use the Chapter 5 example.