In this article will look at JSP Tag Libraries. We will look at using tag libraries for building JSP Page using custom tag libraries. This is the fourth article of five on JavaServer Pages. In the last article, ďTutorial:Review of JSP Tag Libraries for the Web Component Developer ExamĒ, we provided a review of JSP Actions and their use in building JSP Pages and JSP Documents. This is part of a series of articles to help you prepare for the web component developer exam.

As of the JSP specification 2.0, there are two ways to implement custom tag libraries; either by writing Java classes or by writing regular text files containing JSP elements. In the previous article, ďTutorial:Review of JSP Tag Libraries for the Web Component Developer ExamĒ we briefly outline how custom actions can be implemented as Java classes. This practice limits the ability of developing custom actions to programmers. Also when custom actions are implemented in Java, you are obliged to produce complex content by printing out HTML code using println() calls. You might note that embedding HTML in the output was the reason that JSP were invented. In this article we will focus on developing custom action using plain text files and how to package them as tag libraries that can be used in JSP pages.

Developing A Text Tag File

A tag file is a just a text file with JSP elements that implement the functionality for a custom action. For it to be consider a valid tag file, you must use the .tag filename extension in order for the web container to identify this type of file. If you are writing your tag file in XML format, you must then use the .tagx extension. You are free to use any JSP elements that are considered valid for a JSP file except a page directive within the tag file. Other than the fact that some JSP directives that are permitted in a tag file, you create a tag file in the same manner that you create a JSP page. The installation of the tag file and itís use is is exactly the same as with custom actions implemented in Java. An example of a tag file implemented in text is shown below:

XML Code: Example of Tag File
<%@ tag body-content="empty" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<jsp:useBean id="now" scope="application" class="java.util.Date" />
Copyright &copy; ${now.year + 1900} Acme Company
This tag file is used for inserting a copyright statement into the JSP page. The first line of the custom action is a tag directive. You can use attributes in this directive to provide a description or icon. You could even provide an example in a page-authoring tool to help the web designer. Other attributes let you specify whether EL expressions should be processed, as well as various information related to scripting code, i.e., the same type of information as you specify with the page directive in JSP pages.

In the majority of cases, tag file authors will only use the attribute body-content. The body-content attribute defines how the custom action element's body should be handled. It can have one of three values. These values are scriptless, empty or tag-dependent. The default is scriptless. Scriptless means that the body can contain any JSP elements such as template text, EL expressions, standard actions and custom actions. This is because the the tag file can ask the web container to process the actions in a scriptless body when it requires it through the use of standard action named <jsp:doBody>. If the body-content is empty and an attempt is made to use a body for the custom action element, it will result in a syntax error. Finally a body-content attribute of tag-dependent means the action element body is treated as pure template text.

Note that the latter part of the tag file in the listing appears like an ordinary JSP page. We are using the <jsp:useBean> standard action to create an instance of the java.util.Date class in order to represent the current time and finally to output some static template text mixed with the current year generated by the EL expression: ${now.year + 1900}.

Text tag files are to be placed directly in the web application structure under the WEB-INF/tags directory or a subdirectory. You can setup different directories with tag files from a particular tag library. This is shown in the diagram below:

Tutorial:In Depth Look at JSP Custom Tags for the Web Component Developer Exam-a24-taglibrarydirstruct.jpg
Figure: Tag Libraries Under WEB-INF

In the figure there are two tag libraries, footags and mootags. The footags library has the cpyrt.tag file from the previous listing as well as two other tag files. The default for each custom action is the name of the tag file without .tag extension. Therefore the cpyrt.tag file has a custom action named cpyrt in the footags library. When you want a JSP page to use one of these custom actions, you must declare that it is using a tag library from the tag files using a taglib directive. In this case, the web application structure has a slightly different taglib directive than we used for standard or java based custom tags. Here the tagdir attribute replaces the uri attribute and it uses the context-relative path to the directory that contains the tag files for the library. This is shown in the listing below:

