22 - JSP Custom Tag Library

22.1 Overview of JSLT libraries

In earlier chapters we discussed JSTL libraries provided by JSP specifications. Similarly we can create JSP custom tag libraries as well. Custom tags increase productivity because they can be reused in more than one application.

Custom tags provides a rich set of features like -

· We can pass attributes in tags from calling page to achieve customization.

· Access all the objects available to JSP pages.

To create a custom tag we need three things:

1) TLD file: Tag descriptor file where we will specify our tag name, tag handler class and tag attributes.

2) Tag handler class: Custom class which extends SimpleTagSupport class and contains all the custom logic that should be performed by the tag.

22.2 JSP TLD File

Understanding of TLD is very important when we need to write the custom tags. Information about custom tags are defined in TLD file. Have a look at the sample tld file containing one tag to calculate power of a number.

<?xml version="1.0" encoding="UTF-8"?>
  <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">
    <tlibversion>1.2</tlibversion>  - it is a mandatory tag but value of this tag is optional.
    <shortname>power</shortname> - it is an optional field to assign name.
    <info>Sample taglib for Power operation</info> -it is an optional field to add information
    <uri>http://jsp-tutorial/custom-tags/myTags</uri>- unique name for the custom tag library. There can be only one uri in one tld. 
    This is just a name and not a location 
    <tag> - can have many tags. One per tag in tag library
       <name>power</name> - name of tag
       <tagclass>com.sample.jsp-tutorial.tags.PowerTag</tagclass> - tag handler of this tag
       <body-content>empty | scriptless | tagdependent | JSP</body-content>         
       <attribute> - If your tag has attributes, then one <attribute> element per tag attribute is required.
         <name>base</name> - name of attribute. Tag handler need to define variable and get and set methods
         <required>true</required> - is this attribute is mandatory
         <rtexprvalue>true</rtexprvalue> - can this attribute have expressions?
       </attribute>
       <attribute>
         <name>power</name>
         <required>true</required>
       </attribute>
     </tag>
  </taglib> 

Note : Can a custom tag have a body?

It depends on the value of <body-content> tag. This tag can have four possible values –

a) emptybody is not supported

b) scriptless- The tag must NOT have scripting elements (scriptlets, expressions, and declarations), but it CAN have template text and EL

c) tagdependent- The tag body is treated as plain text, so the EL is NOT evaluated.

d) JSP- means tag body can have anything which we can expect in JSP.

22.3 JSP Tag Handler

Custom class can simply extend SimpleTagSupport class and override the doTag() method. doTag() method gets executed when tag is rendered on JSP, so we can place custom code to generate content for the tag to become a Tag handler.

If any attributes are defined in tld, then those variables are required to define in Tag handler with getter and setter methods.

22.4 tld Locations

There are four places where we can place the tld file in our web applications so that container can load it.

a) Directly inside WEB-INF

b) Directly inside a subdirectory of WEB-INF ( for example WEB-INF\tags\custom.tld)

c) Inside the META-INF directory inside a JAR file that’s inside WEB-INF/lib (for example WEB-INF\lib\jar-file.jar\META-INF\custom.tld)

d) Inside a sub-directory of META-INF inside a JAR file that’s inside WEB-INF/lib (for example WEB-INF\lib\jar-file.jar\META-INF\tags\custom.tld)

22.5 JSP TLD File Example

22.5.1 – Write a custom tag to display welcome message.

Solution –

a) Define myTags.tld file with below content

<?xml version="1.0" encoding="UTF-8"?>
<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">
   <tlibversion>1.2</tlibversion>
   <shortname>Custom Tags</shortname>
   <info>Sample taglib for Custom operation</info>
   <uri>http://localhost:8080/myTags/taglib</uri>
   <tag>
     <name>welcome</name>
     <tagclass>com.sample.jsp.tutorial.tags.WelcomeMessageTagHandler</tagclass>
      <body-content>empty</body-content> 
     <info>Welcome Message </info>
   </tag>
</taglib>

b) Create a tag handler class com.sample.jsp.tutorial.tags.WelcomeMessageTagHandler

package com.sample.jsp.tutorial.tags;
import java.io.IOException;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class WelcomeMessageTagHandler extends SimpleTagSupport{
    @Override
    public void doTag() throws JspException, IOException {
        JspContext context = getJspContext();
        JspWriter out = context.getOut();
        out.println("Hello!! This is the message from Custom Tag .");
    }
}

c) Create a customTags.jsp to invoke the custom tag.

<html>
  <head>
   <title> JSP custom Tag </title>
  </head>
  <%@taglib uri="http://localhost:8080/myTags/taglib" prefix="myTags" %>
  <body>
        <h4>
        <myTags:welcome/>
    </h4>
  </body>
</html>

Note : Text highlighted in same colour means these values must match.

Access customTags.jsp using http://localhost:8080/jsp-tutorial/customTags.jsp

22.5.2 Add one more tag in custom library that allows the body content

Solution :

a) Add below tag in myTags.tld

<tag>
    <name>test-body-content</name>
    <tagclass>com.sample.jsp.tutorial.tags.AllowBodyContentTagHandler</tagclass>
     <body-content>scriptless</body-content> 
    <info>Test Body Content </info>
</tag>

b) Add AllowBodyContentTagHandler class

package com.sample.jsp.tutorial.tags;
import java.io.IOException;
import java.io.StringWriter;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class AllowBodyContentTagHandler extends SimpleTagSupport{
    @Override
    public void doTag() throws JspException, IOException {
        JspContext context = getJspContext();
        JspWriter out = context.getOut();
        JspFragment body = getJspBody();
        StringWriter writer = new StringWriter();
        body.invoke(writer);
    out.println("Hello!! Body of Tag is :: " + writer.toString());
    }
}

d) Add calling of tag in cutomTags.jsp like below

<html>
  <head>
    <title> JSP custom Tag </title>
  </head>
  <%@taglib uri="http://localhost:8080/myTags/taglib" prefix="myTags" %>
  <body>
    <h4>
      <myTags:welcome/>
    </h4>
    <h4>
      <myTags:test-body-content>
      Body Content goes here !!
      </myTags:test-body-content>
    </h4>
  </body>
</html>

Access customTags.jsp using http://localhost:8080/jsp-tutorial/customTags.jsp

22.5.3 Add one more tag in custom library to calculate average of three numbers.

a) Add below tag in myTags.tld

<tag>
    <name>average</name>
    <tagclass>com.sample.jsp.tutorial.tags.AverageCalculatorTagHandler</tagclass>
    <body-content>empty</body-content> 
    <info>Average Calculator </info>
    <attribute>
     <name>input1</name>
     <required>true</required>
     <rtexprvalue>true</rtexprvalue>
    </attribute>
    <attribute>
     <name>input2</name>
     <required>true</required>
     <rtexprvalue>false</rtexprvalue>
    </attribute>
 </tag>

b) Add AverageCalculatorTagHandler tag handler

package com.sample.jsp.tutorial.tags;
import java.io.IOException;
import java.io.StringWriter;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class AverageCalculatorTagHandler extends SimpleTagSupport{
    private int input1;
    private int input2;
    public int getInput1() {
        return input1;
    }
    public void setInput1(int input1) {
        this.input1 = input1;
    }
    public int getInput2() {
        return input2;
    }
    public void setInput2(int input2) {
        this.input2 = input2;
    }
    @Override
    public void doTag() throws JspException, IOException {
        JspContext context = getJspContext();
        JspWriter out = context.getOut();
        double result = (input1+input2)/2 ;
        out.println("Average is  :: " + result);
    }
}

c) Add tag calling in customTags.jsp

<html>
  <head>
   <title> JSP custom Tag </title>
  </head>
  <%@taglib uri="http://localhost:8080/myTags/taglib" prefix="myTags" %>
  <body>
    <h4>
      <myTags:welcome/>
    </h4>
    <h4>
      <myTags:test-body-content>
      Body Content goes here !!
      </myTags:test-body-content>
    </h4>
    <h4>
      <myTags:average input1="2" input2="4" />
    </h4>
    <%
      int arg1= 5;
    %>
     <br/>
        
    <h4>
      <myTags:average input1="<%= arg1%>" input2="4" />
    </h4>
  </body>
</html>

Access customTags.jsp using http://localhost:8080/jsp-tutorial/customTags.jsp

Note : As input1 is defined as <rtexprvalue> true, we can pass expressions in it.

Like us on Facebook