14.2 Defining a Basic Tag
This section gives details on defining simple tags without attributes or tag bodies; the tags are thus of the form <prefix:tagname />.
The Tag Handler Class
Tags that either have no body or that merely include the body verbatim should extend the TagSupport class. This is a built-in class in the javax.servlet.jsp.tagext package that implements the Tag interface and contains much of the standard functionality basic tags need. Because of other classes you will use, your tag should normally import classes in the javax.servlet.jsp and java.io packages as well. So, most tag implementations contain the following import statements after the package declaration:
import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; import java.io.*;
I recommend that you download an example from http://www.coreservlets.com/ and use it as the starting point for your own implementations.
For a tag without attributes or body, all you need to do is override the doStartTag method, which defines code that gets called at request time where the element's start tag is found. To generate output, the method should obtain the JspWriter (the specialized PrintWriter available in JSP pages through use of the predefined out variable) from the pageContext field by means of getOut. In addition to the getOut method, the pageContext field (of type PageContext) has methods for obtaining other data structures associated with the request. The most important ones are getRequest, getResponse, getServletContext, and getSession.
Since the print method of JspWriter throws IOException, the print statements should be inside a try/catch block. To report other types of errors to the client, you can declare that your doStartTag method throws a JspException and then throw one when the error occurs.
If your tag does not have a body, your doStartTag should return the SKIP_BODY constant. This instructs the system to ignore any content between the tag's start and end tags. As we will see in Section 14.5 (Optionally Including the Tag Body), SKIP_BODY is sometimes useful even when there is a tag body, but the simple tag we're developing here will be used as a stand-alone tag (<prefix:tagname />) and thus does not have body content.
Listing 14.4 shows a tag implementation that uses this approach to generate a random 50-digit prime through use of the Primes class developed in Chapter 7 (Generating the Server Response: HTTP Response Headers) see Listing 7.4.
The Tag Library Descriptor File
The general format of a descriptor file is almost always the same: it should contain an XML version identifier followed by a DOCTYPE declaration followed by a taglib container element. To get started, just download a sample from http://www.coreservlets.com/. The important part to understand is what goes in the taglib element: the tag element. For tags without attributes, the tag element should contain four elements between <tag> and </tag>:
name, whose body defines the base tag name to which the prefix of the taglib directive will be attached. In this case, I use <name>simplePrime</name> to assign a base tag name of simplePrime.
tagclass, which gives the fully qualified class name of the tag handler. In this case, I use <tagclass>coreservlets.tags.SimplePrimeTag </tagclass>
info, which gives a short description. Here, I use <info>Outputs a random 50-digit prime.</info>
bodycontent, which should have the value EMPTY for tags without bodies. Tags with normal bodies that might be interpreted as normal JSP use a value of JSP, and the rare tags whose handlers completely process the body themselves use a value of TAGDEPENDENT. For the SimplePrimeTag discussed here, I use EMPTY as below: <bodycontent>EMPTY</bodycontent>
Listing 14.5 shows the full TLD file.
Listing 14.5 csajsp-taglib.tld
<?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"> <!-- a tag library descriptor --> <taglib> <!-- after this the default space is "http://java.sun.com/j2ee/dtds/jsptaglibrary_1_2.dtd" --> <tlibversion>1.0</tlibversion> <jspversion>1.1</jspversion> <shortname>csajsp</shortname> <urn></urn> <info> A tag library from Core Servlets and JavaServer Pages, http://www.coreservlets.com/. </info> <!-- Other tags defined earlier... -->
The JSP File
JSP documents that make use of custom tags need to use the taglib directive, supplying a uri attribute that gives the location of the tag library descriptor file and a prefix attribute that specifies a short string that will be attached (along with a colon) to the main tag name. Listing 14.6 shows a JSP document that uses
<%@ taglib uri="csajsp-taglib.tld" prefix="csajsp" %>
to use the TLD file just shown in Listing 14.5 with a prefix of csajsp. Since the base tag name is simplePrime, the full tag used is
Figure 142 shows the result.
Listing 14.6 SimplePrimeExample.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE>Some 50-Digit Primes</TITLE> <LINK REL=STYLESHEET HREF="JSP-Styles.css" TYPE="text/css"> </HEAD> <BODY> <H1>Some 50-Digit Primes</H1> <%@ taglib uri="csajsp-taglib.tld" prefix="csajsp" %> <UL> <LI><csajsp:simplePrime /> <LI><csajsp:simplePrime /> <LI><csajsp:simplePrime /> <LI><csajsp:simplePrime /> </UL> </BODY> </HTML>
Figure 142 Result of SimplePrimeExample.jsp.