Click here to Skip to main content
Click here to Skip to main content

JSP - JSTL Custom Tag Library

, 8 Dec 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
JSP custom tags provide a standardized mechanism for separating the presentation and business logic in a dynamic web page, allowing page designers to focus on the presentation while application developers code the backend.

JSP Custom Tags

JSP custom tags provide a standardized mechanism for separating the presentation and business logic in a dynamic web page, allowing page designers to focus on the presentation while application developers code the backend. They are just Java classes that implement special interfaces. Once a custom tag is developed and deployed, its actions can be called from your HTML using an XML syntax. There is a start tag and an end tag. The tag may or may not have a body. A custom tag can be expressed as:

<tagLibrary:tagName attribute="value">
       body
</tagLibrary:tagName>

Benefits of Custom Tags

A very important thing to note about JSP custom tags is that they does not offer more functionality than scriptlets. They simply provide better packaging, by helping us improve the separation of the business logic and the presentation logic. Some of the benefits of a custom tag are:

  • It can reduce or eliminate scriptlets in our JSP applications. Any necessary parameters to the tag can be passed as attributes or as body content, and therefore no Java code is needed to initialize or set component properties.
  • It has a simpler syntax. A scriptlet is written in Java, but a custom tag can be used in an HTML-like syntax.
  • It can improve the productivity of nonprogrammer content developers, by allowing them to perform tasks that cannot be done with HTML.
  • It is reusable. It saves development and testing time. A scritplet is not reusable, unless we do cut-and-paste reuse.

Implementing JSP Custom Tags

There are a few steps involved in developing a custom tag. These steps can be summarized as follows:

  1. Write the tag handler class.
  2. Create the tag library descriptor (TLD).
  3. Make the TLD file and handler classes accessible.
  4. Reference the tag library.
  5. Use the tag in a JSP page.

Step 1. Write the tag handler class

The first thing we need to do is write the tag handler class. A tag handler is an object invoked by the JSP runtime to evaluate a custom tag during the execution of a JSP page that references the tag. The methods of the tag handler are called by the implementation class at various points during the evaluation of the tag. All tags must implement the Tag interface. We do not need to include the body content in our example TodayTag, because it only displays the current date in the user defined format. As such, our handler class will implement the Tag interface (typically by extending the TagSupport class). If we were to create a tag capable of processing body content, we would need to implement the BodyTag interface (typically by extending the BodyTagSupport class).

package jstl;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;

/**
 * @author Bikash Shaw
 */
public class TodayTag extends TagSupport{
    private String mFormat;
    
    public void setFormat(String pFormat) {
        mFormat = pFormat;
    }
    
    
    public int doStartTag() throws JspException {
        try {
            JspWriter out = pageContext.getOut();
            Date today = new Date();
            SimpleDateFormat dateFormatter = new SimpleDateFormat(mFormat);
            out.print(dateFormatter.format(today));
            
        } catch(IOException ioe) {
            throw new JspException("Error: " + ioe.getMessage());
        }       
        return SKIP_BODY;
    }
    
    
    public int doEndTag() throws JspException {
        return SKIP_PAGE;
    }
}

Step 2. Create the tag library descriptor (TLD)

Our next step is to define the library that will contain the mappings between our custom tag and the Java class (or classes) that will handle it. This library is defined within an XML document called a tag library descriptor (TLD). We'll call the TLD for our custom tag examples, customTag.tld.

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" 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 web-jsptaglibrary_2_0.xsd">
  <tlib-version>1.0</tlib-version>
    <short-name>ct</short-name>
    <uri>/WEB-INF/customTag</uri>
    <tag>
        <name>today</name>
        <tag-class>jstl.TodayTag</tag-class>
        <body-content>empty</body-content>
        <info>This Tag Displayes current server date in usser defined format</info>
        <attribute>
            <name>format</name>
            <required>true</required>
            <description>Provide a display format</description>
            <rtexprvalue>false</rtexprvalue>
        </attribute>
    </tag>
</taglib>

All key information is contained within the Tag tag where the tag name and the handler class are mapped. In more complex cases, we could use additional XML tags to provide more information about the library and about the tags. It is also typical to define multiple tags within a single library.

Step 3. Make the TLD file and handler classes accessible

The third step is to make the class or classes and TLD accessible to the web application. There are two ways of doing this. We can either package the classes and the TLD together into a JAR file and then store the JAR file in the web application's lib directory, or we can place the class files loosely in the classes subdirectory and place the TLD file somewhere beneath the web application's WEB-INF directory.

Step 4. Reference the tag library

The fourth step is to make the class or classes and TLD accessible to the web application. In order to use the tag, we have to reference it, and this can be done in three ways:

  1. Reference the tag library descriptor of an unpacked tag library. For example:
  2. <%@ taglib uri="/WEB-INF/customTag.tld" prefix="ct" %>
  3. Reference a JAR file containing a tag library. For example:
  4. <%@ taglib uri="/WEB-INF/lib/customTag.jar" prefix="ct" %>
  5. Define a reference to the tag library descriptor from the web-application descriptor (web.xml), and define a short name to reference the tag library from JSP.
  6. <taglib>
        <taglib-uri>customTag</taglib-uri>   
        <taglib-location>/WEB-INF/customTag.tld</taglib-location>      
    </taglib>

    Next, we add a JSP declaration to any page that will need to use the custom tag library:

    <%@ taglib uri="customTag" prefix="ct" %>

Step 5. Use the tag in a JSP page

Now, we're ready to use our custom tag within a JSP page.

<%@ taglib uri="/WEB-INF/customTag.tld" prefix="ct" %>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">

<html>
  <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSTL Custom Tag Today</title>
  </head>
  <body>
        <h2 align="center"><ct:today format="MMMM dd, yyyy"/></h2>
  </body>
</html>

The results should look similar to the figure shown below:

JSTL-TodayTag.png

Parameterized Tags

There are two things that need to be mentioned to handle attributes to develop parameterized tags:

  1. Add a set method in the tag handler
  2. Add a new tag to customTag.tld

We can refer to the highlighted section of our previous example.

Tags with a body

A tag handler for a tag with a body is implemented differently depending on whether the body needs to be evaluated once or multiple times.

  • Single Evaluation: If the body needs to be evaluated once, the tag handler should implement the Tag interface, or extend the TagSupport abstract class; the doStartTag method needs to return EVAL_BODY_INCLUDE, and if it does not need to be evaluated at all, then it should return BODY_SKIP.
  • Multiple Evaluation: If the body needs to be evaluated multiple times, the BodyTag interface should be implemented. The BodyTag interface extends the Tag interface, and defines additional methods (setBodyContent, doInitBody, and doAfterBody) that enable a tag handler to inspect and possibly change its body. Alternatively, and similar to the TagSupport class, we can extend the BodyTagSupport class, which provides default implementations for the methods in the BodyTag interface. Typically, we need to implement doInitBody and doAfterBody methods. The doInitBody is called after the body content is set but before it is evaluated, and the doAfterBody is called after the body content is evaluated.

Single Evaluation

Here is an example of a single evaluation where we extend the BodyTagSupport class. This example reads the body content, and converts it to uppercase or lowercase depending on the attribute provided by us.

At first, we need to create the tag handler class:

package jstl;

import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;

/**
 *
 * @author Bikash Shaw
 */
public class ChangeCaseTag extends BodyTagSupport {

    private String mCase;

    public void setCase(String pCase) {
        mCase = pCase;
    }

    
    public int doAfterBody() throws JspException {
        try {
            BodyContent bc = getBodyContent();
            String body = bc.getString();
            JspWriter out = bc.getEnclosingWriter();
            if (body != null) {
                if ("upper".equalsIgnoreCase(mCase)) {
                    out.print(body.toUpperCase());
                } else {
                    out.print(body.toLowerCase());
                }
            }
        } catch (IOException ioe) {
            throw new JspException("Error: " + ioe.getMessage());
        }
        return SKIP_BODY;
    }
}

The next step is to add a tag to the tag library descriptor file, customTag.tld:

<taglib version="2.0" 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 web-jsptaglibrary_2_0.xsd">
<tlib-version>1.0</tlib-version>
<short-name>ct</short-name>
<uri>/WEB-INF/customTag</uri>
    <tag>
        <name>changeCase</name>
        <tag-class>jstl.ChangeCaseTag</tag-class>
        <body-content>JSP</body-content>
        <info>This Tag Displayes current server date in user defined format</info>
        <attribute>
            <name>case</name>
            <required>true</required>
            <description>Provide the case upper or lower</description>
            <rtexprvalue>false</rtexprvalue>
        </attribute>
    </tag>
</taglib>

Note that when you write a tag with a body, the <body-content> tag's value must be either JSP or jspcontent.

Now, a test driver for this example is shown below:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
  <%@ taglib uri="/WEB-INF/customTag.tld" prefix="ct" %>
  <html>
      <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>Upper or Lower Case</title>
      </head>
      <body>
        <h2>
            Upper Case : 
              <ct:changeCase case="upper">
            Hello World
              </ct:changeCase>
        </h2>
        <h2>
            Lower Case : 
            <ct:changeCase case="lower">
                Hello World
            </ct:changeCase>
        </h2>
      </body>
  </html>

The results should look similar to the figure shown below:

JSTL-UpperLowerCase.png

Multiple Evaluation

Let's now see an example of a body tag evaluated multiple times. The example tag accepts an integer as its attribute, and prints its body HTML as many times as indicated in the JSP code.

Once again, create a tag handler class first:

package jstl;

import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTagSupport;

/**
 *
 * @author Bikash Shaw
 */
public class LoopTextTag extends BodyTagSupport {