XML Code: Declaration of Tag Files
<%@ page contentType="text/html" %>
<%@ taglib prefix="foo" tagdir="/WEB-INF/tags/footags" %>

<html>
  <body bgcolor="blue">
    ...
    <foo:copyright/>
  </body>
</html>
As all tag directories start with this path, this specification appears redundant, but this was included in the JSP specification in order to be consistent with other attributes taking path values.

When the web container processes the JSP page, it first finds the cpyrt.tag file in the WEB-INF/tags/footags directory and transforms it into a format that the web container can invoke. You donít need to know the details of this as it is the responsibility of the web container vendor. For example, Tomcat turns the tag file into a Java class and compiles it, but it could be transformed into other languages.

You can also package your tag files in a JAR file if you want to reuse your tag files in other applications. When the tag files are packaged in a JAR file, your must use the taglib directive with the uri attribute making them indistinguishable from custom actions implemented in Java. This gives you the flexibility of implementing custom actions initially as tag files and then later converting them to Java classes in order to improve on performance. This can all be done without requiring any changes in the JSP pages that make use of them.

Custom Actions Attribute Values

In production web applications, tag files are controlled through attribute values set by the page author. In the previous article, ďTutorial:Review of JSP Tag Libraries for the Web Component Developer Exam", we developer a custom action <atl:mod> that has a category attribute for selecting the message category used for determining the message to be displayed. Below we present a text tag file implementation of the <atl:mod> shows how to declare and use the attribute value:

XML Code: Attributes in Tag File
<%@ tag body-content="empty" %>
<%@ attribute name="category" required="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<jsp:useBean id="mb" class="com.acme.mytestproj.domain.MessageBean" />
<c:set target="${mb}" property="category" value="${category}" />
${mb.message}
Each attribute in a tag file has to be declared using an attribute directive. In the listing, we declare the category attribute using an attribute directive setting the name attribute to category. The required attribute is set to true. This means that one must specify a value for the category attribute or the web container cause an error in the custom action if the attribute is missing. For optional attributes, as the default value for required is false, you donít need to expressly add it. We have also not use the attribute, rtexprvalue. If the value for rtexprvalue is true, then the author can specify the value either as a static string or as a request-time attribute value, such as an EL expression. If it is false then the value must be a static string. The default for rtexprvalue is true, so that you only need to provide it when you are working with only static values. In JSTL, the convention is use for var and scope attributes to have rtexprvalue set to false as they may need to be available in the translation phase in a later version of the JSP specification to allow for additional syntax checking and optimizations.

Any value provided for the attribute by the web designer is considered as a page scope variable in the tag file, with the same name as the attribute. This is facilitate itís use in an EL expression. In the previous listing, the <c:set> action sets the category property in a MessageBean. The EL expression becomes the value for the page scoped category attribute. Note that the page scope is different for the tag file and for the page. Page scope for the tag is actually more precisely, tag scope. By doing this the chance for confusion between the calling page and the tag file if they use the same names for page scope variables is minimized.

Working Undeclared Attributes in Tag Files

There will be times where you donít want to declare every single attribute due to the number of potential attributes that might be required. If a tag file is used to generate an HTML table and the web designer needs to be able to specify all standard attributes that an HTML table element supports, the preferred approach is to use the tag directive's dynamic-attributes attribute. The dynamic-attributeís attribute declares that the tag file accepts any custom action element attribute. The attribute value is the name of a local page scope variable that holds a collection (a Map) with all undeclared attribute names and values. The example below shows a tag file that uses this approach for generating a table of all the request header values.

XML Code: Using undeclared attributes in a tag file
<%@ tag body-content="empty" dynamic-attributes="tblattrs" %>
<%@ attribute name="caption" required="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<table>
  <c:forEach items="${tblattrs}" var="a">
    ${a.key}="${a.value}"
  </c:forEach>
  <caption>${caption}</caption>
  <tr>
    <th>Name</th>
    <th>Value</th>
  </tr>
  <c:forEach items="${header}" var="h">
    <tr>
      <td>${h.key}</td>
      <td>${h.value}</td>
    </tr>
  </c:forEach>
</table>
In the listing, the dynamic-attributes attribute declares a variable named tblattrs to hold the undeclared attributes. The <c:forEach> action from JSTL is used to loop through the collection and insert the name and value for each of the HTML <table> element's attribute list. In the next listing, we show that you can also declare regular attributes, in this case in the form of a mandatory attribute named caption in the same tag file. This attribute is used to add a caption text for the table:

XML Code: Using the Table Tag File with Mandatory Caption Attribute
<%@ page contentType="text/html" %>
<%@ taglib prefix="foo" tagdir="/WEB-INF/tags/footags" %>

<html>
  <head>
    <title>Headers</title>
  </head>
  <body bgcolor="white">
    <foo:headers caption="Request Headers"
      border="1" cellspacing="0" cellpadding="5" />
  </body>
</html>
In the listing, the tag fileís action element defines values for the mandatory caption attribute as well as three undeclared attributes: border, cellspacing, and cellpadding.

Processing the Custom Action Body

The body is often a key part of a custom action element. An example is a conditional custom action like a variation of the <c:if> JSTL action. If the condition is true, it will need to process the body. This is also the case for a custom action that transforms the body in some way or simply uses it as input.

Below we present an example of a custom action that transforms its body content. It converts all characters that are relevant in HTML and XML to their respective character entity codes (e.g., < to &lt;) as well as converting special proprietary codes into HTML elements. You could use this custom action to process user input in an online forum as a means of protect it against cross-site scripting attacks while allowing for limited formatting of the messages. The custom action is shown below in a JSP page:

XML Code: Custom Action to Convert Relevant HTML and XML Characters
<%@ page contentType="text/html" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="foo" tagdir="/WEB-INF/tags/footags" %>

<%-- Create test data --%>
<c:set var="message">
  This is just a lot of text that the browser will format to
  fit the browser window. Attempts to <blink> add HTML elements
  are dealt with by conversion to character entities.
  code in brackets
  This part I want the browser to leave alone, so that
  all my indentations are left intact:

    public class Foo {
      public String getBar(  ) {
        return bar;
      }
    }
  /code in brackets
  And then some regular text again.
</c:set>
<html>
  <head>
    <title>Online Forum</title>
  </head>
  <body bgcolor="white">
    <h1>Online Forum</h1>
    Here's a formatted message:
    <p>
      <foo:htmlFormat>
        ${message}
      </foo:htmlFormat>
    </p>
  </body>
</html>
The JSP page first saves the test data containing the text, any HTML element, and the proprietary formatting codes in a variable named message. In a production application, the text would come from some external source like a database. It then processes the text with the <foo:htmlFormat> custom action. Below is shown the tag file that implements the <foo:htmlFormat> custom action:

XML Code: Custom Action for processing the body - &lt;foo.htmlFormat&gt;
<%@ tag body-content="scriptless" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%-- Capture the body evaluation result in a variable --%>
<jsp:doBody var="bodyRes" />

<%-- Convert special characters to character entities --%>
<c:set var="escapedBody" value="${fn:escapeXml(bodyRes)}" />

<%-- Replace code and /code in brackets with "<pre>/</pre>" --%>
<c:set var="convBody" 
  value="${fn:replace(escapedBody, 'code', '<pre>')}" />
<c:set var="convBody" 
  value="${fn:replace(convBody, '/code', '</pre>')}" />

<%-- Output the result --%>
${convBody}
In the listing above the tag directive sets the body-content attribute to scriptless. So the web designer can put template text, standard actions and custom actions in the body but not scripting elements (i.e., Java code). Next there is the <jsp:doBody> standard action. This action can only be used in tag files. It evaluates the body of the custom action element including all action elements in the body that are called and produces output that is mixed with the template text. In our page, the result is saved in a variable through the use of the var attribute to name the optional variable. You could also use the varReader attribute as an alternative. Otherwise if you don't specify any of these attributes, the result will be added to the page invoking the custom action. The attributes for the <jsp:doBody> standard action is shown below:

