Custom JSP tags

In this part of the JEE tutorials we will talk about custom tags.

A custom tag is a user-defined JSP language element. It is an extension to the JSP language. Custom tags are reusable software components. Custom tags are used to handle common functionality. They also separate programming code from the content. They make the JSP pages look uniform. This way the JSP pages are more maintainable.

Custom tags can be created using:

Tag handlers are Java classes that implement the custom tag. A tag file is a source file containing JSP code that is translated into a simple tag handler by the web container. Same as with JSPs and serlvets.

Tag handlers can be made available to a web application in two basic ways. The classes implementing the tag handlers can be stored in an unpacked form in the WEB-INF/classes/ subdirectory of the web application. Alternatively, if the library is distributed as a JAR, it is stored in the WEB-INF/lib/ directory of the web application.

Empty custom tag

When we started with JavaServer pages, we introduced a simple example that showed the current date. In the following example, we put the Java code into the tag handler and thus, separate the code from the content.

Each custom tag implemented with a tag handler must be declared in a special xml file called tag library descriptor(TLD). The TLD file maps custom tags to their corresponding simple tag handler implementation classes.

index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="d" uri="http://zetcode.com/tlds/date" %>

<html>
    <head>
        <title>Custom tags</title>
        <style>
        * { font-size: 12px; font-family: Verdana }
        </style>
    </head>
    <body>
        <h2>Date</h2>
        <b>Today's Date: </b> <d:DateTag />
    </body>
</html>

This is the JSP file that will output the current date.

<%@taglib prefix="d" uri="http://zetcode.com/tlds/date" %>

The taglib directive will enable us to use the custom tag in this JSP page. The URI parameter is a unique identifier for the tag library. In the previous versions of the JSP technology, developers had to edit the web.xml file. Today this is not necessary. The container will automatically map the URI with the corresponding TLD. The URI must be unique within the application. The taglib directive also specifies the prefix, used in our custom tag.

<b>Today's Date: </b> <d:DateTag />

Here we use our custom tag. This tag displays current date and time. The DateTag is the name of the custom tag, specified in the date.tld file. We have a tag with empty body, so there is ending tag.

date.tld
<?xml version="1.0" encoding="UTF-8"?>

<taglib>
  <tlib-version>1.0</tlib-version>
  <jsp-version>2.0</jsp-version>
  <short-name>d</short-name>
  <uri>http://zetcode.com/tlds/date</uri>

  <tag>
    <name>DateTag</name>
    <tag-class>com.zetcode.DateTagHandler</tag-class>
    <body-content>empty</body-content>
  </tag>

</taglib>

This is the tag library descriptor, for our example. In the tag element, we provide the name of the tag, the Java class that implements the tag. We also specify that our tag has no body. We placed the date.tld file into the WEB-INF/tlds directory.

DateTagHandler.java
package com.zetcode;

import java.util.Date;
import javax.servlet.jsp.tagext.*;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.JspException;


public class DateTagHandler extends SimpleTagSupport {

  public void doTag() throws JspException {

      JspWriter out=getJspContext().getOut();

      try {

          out.println(new Date());

      } catch (java.io.IOException ex) {
          throw new JspException(ex.getMessage());
      }
  }
}

This is the implementation of the tag handler for our custom tag.

out.println(new Date());

We print the current date.

An custom tag
Figure: A custom tag

Tag file

The other way of creating custom tags is using the tag files. The idea is identical to how JSP files are transformed to servlets. Similarly, the tag files are first transformed into the tag handlers and then compiled.

In the next example, we will use custom tags to indicate mandatory and non mandatory fields in an HTML form. Our custom tag will also have an attribute.

index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="t" tagdir="/WEB-INF/tags" %>