    private int mTimes = 0;
    private BodyContent mBodyContent;

    public void setTimes(int pTimes) {
        mTimes = pTimes;
    }

    
    public void setBodyContent(BodyContent pBodyContent) {
        mBodyContent = pBodyContent;
    }

    
    public int doStartTag() throws JspException {
        if (mTimes > 1) {
            return EVAL_BODY_TAG;
        } else {
            return SKIP_BODY;
        }
    }

    
    public int doAfterBody() throws JspException {
        if (mTimes > 1) {
            mTimes--;
            return EVAL_BODY_TAG;
        } else {
            return SKIP_BODY;
        }
    }

    
    public int doEndTag() throws JspException {
        try {
            if (mBodyContent != null) {
                mBodyContent.writeOut(mBodyContent.getEnclosingWriter());
            }
        } catch (IOException pIOEx) {
            throw new JspException("Error: " + pIOEx.getMessage());
        }
        return EVAL_PAGE;
    }
}

The methods of this tag perform the following roles:

  • The doStartTag method gets called at the start of the tag. It checks if the loop needs to be performed.
  • The setBodyContent is called by the JSP container to check for more than one loop.
  • The doAfterBody method is called after each evaluation; the number of times the loop needs to be performed is decreased by one, then it returns SKIP_BODY when the number of times is not greater than one.
  • The doEndTag method is called at the end of the tag, and the content (if any) is written to the enclosing writer.

Similar to the previous examples, the next step is to add a new tag descriptor to customTag.tld:

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" 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 web-jsptaglibrary_2_0.xsd">
<tlib-version>1.0</tlib-version>
<short-name>ct</short-name>
<uri>/WEB-INF/customTag</uri>
    <tag>
        <name>loopText</name>
        <tag-class>jstl.LoopTextTag</tag-class>
        <body-content>JSP</body-content>
        <info>This Tag Displayes given text multiple times</info>
        <attribute>
            <name>times</name>
            <required>true</required>
            <description>Provide number of times the text will be repeated</description>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
    </tag>
</taglib>

Note that the <rtexprvalue> tag is true, which specifies that evaluations will be performed at runtime.

Finally, we write a sample JSP page to test the <loopText> tag.

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="/WEB-INF/customTag.tld" prefix="ct" %>
<html>
    <head>
        <meta http-equiv="Content-Type" 
           content="text/html; charset=UTF-8">
        <title>JSTL Custom Tag Loop Text</title>
    </head>
    <body>
        <center>

            <ct:loopText times="5">
                <h3>Loop Text!</h3>
            </ct:loopText>

        </center>
    </body>
</html>

The output should look similar to the figure shown below:

JSTL-LoopText.png

Conclusion

Custom tags help us improve the separation of program logic and presentation. The various examples in this article show how to develop and deploy simple and advanced custom tags. Also, you may wish to look at what the Jakarta Taglibs Project has to offer for various custom tag libraries. For more information, you can refer to the following websites:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Bikash Shaw
Software Developer (Senior) Société Générale
India India
Summary:
 
1. Extensive working experience in web and windows application development, database programming using Java and .Net technologies.
 
2. Good knowledge in SDLC and Processes like project planning, requirement gathering, development, test planning, release management and production support.
 
3. Good knowledge and working experience in following methodologies:
a. Agile Development Approach
b. Test Driven Development
c. Behavior Driven Development
d. Continuous Integration & Delivery Model.
 
4. Excellent communication & analytical skills, good team player, great mentoring capability.
 
5. Interaction with customer and team spread over different geographical area.
 
Technologies / Languages: J2SE 5/6, J2EE, .Net 2.0/3.5, C#, ASP.NET, AJAX, XHTML, CSS, JavaScript, jQuery, PL/SQL, Web Services (SOAP based), Winforms, Hibernate, Spring, GWT, XML, XSD, XPath, SAX, JAXB, JUnit, JBehave, Mockito, Selenium, StringTemplate, Log4J, Apache Commons API
 
Database: Oracle, SQL Server, MySQL, Sybase
 
Application Server: Tomcat, Sun Application Server, JBoss, GlassFish, Jetty, IIS
 
Development Environments: Eclipse, NetBeans, Visual Studio.
 
Designing Tools: Enterprise Architect, Microsoft Visio
 
Version Control: SVN, Perforce
 
Build Management: Hudson & JCruisemonitor, TeamCity
 
Bug Tracking Tools: HP Quality Center, Bugzilla, JIRA
 
Specialties:
1. Agile Test and Behavior Driven Development
2. Continuous Delivery Approach
2. Spring IOC and MVC
3. Web Services
Follow on   Twitter

Comments and Discussions

 
GeneralMy vote of 5 Pinmembershivasoft17-Mar-11 20:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.1411028.1 | Last Updated 9 Dec 2008
Article Copyright 2008 by Bikash Shaw
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid