Open In App

Custom Tags in JSP

Last Updated : 30 Dec, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Custom tags are user-defined action tags that can be used within Java Server Pages. A tag handler is associated with each tag to implement the operations. Therefore, it separates the business logic from JSP and helps avoid the use of scriptlet tags. The scriptlet tag embeds java code inside the JSP page itself rendering the page difficult to understand therefore, it is better to avoid the use of scriptlet.

Reasons to avoid scriptlets in JSP:

Both scriptlets and custom tags use servlets at the core, therefore, they do not differ much in performance. But custom tags are always preferred over scriptlets for the following reasons : 

  • Custom tags separate the business logic from Java Server Pages. JSP still controls the flow but processing is delegated to a separate java class( tag handler class).
  • It increases the readability of Java Server Pages. Scriptless JSPs are a lot easier to read and understand as compared to JSPs embedded with scriptlets. 
  • It is easier for a frontend developer to use tags rather than writing java code inside the JSPs.
  • Custom tags can be reused across various applications but it is not possible to reuse the java code embedded within a JSP using scriptlets.

Creating custom tags

Syntax of custom tags:

empty custom tag(without body)

  • <prefix : suffix attribute = “value”/>

Non-empty custom tag

  • <prefix : suffix attribute = “value”>body</prefix : suffix>

The following three components are required to develop custom tags :

  1. Tag Handler
  2. TLD(Tag Library Descriptor) file
  3. Taglib directive in jsp file

1. Tag Handler

It is a container-managed object created by a JSP container at runtime. A Java class is used to implement the processing logic for the tag. It may contain certain properties corresponding to the attributes or body of the tag. All tag handlers have a pageContext property for the JSP page where the tag is located, and a parent property for the tag handler to the closest enclosing parent tag. It must implement/extend one of the following interfaces/classes present in javax.servlet.jsp.tagext package :

Tag Handler

 

Lifecycle of tag handler:

  • During runtime, the JSP container is responsible to create the object of implementing the tag handler class using the no-arg constructor.
  • Once the object is created, the JSP container calls the setParent and setPageContext methods on the tag handler
  • JSP container then calls setter methods on the tag handler to set its properties using the values of corresponding attributes of the tag. 
  • When the object is ready for use, various lifecycle methods are called on the object.
  • Pooling of tag handlers is managed by the JSP container. The same tag handler might be used for multiple occurrences of tag on the page if the values of the attributes are the same. But if the values of attributes are different, properties might need to be reset. In the case of SimpleTag and SimpleTagSupport classes, tag handlers are not pooled.

Tag Interface

Tag interface can be implemented by a tag handler to provide the processing logic if the body of the tag is not required to be evaluated. It provides the following methods :

  • int doEndTag()
  • int doStartTag()
  • Tag getParent()
  • void release()
  • void setPageContext(PageContext pc)
  • void setParent(Tag t)

doStartTag() is evaluated at the starting tag and returns one of the following:

  • static int EVAL_BODY_INCLUDE
  • static int SKIP_BODY

doEndTag() is evaluated at the ending tag and returns one of the following:

  • static int EVAL_PAGE
  • static int SKIP_PAGE

If the page is included by some other servlet/JSP, only the current page is skipped in case doEndTag() returns SKIP_PAGE.

IterationTag Interface

IterationTag interface can be implemented if the body of the tag needs to be repeated a certain number of times. It provides the following method:

int doAfterBody()

doAfterBody() is invoked after every iteration method of the body to decide whether to reevaluate the body or not. It returns one of the following :

  • static int SKIP_BODY
  • static int EVAL_BODY_AGAIN

If SKIP_BODY is returned, the container calls the doEndTag() method and proceeds further. In case EVAL_BODY_AGAIN is returned, the body is evaluated again.

TagSupport class

It is a base class that implements Tag and IterationTag interfaces. It can be used to implement a tag handler in case implementation for all the methods is not required. It provides the default implementation of all the abstract methods of its parent interfaces.

BodyTag Interface

BodyTag interface can be implemented by a tag handler if the body of the tag is to be evaluated. It provides the following methods:

  •  void doInitBody()
  • void setBodyContent(BodyContent b)

Unlike IterationTag, doStartTag() of the BodyTag method may return one of the following :

  • static int EVAL_BODY_INCLUDE
  • static int SKIP_BODY
  • static int EVAL_BODY_BUFFERED

If EVAL_BODY_BUFFERED is returned by the doStartTag() method, the BodyContent object is created and passed to setBodyContent() method. BodyContent: It is a subclass of JspWriter. Given below are some useful methods of BodyContent class.

  • void clearBody()
  • Reader getReader()
  • String getString()
  • void writeOut(Writer out)

These methods of BodyContent can be used to convert its contents into a String, to read its contents, and to clear the contents.

BodyTagSupport class

It is a base class that implements BodyTag class and extends TagSupport class. It provides the default implementation of its parent interfaces.

SimpleTag Interface

A tag handler can implement the SimpleTag interface in order to provide the processing logic. It consists of a much simpler lifecycle as compared to classic tag handlers. The following methods are provided by the SimpleTag interface:

  • void doTag()
  • JspTag getParent()
  • void setJspBody(JspFragment jspBody)
  • void setJspContext(JspContext pc)
  • void setParent(JspTag parent)
  • doTag() method is used to provide all the processing logic. It is executed only once, therefore iteration logic, if required,  must be encapsulated within it. 
  • setJspBody() method sets the body of the tag if the body needs to be evaluated. It takes in the JspFragment object.
  • JspFragment: Encapsulates a portion of JSP code in an object that can be invoked as often as needed. The definition of the JSP fragment must only contain template text and JSP action elements. In other words, it must not contain scriptlets or scriptlet expressions. The following methods are provided by JspFragment  class :
  • JspContext getJspContext()
  • void invoke(Writer out)