<html>
  <head>
    <title>Tag File</title>
    <style>
        * { font-size: 12px; font-family: Verdana }
        input, textarea { border: 1px solid #ccc }
    </style>
  </head>
  <body>  

   <div style="width:400px">
   <center>
   <form>   
     <table>
       <tr>
         <td><t:field text="Name" mandatory="yes" /></td>
         <td><input type="text" name="from"></td>
       </tr>
       <tr>
       <tr>
         <td><t:field text="Email" mandatory="no" /></td>
         <td><input type="text" name="to"></td>
       </tr>
       <tr>
         <td><t:field text="Message" mandatory="yes" /></td>
         <td><textarea cols="25" rows="8" name="message"></textarea></td>
       </tr>
   </table>
   <br>
   <input type="submit" value="submit">
   </form>
   </center>
   </div>
  </body>
</html>

This is the JSP file where we use our custom tag.

<%@taglib prefix="t" tagdir="/WEB-INF/tags" %>

The prefix attribute defines the prefix that distinguishes tags defined by a given tag library from other tag libraries. The tagdir attribute identifies the location of the tag library. The value of the attribute must start with /WEB-INF/tags/.

<td><t:field text="Name" mandatory="yes" /></td>

The custom tag creates a text field in the HTML form. It is a mandatory field, so we will see an asterix.

field.tag
<%@tag description="normal or mandatory fields" pageEncoding="UTF-8"%>


<%@attribute name="mandatory" required="true"%>
<%@attribute name="text" required="true"%>


<%
  if ("yes".equals(mandatory)) {
      out.println(text + "*");
  } else {
      out.println(text);
  }
%>

The tag fiel field.tag is created using the JSP syntax. We placed the field.tag file into the WEB-INF/tags directory. If a tag is implemented as a tag file and ispackaged in WEB-INF/tags/ or a subdirectory, a TLD will be generated automatically by the web container.

TagFile project
Figure: TagFile project
<%@attribute name="mandatory" required="true"%>

This directive creates an attribute for our custom tag. The attribute name is mandatory and it is not optional. We must provide it when we use the custom tag.

if ("yes".equals(mandatory)) {
    out.println(text + "*");
} else {
    out.println(text);
}

Mandatory fields will have an asterix.

A tag file
Figure: TagFile

Random numbers

If we need a custom tag, we might look if it was not already created by someone. Say we want to generate random numbers using custom tags. There is already a library to achieve this. The random tag library from the Jakarta Project. From their web http://jakarta.apache.org/taglibs/ , we download the latest random tag library. The name of the JAR is taglibs-random.jar. We put the JAR file into the WEB-INF/lib directory.

index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>

<%@ taglib uri="http://jakarta.apache.org/taglibs/random-1.0" prefix="rand" %>

<html>
  <head>
      <title>Random</title>
      <style>
          * { font-size: 12px; font-family: Verdana }    
      </style>
  </head>
  <body>
      <h2>Random numbers</h2>
  </body>

  <% for (int i = 0; i < 100; i++) {%>

  <% if (i % 10 == 0) {
       out.println("<br>");
  } %>

  <rand:number id="random1" range="1-100"/>
  <jsp:getProperty name="random1" property="random"/> 

  <% } %>

</html>

In this example, we display 100 random numbers.

<%@ taglib uri="http://jakarta.apache.org/taglibs/random-1.0" prefix="rand" %>

We declare that we use the random tag library in our JSP page. The URI is a unique identifier for the tag library. The container tries to match it against any <taglib-uri> elements in the application's web.xml file or the <uri> element of TLDs in JAR files in /WEB-INF/lib/ or TLDs under WEB-INF.

In our case, the Resin AS will look inside the taglibs-random.jar at the META-INF/tablib.tld file for the URI.

<taglib>
  <taglib-uri>
    http://jakarta.apache.org/taglibs/random-1.0
  <taglib-uri>
  <taglib-location>
    /WEB-INF/tlds/taglibs-random.tld
  <taglib-location>
</taglib>

For older containers, we must edit the web.xml file. We must provide the URI and the taglib location. For newer containers, we need not to copy the taglibs-random.tld. The TLD is already available in the JAR file and the contaner will look it up automatically.

<rand:number id="random1" range="1-100"/>
<jsp:getProperty name="random1" property="random"/> 

Here we create and display a random number in range from 1 .. 100.

In this chapter we have described custom JSP tags.