Tutorial:In Depth Look at JSP Custom Tags for the Web Component Developer Exam-a24-attributesdobodytag.jpg
Table: Attributes for <jsp:doBody> Custom Action

As previously mentioned there are two attributes that can be used for capturing the results of the evaluation of the <jsp:doBody>; var and varReader. The differences between the var and varReader attributes is down to the type of Java object that is used for capturing the result. The var attribute captures it as a String while the varReader attribute captures it as a java.io.Reader object. In most cases, the var attribute will be sufficient for most of your needs. For large results, the varReader will be slightly more efficient especially if combined with an action or function for the transformation that can read its input from a Reader. In addition to the var or varReader, you can also specify the scope for the variable using the scope attribute.

Next the tag file transforms the captured body by the fn:escapeXml( ) JSTL function used to convert all special characters to character entity codes and then by replacing all occurrences of code and forward slash code in brackets with HTML <pre> and </pre> tags using the JSTL fn:replace( ) function. The fn:replace() function is used to preserve formatting in these sections. The last EL expression takes the converted body evaluation result and adds it to the calling page.

Processing Custom Action Fragment Attributes

One of the nice things about custom action body is just a special case of a JSP fragment. A JSP fragment, which is part of the JSP specification, is an executable representation of a set of actions and EL expressions, often combined with template text. When a tag file invokes a JSP fragment, all the actions and EL expressions in the fragment are executed. The results will differ from one invocation to another since the tag file can invoke it numerous times and the elements have access to the current values of all scoped variables. In the htmlFormat.tag, the <jsp:doBody> action invokes the special fragment representing a custom action element body. You have the option of providing named fragments as custom action attributes that are invoked by the tag file. You use the <jsp:invoke> action in order to produce the JSP fragment. The attributes for <jsp:invoke> are shown below:

Tutorial:In Depth Look at JSP Custom Tags for the Web Component Developer Exam-a24-attributesinvoketag.jpg
Table: Attributes for <jsp:invoke> Custom Action

To demonstrate the use of named fragment, we will create a custom action that loops through all the elements of a collection and insert them into an HTML table. We will also vary toggle the rendering of even and odd rows. Below is the JSP Page that demonstrates using a custom action with separate fragment attributes for even and odd rows:

XML Code: Custom Action with Separate Fragments
<%@ page contentType="text/html" %>
<%@ taglib prefix="ft" tagdir="/WEB-INF/tags/footags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
  <head>
    <title>Even and Odd Rows</title>
  </head>
  <body bgcolor="white">
    <h1>Even and Odd Rows</h1>
    <table>
      <ft:forEvenAndOdd items="v,w,x,y,z">
        <jsp:attribute name="even">
          <c:set var="count" value="${count + 1}" />
          <tr bgcolor="red"><td>${count}: Even Row</td></tr>
        </jsp:attribute>
        <jsp:attribute name="odd">
          <c:set var="count" value="${count + 1}" />
          <tr bgcolor="blue"><td>${count}: Odd Row</td></tr>
        </jsp:attribute>
      </ft:forEvenAndOdd>
    </table>
  </body>
</html>
In this listing, the fragment attribute value is defined using the <jsp:attribute> action. The <jsp:attribute> actionís body makes up the content of the fragment. Each fragment attribute value has the <c:set> action for incrementing the count and HTML table row as well as the cell elements for showing the countís value plus static text showing either "Even Row" or "Odd Row". The fragments also toggles the row background colors to make the differences clear. The current value of the page scope variable, count is used for each new row, and determines how the odd and even fragments are toggled. The example below, shows the tag file for the <ft:forEvenAndOdd> custom action.


XML Code: Using fragment attributes
<%@ tag body-content="empty" %>
<%@ attribute name="items" rtexprvalue="true" required="true" %>
<%@ attribute name="even" fragment="true" required="true" %>
<%@ attribute name="odd" fragment="true" required="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<c:forEach items="${items}" varStatus="status">
  <c:choose>
    <c:when test="${status.count % 2 == 0}">
      <jsp:invoke fragment="even" />
    </c:when>
    <c:otherwise>
      <jsp:invoke fragment="odd" />
    </c:otherwise>
  </c:choose>
</c:forEach>
In the listing for the custom action, first we have the tag directive specifying the body must be empty. It must only contain the <jsp:attribute> elements and no template text of other elements. This tag is considered an alternative to using regular element attributes. Web container can use executable fragments as an attribute value when you declare the attribute as an executable fragment. In the listing, the attribute directive's fragment attribute is set to true for both the even and odd attributes. Else if not, the web container evaluates the <jsp:attribute> body only once and then sets the attribute to the resulting value. After the directives in the top of the listing, we use the JSTL actions <c:forEach>, <c:choose> and <c:when> are used for looping through the list of items, toggle from even to odd rows and then use the <jsp:invoke> action to invoke the appropriate fragment.

Using Variables to Expose Data to the Calling Page

With custom actions, attributes are used as a means of input, however there are times when you need to provide the page in which the custom action is located access to data generated by the custom action. This is the case for the <ft:forEvenAndOdd> action where unless the page can access the current iteration value in the fragments for even and odd rows, the action would be useless. This can be managed by passing data from a custom action to the caller by exposing it through declared variables. This has been done in an updated version of the forEvenAndOdd tag file. This version exposes the current iteration value as a variable named thisRow. This is shown below:

XML Code: Exporting Data through Variables with forEvenAndOdd2.tag
<%@ tag body-content="empty" %>
<%@ attribute name="items" rtexprvalue="true" required="true" %>
<%@ attribute name="even" fragment="true" required="true" %>
<%@ attribute name="odd" fragment="true" required="true" %>
<%@ variable name-given="thisRow" variable-class="java.lang.Object"
  scope="NESTED" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<c:forEach items="${items}" varStatus="status" var="thisRow">
  <c:choose>
    <c:when test="${status.count % 2 == 0}">
      <jsp:invoke fragment="even" />
    </c:when>
    <c:otherwise>
      <jsp:invoke fragment="odd" />
    </c:otherwise>
  </c:choose>
</c:forEach>
Here we use the variable directive to declare the variable, thisRow. This is done in the name-given attribute which is used to specify the name. The variable-class attribute is used to specify the type. In the listing, we use java.lang.Object. We use this class, the most generic class possible, since we will be iterating over a collection containing elements of an unknown type. The thing is to provide the scope attribute. The scope attribute accepts one of three values
  • AT_BEGIN - the variable will be visible to the caller immediately after the start tag for the custom action element.
  • AT_END - the variable is visible after the end tag
  • NESTED - the variable is only visible between the start and end tags

It will control where the variable will be located and visible to the caller. The name has relation with the page, request, session or application scopes. A more precise name for this attribute would have been visibility.

Making the data visible to the caller involves setting a page scope variable by the tag file with the name declared by the variable directive. As the tag file has its own page scope, separate from the caller, this will involve a bit of work by the web container for this to work. When a variable declared as AT_BEGIN or NESTED, the web container copies the variable value from the tag file's page scope to the caller's page scope before invoking the fragment. When a variable is declared as AT_BEGIN or AT_END, the web container will make a copy of the variable value before it exits the tag file. When a variable is declared as NESTED, if there are any page scoped variables in the caller page with the same name, the web container will save and restore itís value before entering and exiting the tag file.

In the listing, the tag file exposes a variable called thisRow that is used as an iteration value. This local variable is set indirectly using the var attribute of the <c:forEach> action. The <c:forEach> action uses the thisRow iteration value as the page scope variable named by the var attribute. Using thisRow as the name of the <c:forEach> variable, the variable value set by the <c:forEach> action is also exposed to the caller. In a new version of the tag file, I use it to display the thisRow iteration value for each row:

XML Code: Version 2 of forEvenAndOdd2.tag
<%@ page contentType="text/html" %>
<%@ taglib prefix="my" tagdir="/WEB-INF/tags/mytags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
  <head>
    <title>Even and Odd Rows</title>
  </head>
  <body bgcolor="white">
    <h1>Even and Odd Rows</h1>
    <table>
      <ft:forEvenAndOdd2 items="a,b,c,d,e">
        <jsp:attribute name="even">
          <c:set var="count" value="${count + 1}" />
          <tr bgcolor="red"><td>${count}: Even Row: ${thisRow}</td></tr>
        </jsp:attribute>
        <jsp:attribute name="odd">
          <c:set var="count" value="${count + 1}" />
          <tr bgcolor="blue"><td>${count}: Odd Row: ${thisRow}</td></tr>
        </jsp:attribute>
      </my:forEvenAndOdd2>
    </table>
  </body>
</html>
In this listing we have exposed variable for use in EL expressions in both fragments.
As the exposed variable name is hardcoded into the tag file, this can create problems. A better means of exposing the variable would be if the variable name is specified using an attribute similar to choosing a name with the var attribute for a JSTL action that exposes data. In the next example, we solve this problem by using the name-from-attribute and alias attributes of the variable directive. The name-from-attribute is an attribute whose value is the name of the custom action attribute used to name the variable. This is shown in the listing below:

XML Code: Variable Name Version of forEvenAndOdd3.tag
<%@ tag body-content="empty" %>
<%@ attribute name="items" rtexprvalue="true" required="true" %>
<%@ attribute name="var" rtexprvalue="false" required="true" %>
<%@ attribute name="even" fragment="true" required="true" %>
<%@ attribute name="odd" fragment="true" required="true" %>
<%@ variable name-from-attribute="var" alias="thisRow"
  variable-class="java.lang.Object" scope="NESTED" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<c:forEach items="${items}" varStatus="status" var="thisRow">
  <c:choose>
    <c:when test="${status.count % 2 == 0}">
      <jsp:invoke fragment="even" />
    </c:when>
    <c:otherwise>
      <jsp:invoke fragment="odd" />
    </c:otherwise>
  </c:choose>
</c:forEach>
In this case, the named attribute, var is declared as required and cannot accept request time value. Also the alias attribute value is used to declare the name of the tag file's local page scope variable. The web container copies this value to the callerís page scope. Unfortunately we cannot do with this aliasing trick since the web designer can assign any name for the variable it wants when they use the custom action although a fixed name must be used while developing the tag file. In the next listing we show how to specify the variable name in the calling page:

XML Code: Variable Name Version of forEvenAndOdd3.tag
<%@ page contentType="text/html" %>
<%@ taglib prefix="my" tagdir="/WEB-INF/tags/mytags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
  <head>
    <title>Even and Odd Rows</title>
  </head>
  <body bgcolor="white">
    <h1>Even and Odd Rows</h1>
    <table>
      <ft:forEvenAndOdd3 items="a,b,c,d,e" var="anyName">
        <jsp:attribute name="even">
          <c:set var="count" value="${count + 1}" />
          <tr bgcolor="red"><td>${count}: Even Row: ${anyName}</td></tr>
        </jsp:attribute>
        <jsp:attribute name="odd">
          <c:set var="count" value="${count + 1}" />
          <tr bgcolor="blue"><td>${count}: Odd Row: ${anyName}</td></tr>
        </jsp:attribute>
      </my:forEvenAndOdd3>
    </table>
  </body>
</html>
Aborting Processing Through Forward or Redirect

There are times where it might be necessary to abort the page processing similar to a <jsp:forward> action or a JSTL <c:redirect> action which shifts processing from the current page to the page specified by the page attribute, effectively aborting processing of the thisRow page. You can easily achieve the same thing using custom actions. Although there is no directive or similar mechanism for a tag file to use to explicitly abort processing, but you can also use the <jsp:forward>, <c:redirect>, or create a specific custom action to achieve the same effect of aborting page processing within a tag file. In this case, the tag file processing as well as the processing of the page invoking the tag file stop after it aborts the processing. This feature can be developed to provide smart forwarding action that forwards to a particular page based on runtime conditions (i.e. type of browser, the user, etc).