SimpleTagSupport class

It is a base class of the SimpleTag interface. It can be extended to provide the handler code. From the above discussion, it can be concluded that a tag handler must implement one of the following interfaces: Tag, IterationTag, SimpleTag or extend any of the following classes: TagSupport, BodyTagSupport, SimpleTagSupport to provide the processing logic for the tag.

2. TLD(Tag Library Descriptor)

It is a file saved with a .tld extension that contains a set of related tags mapped to their respective tag handlers along with their description such as the name of the tag, attributes of the tag, etc. The root tag of the TLD document is <taglib> in which multiple tags can be encapsulated using <tag> tag. It is stored inside the WEB-INF folder. It consists of the following header:

<taglib version=”2.0″ xmlns=”http://java.sun.com/xml/j2ee” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd”>

<Taglib> consists of the following sub-elements:

  • <tlib-version>: defines the version of the tag library.
  • <jsp-version>: defines the version of JSP.
  • <uri>: provides URI for the tag library.

<Tag> consists of the following sub-elements:

  • <body-content>: describes the type of body content: empty, JSP, scriptless, tagdependent
  • <name>: used to provide a unique name to the tag.(suffix)
  • <tagclass>: used to provide tag handler class for the tag
  • <attribute>: used to provide attributes for the tag.

<Attribute> further encapsulates the following properties:

  •  name>: used to provide a unique name to the attribute.
  • <required>: used to specify whether the attribute is required or optional. Takes a boolean value.
  • <rtexprvalue>: used to specify whether runtime expression can be fed into the value of the attribute. Takes a boolean value.
  • <type>: used to specify the type of value that is to be provided to the attribute. Default is taken as String.
  • <fragment>: used to specify whether the attribute stores a JspFragment or not.

TLD along with the tag handlers constitute the tag library which is then distributed and used in the JSPs. A standard example of such libraries is JSTL(Java Standard Tag Library) which provides several useful tags for control flow, string processing, database operations, etc.

3. Taglib Directive

Taglib directive is used to access a particular tag library within a JSP. It specifies the URI of the tag library and its prefix.

Syntax:

<%@taglib uri=” ” prefix=” “%>

Example

mytld.tld:

XML




<?xml version="1.0" encoding="UTF-8"?>
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
   <tlib-version>2.0</tlib-version>
   <jsp-version>2.0</jsp-version>
   <tag>
      <name>welcome</name>
      <tag-class>tagHandler.WelcomeTagHandler</tag-class>
      <body-content>empty</body-content>
   </tag>
   <tag>
      <name>date</name>
      <tag-class>tagHandler.DateTagHandler</tag-class>
      <body-content>empty</body-content>
   </tag>
   <tag>
      <name>repeat</name>
      <tag-class>tagHandler.IterationTagHandler</tag-class>
      <body-content>jsp</body-content>
      <attribute>
         <name>numberOfIterations</name>
         <required>true</required>
      </attribute>
   </tag>
</taglib>


WelcomeTagHandler.java:

Java




package tagHandler;
  
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;
  
public class WelcomeTagHandler extends SimpleTagSupport {
    public void doTag() throws JspException,IOException
    {
        JspWriter out=getJspContext().getOut();
        out.println("Welcome!");
    }
}


DateTimeHandler.java:

Java




package tagHandler;
  
import java.io.IOException;
import java.util.Date;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
  
public class DateTagHandler extends TagSupport {
    
    public int doStartTag() throws JspException
    {
        try {
            pageContext.getOut().println("Current date and time is : ");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return SKIP_BODY;
    }
    public int doEndTag() throws JspException
    {
        try {
            pageContext.getOut().println(new Date());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return EVAL_PAGE;
    }
  
}


IterationTagHandler.java: 

Java




import java.io.IOException;
  
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
  
public class IterationTagHandler extends TagSupport {
    
    int numberOfIterations;
    int currentIteration;
      
    public int getNumberOfIterations() {
        return numberOfIterations;
    }
    public void setNumberOfIterations(int numberOfIterations) {
        this.numberOfIterations = numberOfIterations;
    }
    public int doStartTag() throws JspException
    {
        return EVAL_BODY_INCLUDE;
    }
    public int doAfterBody() throws JspException
    {
        if(currentIteration<numberOfIterations-1)
        {
            currentIteration++;
            return EVAL_BODY_AGAIN;
        }
        else
        {
            currentIteration=0;
            return SKIP_BODY;
        }
    }
}


index.jsp:

HTML




<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
   pageEncoding="ISO-8859-1"%>
<%@taglib uri="WEB-INF/mytld.tld" prefix="com" %>
<!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=ISO-8859-1">
      <title>WelcomePage</title>
   </head>
   <body>
      <h1>
         <com:welcome/>
      </h1>
      <h3>
         <com:date/>
         <br><br>
         Thanks for the visit.<br>
         Have a nice day!
      </h3>
      <com:repeat numberOfIterations="50">*</com:repeat>
   </body>
</html>


Output:

index.jsp

index.jsp



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads