April 15, 2010

Custom Tags and Custom EL Functions in JSP Pages

What is a Custom Tag?

A Custom Tag is a generic term for simplifying or eliminating Java code inside JSP pages (eg. eliminating scriptlets). A typical custom tag looks like this:

<myTagLibrary:doSomething/>

What is a Custom EL Function?

A Custom EL Function is a method that you can invoke using the JSP Expression Language. A typical Custom EL Function looks like this:

${myTagLibrary:randomColor()}

In order to create a Custom Tag or a Custom EL Function you will need two things:

  1. A Java class to define what the Custom Tag or Custom El Function will do
  2. A TLD file in which will specify the Java class and method to use, and how your Custom Tag or El Function will be called.

Creating the TLD file

Here is a TLD file which will defines an EL Function and a Custom Tag. We're going to call this file funkytaglibrary.tld.

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" 
"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<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/web-jsptaglibrary_2_0.xsd"
    version="2.0">
  
 <tlib-version>1.0</tlib-version>
    <short-name>MyLibrary</short-name> <!-- Used for tools to display -->
    <uri>FunkyTagLibrary</uri>         

    <!-- Define a Custom EL Function -->
    <function>
        <name>randomColor</name> <!-- Will be used to call your El Function:   ${myTagLibrary:randomColor()} inside your JSP page -->
        <function-class>foo.RandomColorGenerator</function-class>
        <function-signature>String pickRandomColor()</function-signature>
    </function>
 
    <!-- Define a Custom Tag -->
    <tag>
        <description>This tag prints a random number.</description>
        <name>randomNumber</name>   <!-- Will be used to call your tag  <myTagLibrary:randomNumber greaterThan="2"/> -->
        <tag-class>foo.RandomNumberGenerator</tag-class>
        <body-content>empty,scriptless,tagdependent or JSP</body-content>
        
        <!-- If your Custom Tag has attributes you will define them here --> 
        <attribute>
            <name>greaterThan</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>     <!-- if true, you can have things like ${myNumber} as the attribute value -->
        </attribute>
           
    </tag>
</taglib>

Your JSP file will have to contain the following directive to make use of this TLD file
<%@ taglib prefix="myTagLibrary" uri="FunkyTagLibrary" %>

Creating the Java class

In order to implement the functionality of the Custom Tag or Custom EL Function defined in the TLD field above, you also have to have a Java class for each.

Class for implementing the custom EL Function randomColor()


package foo;  

public class RandomColorGenerator{
 public static String pickRandomColor(){   //notice that this method doesn't have to be  the same as the one that will apear in your tag 'randomColor'. This is only true for a class that implements a Custom El Function.
  String [] colors = new String[3];
  colors[0] = 'Red';
  colors[1] = 'Blue';
  colors[2] = 'Yellow';
        return color[Math.abs(r.nextInt()) % 4]; //return one of the colors in array at random
    }
}

In order to implement the functionality of the Custom Tag or Custom EL Function defined in the TLD field above, you also have to have a Java class for each.

Class for implementing the custom tag functionality

Some people refer to a class that implements a custom tag functionality as a Tag Handler


package foo;
public javax.servlet.jsp.JspException;  
public javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;

public class RandomNumberGenerator extends SimpleTagSupport{
 private String greaterThan; //stores the value of the greaterThan attribute of the custom tag

 @Override
 public void doTag() throws JspException, IOException{ //this is the method that is called when the custom tag  is called from a JSP page 
  int randomNumber = (int)Math.random() * (greaterThan+1); //generate a random number, which is greater than the 'greaterThan' attribute's value 
  getJspContext().getOut().write(randomNumber); 
 }

 public void setGreaterThan(int number){ //the method name must match the attribute name defined in the TLD file
  greaterThan = number;
  } 
 }
}

Where do I put the TLD file?

In order for the Servlet Container to find the TLD file and use it, you can put the funkytaglibrary.tld in any of the following locations:

  • WEB-INF/funkytaglibrary.tld
  • WEB-INF/subfolder/funkytaglibrary.tld
  • WEB-INF/lib/mylibrary.jar -> META-INF/funkytaglibrary.tld //inside the META-INF folder of your jar file
  • WEB-INF/lib/mylibrary.jar -> META-INF/subfolder/funkytaglibrary.tld //inside a META-INF sub folder of your jar file

Calling the Custom Tag and Custom EL Function from JSP

test.jsp

<html>
 <body>
  <%-- call your custom el function --%>
  Here is a random color: ${myTagLibrary:randomColor()}.

  <%-- call your custom tag --%>
  Here is a random number: <myTagLibrary:randomNumber greaterThan="10"/> 
 </body>
</html>