ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Designing JSP Custom Tag Libraries

by Sue Spielman
04/19/2001

In this article you'll learn

  • what a custom tag library is,
  • why you want to use a custom tag library,
  • the composition of a tag library, and
  • how to build and use a complete library.

What a Custom Tag Library Is

If you've ever had the opportunity to build a web application using Java technology, chances are you have used Java Server Pages (JSP) for content display. JSP is the technology that helps separate the front end presentation from the middle and backend tiers. The custom tag library is a powerful feature of JSP v1.1 that aids in that separation. This technology is valuable to anyone who is building production-quality web applications, and it is very applicable in today's market.

Custom tag libraries allow the Java programmer to write code that provides data access and other services, and they make those features available to the JSP author in a simple to use XML-like fashion. An action in a web application -- for example, gaining database access -- can be customized by using a custom tag in a JSP page. The JSP author doesn't have to understand the underlying detail to complete the action. In short, a tag library is a collection of custom actions presented as tags.

Custom tags have many features that make them attractive to use from any JSP. Custom tags can

  • be customized via attributes passed from the calling page, either staticly or determined at runtime;
  • have access to all the objects available to JSP pages including request, response, in and out;
  • modify the response generated by the calling page;
  • communicate with each other; you can create and initialize a JavaBeans component, create a variable that refers to that bean in one tag, and then use the bean in another tag;
  • be nested within one another, allowing for complex interactions within a JSP page; and
  • encapsulate both simple and complex behaviors in an easy to use syntax and greatly simplify the readability of JSP pages.

Any of these points is reason enough to consider using a tag library.

Let's look at what makes up a tag library and build one step by step.

The Composition of a Tag Library

There are two types of components for a tag library: the tag library descriptor file and the tag handlers. With these a JSP is able to use tags contained in the library within its page.

The TLD File
A tag library descriptor (TLD) file is an XML document that describes the library. A TLD contains information about the library as a whole and about each tag contained in the library. TLDs are used by a JSP container to validate the tags.

There is typically some header information followed by elements used to define the tag library. The elements are

<taglib>

The tag library itself.

<tlibversion>

The tag library's version.

<jspversion>

The JSP specification version the tag library depends on.

<shortname>

A simple default name with a mnemonic value. For example, <shortname> may be used as the preferred prefix value in taglib directives and/or to create prefixes for IDs.

<uri>

A optional URI that uniquely identifies the tag library.

<info>

Descriptive information about the tag library.

Then each tag contained in the library is described. There can be one or many tags per library. There is only one TLD element required for all tags, and that is the one used to specify a tag handler's class: <tagclass>classname</tagclass>

There are various other elements used to describe tags. Which elements a tag uses will depend on how the tag is implemented in the handler. We'll get to that discussion in the section below.

If a tag has attributes associated with it, then each attribute must be described within the <tag> element. If an attribute is required by a tag, <required> is set to "true" or "yes". To allow a runtime expression value to be used by the tag, the <rtexpvalue> is set to "true" or "yes". For each attribute of a tag, a Bean-like getter/setter method needs to be defined in the handler class. It's also possible to define scripting variables for use in tags. This is accomplished using a TagExtraInfo class and will be discussed in the tag handler section. If a TagExtraInfo is to be used, the class must be defined using the <teiclass>classname<teiclass> within the tag definition.

A sample TLD named oreillySample.tld looks like

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" 
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<taglib>
	<tlibversion>1.0</tlibversion>
	<jspversion>1.1</jspversion>
	<shortname>oreillySamples</shortname>
	<info>OReilly Sample Tag library</info>
  <!-A Simple tag -->
  <tag>
    <name>hello</name>
    <tagclass>oreilly.examples.Hello </tagclass>
  <!--Body content can have a value of 
  	 empty: no body 
      JSP: body that is evaluated by container, then possibly processed by the tag 
      tagdependent: body is only processed by tag; JSP in body is not evaluated.
   -->
    <bodycontent>empty</bodycontent>
    <info>
	This is a simple hello tag.
    </info>
  <!-- Optional attributes  -->
  <!- personalized name -->
  <attribute>
      <name>name</name>
      <required>false</required>
      <rtexpvalue>false</rtexpvalue>
  </attribute>
</tag>
</taglib>

The Tag Handler
The tag is defined in a handler class. TagSupport is the base class used for simple tags. It can be found in the javax.servlet.tagext package. What your tag is implementing will depend on what methods could potentially be called and what needs to be implemented. TagSupport and TagBodySupport supply default implementations of the methods listed below.

If your Tag Handler:

You need to implement the following methods:

has no attributes and no body

doStartTag, doEndTag, release

has attributes

doStartTag, doEndTag, set/getAttribute1...N

has a body with no interaction

doStartTag, doEndTag, release

has a body with interaction

doStartTag, doEndTag, release, doInitBody, doAfterBody

A more advanced feature is the use of scripting variables. Typically an attribute is passed to the tag that contains the ID of the object to be used. The usual operation is that the tag handler retrieves a scripting variable value object using pageContext.getAttribute(name), performs some processing on it, and then sets the scripting variable's value using the pageContext.setAttribute(name, object). In addition to setting the value of the variable within the tag handler, you must define a class derived from TagExtraInfo that provides information to the JSP container about the nature of the variable. That class is then listed in the <teiclass> attribute of the tag.

The Java code for the tag defined in the oreillySample.tld file would look like

package oreilly.examples
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
/**
 * This is a simple tag example to show how content is added to the
 * output stream when a tag is encountered in a JSP page. 
 */
public class Hello extends TagSupport {
	private String name=null;
    /**
      * Getter/Setter for the attribute name as defined in the tld file 
      * for this tag
      */
public void setName(String value){
    name = value;
}

	public String getName(){
          return(name);
       }
/**
* doStartTag is called by the JSP container when the tag is encountered
*/
    public int doStartTag() {
	  try {
        JspWriter out = pageContext.getOut();
        out.println("<table border="\1\">");
	     if (name != null)
	      out.println("<tr><td> Hello " + name + " </td></tr>");
        else
	      out.println("<tr><td> Hello World </td></tr>");
	  } catch (Exception ex) {
	    throw new Error("All is not well in the world.");
	  }
	  // Must return SKIP_BODY because we are not supporting a body for this 
	  // tag.
	  return SKIP_BODY;
    }
/**
 * doEndTag is called by the JSP container when the tag is closed
 */
	public int doEndTag(){
	   try {
        	JspWriter out = pageContext.getOut();
	       out.println("</table>");
	   } catch (Exception ex){
	    	throw new Error("All is not well in the world.");
	   }
	}
}

Next page: The JSP

Pages: 1, 2

Next Pagearrow