Packaging Tag Files

From the previous article, ďTutorial:Review of JSP Tag Libraries for the Web Component Developer ExamĒ, we have seen it is very easy to deploy a tag library packaged as a JAR file. You only need to put the JAR file in the WEB-INF/lib directory and then use the default URI as the uri attribute value in the taglib directive. As well, it is equally easy to package your tag library as tag files. In this case, you will need to create a Tag Library Descriptor (TLD) and include it in the JAR file. Below is an example of a TLD based on the tags we have created in this article:

XML Code: TLD for Tag Files
<?xml version="1.0" encoding="ISO-8859-1" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
    http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
  version="2.0">

  <tlib-version>1.0</tlib-version>
  <short-name>ft</short-name>
  <uri>footaglib</uri>

  <tag-file>
    <name>copyright</name>
    <path>/META-INF/tags/footags/cpyrt.tag</path>
  </tag-file>

  <tag-file>
    <name>forEvenAndOdd</name>
    <path>/META-INF/tags/footags/forEvenAndOdd.tag</path>
  </tag-file>

  <tag-file>
    <name>htmlFormat</name>
    <path>/META-INF/tags/footags/htmlFormat.tag</path>
  </tag-file>
</taglib>
As we have mentioned in the previous article, the TLD is an XML document. The first elements provide information about the tag library itself. Next the <tlib-version> element tell us the version of this tag library and the <short-name> element has the default namespace prefix for the library. These elements are useful for an authoring tool to use the default namespace prefix when it generates the taglib directive and action elements. You still have the flexibility to choose different prefixes to suit your needs.

The next element is the <uri> element. This element declares the default URI for the library. The serves as the uri attribute value for the taglib directive in JSP pages that take advantage of the auto-deploy feature.

Next part is the <tag-file> element for each tag file. Within each <tag-file> element is a <name> element providing the name for the custom action and often matching the filename minus the .tag extension and then the <path> element that contains the path within the JAR file to the tag file. All <path> elements must start with /META-INF/tags/ since the TLD file must be located in the /META-INF directory within the JAR file. For our tags files, the directory structure like this for the tag files and the TLD:

Tutorial:In Depth Look at JSP Custom Tags for the Web Component Developer Exam-a24-meta-inf_dirstruct.jpg
Figure: META-INF Directory Structure for Tag Files and TLDs

In order to create the JAR file with your tags files and the TLD file, you will need to use the the jar command. It is included as part of the Java SDK. The command for doing this is the following:

Java Code: Jar Command to Archive Tag Files
C:\> jar cvf footags.jar META-INF
This creates a JAR file named footags.jar containing the contents of the META-INF directory structure. You now place this JAR file in the WEB-INF/lib directory of the web application using the library. You restart the web container. On restart, the web container will locate the JAR file and TLD. Now your JSP pages can use the tag library by adding the taglib directive:

XML Code: Taglib Directive for FooTags
<%@ taglib prefix="ft" uri="footags" %>
You also have the flexibility to use the TLD to identify tag files that are placed directly in the filesystem rather than being packaged in a JAR file. In this case, you can use the uri attribute instead of the tagdir attribute for the taglib directive. In this case you put the tag files under WEB-INF/tags in the proper subdirectory as was shown in the figure at the beginning of the article and you place the TLD in the WEB-INF directory in the proper subdirectory as well. This is shown in the following figure:

Tutorial:In Depth Look at JSP Custom Tags for the Web Component Developer Exam-a24-tagtlddirstruct.jpg
Figure: Directory Structure for Tag Files and TLDs

Here the <path> elements in the TLD are used to specify the context-relative path to the tag files in the filesystem. The rest of the TLD stays the same as the listing above:

XML Code: Section of TLD Showing Change to &lt;path&gt;
<tag-file>
    <name>copyright</name>
    <path>/WEB-INF/tags/footags/cpyrt.tag</path>
  </tag-file>
OK. Thatís it for the custom tags and the web component developer exam. You should now be in a position to do some mock exams and complete the real exam with no problem.