Nearby lessons

19 of 30

JSP - Simple Tags (SimpleTag Model)

📌 What You Will Learn
  • Understand the SimpleTag interface and its 5 methods
  • Learn the SimpleTag Handler lifecycle
  • Use SimpleTagSupport for easy tag development
  • Process tag body content with JspFragment
  • Implement dynamic attributes
  • Compare Simple Tags vs Classic Tags

The Simple Tag Model (JSP 2.0) simplifies custom tag development by replacing the complex classic tag lifecycle with a single doTag() method. This lesson covers the SimpleTag interface, SimpleTagSupport class, body processing with JspFragment, dynamic attributes, and a comparison with classic tags.

SimpleTag Interface

SimpleTag is a child interface of JspTag and contains 5 methods:

public void setJspContext(JspContext c)
public void setParent(JspTag t)
public void setJspBody(JspFragment f)
public void doTag() throws JspException, IOException
public JspTag getParent()
MethodDescription
setJspContext()Provides the JspContext object (equivalent to PageContext in classic model)
setParent()Sets the parent tag (for nested tags)
setJspBody()Provides the tag body as a JspFragment (if tag has a body)
doTag()Main method — contains all tag logic. Equivalent to doStartTag + doEndTag + doAfterBody.
getParent()Returns the parent tag, or null

SimpleTag Handler Lifecycle

The lifecycle of a SimpleTag handler is much simpler than the classic model:

  1. Identify — JSP engine finds the tag handler via taglib directive and TLD
  2. Create — Web container creates a new instance (public no-arg constructor). Simple tag objects are never reused — a new instance is created for each invocation.
  3. setJspContext() — Makes JspContext available
  4. setParent() — Sets parent tag (for nested tags)
  5. Set Attributes — Setter methods called for each attribute
  6. setJspBody() — If tag has a body, provides the JspFragment
  7. doTag() — Executes the tag logic. This is the only method you must implement.
  8. Destroy — Tag handler object is destroyed after doTag() completes

SkipPageException behavior:

  • If doTag() throws SkipPageException → rest of the JSP is NOT executed
  • If doTag() does NOT throw it → rest of the JSP executes normally

SimpleTagSupport — Convenience Class

SimpleTagSupport implements SimpleTag and provides default implementations for all methods. It also adds helper methods:

public JspContext getJspContext()     // Get the JspContext
public JspFragment getJspBody()       // Get the tag body fragment
public JspTag findAncestorWithClass(JspTag t, Class c)  // Find ancestor

Demo — Basic Simple Tag

Project structure:

cust10/
├── test.jsp
├── WEB-INF/
│   ├── MyTld.tld
│   └── classes/tags/
│       └── MyCustomTag.class

test.jsp:

<%@ taglib prefix="mine" uri="/WEB-INF/MyTld.tld" %>
<h1>This is Simple Tag Demo</h1>
<mine:mytag />
<h1>This is rest of the JSP</h1>

MyCustomTag.java:

package tags;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;

public class MyCustomTag extends SimpleTagSupport {
  public void doTag() throws JspException, IOException {
    JspWriter out = getJspContext().getOut();
    out.println("<h1>Hello this is from simple tag handler</h1>");
    // throw new SkipPageException();  // Uncomment to stop rest of JSP
  }
}

Output (without SkipPageException):

This is Simple Tag Demo
Hello this is from simple tag handler
This is rest of the JSP

Output (with SkipPageException):

This is Simple Tag Demo
Hello this is from simple tag handler

Body-content Differences: Simple vs Classic

The allowed values for <body-content> differ between the two models:

ValueClassic TagsSimple Tags
empty
tagdependent
scriptless
jsp✓ (default)✗ Not allowed

Key rule: In the Simple Tag Model, scripting elements are not allowed in tag body. Default value is scriptless.

Processing Body Content with JspFragment

To access and process the tag body in a Simple Tag Handler, use getJspBody():

public JspFragment getJspBody()

The returned JspFragment object represents the tag body. It provides these methods:

MethodDescription
getJspContext()Returns the JspContext
invoke(Writer w)Evaluates the tag body and writes to the supplied Writer. Pass null to write directly to the JspOutputStream.

Demo — Process tag body:

<%@ taglib prefix="mine" uri="/WEB-INF/MyTld.tld" %>
<h1>This is Before tag invocation</h1>

<mine:mytag>
  <h1>This is Tag Body</h1>
</mine:mytag>

<h1>This is After tag invocation</h1>

MyCustomTag.java:

package tags;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;

public class MyCustomTag extends SimpleTagSupport {
  public void doTag() throws JspException, IOException {
    JspWriter out = getJspContext().getOut();
    out.println("<h1>Hello this is from simple tag handler</h1>");
    getJspBody().invoke(null);  // Evaluate and output the tag body
  }
}

Key Differences: Simple Tags vs Classic Tags

PropertySimple TagsClassic Tags
Tag InterfacesSimpleTagTag, IterationTag, BodyTag
Implementation ClassSimpleTagSupportTagSupport, BodyTagSupport
Key MethoddoTag()doStartTag(), doEndTag(), doAfterBody()
Object ReuseNever reused — new instance per invocationReused by web container
OutputgetJspContext().getOut().println()pageContext.getOut().println()
IOExceptionNo try-catch needed (declared in throws)Must enclose in try-catch
Body ProcessinggetJspBody().invoke(null)Returns EVAL_BODY_INCLUDE or EVAL_BODY_BUFFERED
Page StopThrow SkipPageExceptionReturn SKIP_PAGE from doEndTag()
Implicit ObjectsVia JspContextVia PageContext
Tag Body ContentJspFragmentBodyContent buffer
Scripting in BodyNot allowed (scriptless)Allowed (jsp)

Dynamic Attributes

In general, tag attributes must be declared in the TLD file. Dynamic attributes allow you to use attributes without pre-declaring them — introduced in JSP 2.0.

To support dynamic attributes:

  1. In the TLD, add <dynamic-attributes>true</dynamic-attributes>
  2. The tag handler must implement the DynamicAttributes interface
  3. Implement setDynamicAttribute(String namespace, String name, Object value)

The web container calls setDynamicAttribute() for each dynamic attribute at runtime.

Demo — Math operations with dynamic attributes:

<%@ taglib prefix="mine" uri="/WEB-INF/MyTld.tld" %>
<h1>Hello this is Sample JSP</h1>
<mine:mytag num="2" min="10" max="20" pow="2" />

MyCustomTag.java:

package tags;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;

public class MyCustomTag extends SimpleTagSupport implements DynamicAttributes {
  double num;
  String output = "";

  public void setNum(double num) { this.num = num; }

  public void setDynamicAttribute(String ns, String name, Object value) {
    double d = Double.parseDouble((String) value);
    if (name.equals("min"))
      output += "The Minimum value is: " + Math.min(num, d) + "<br>";
    else if (name.equals("max"))
      output += "The Maximum value is: " + Math.max(num, d) + "<br>";
    else if (name.equals("pow"))
      output += "The Power value is: " + Math.pow(num, d) + "<br>";
  }

  public void doTag() throws JspException, IOException {
    JspWriter out = getJspContext().getOut();
    out.println("<h1>" + output + "</h1>");
  }
}

Dynamic Attributes with Static Attributes

You can combine declared (static) attributes with dynamic attributes:

MyTld.tld:

<taglib version="2.1">
  <tlib-version>1.2</tlib-version>
  <tag>
    <name>mytag</name>
    <tag-class>tags.MyCustomTag</tag-class>
    <attribute>
      <name>num</name>
      <required>true</required>
    </attribute>
    <dynamic-attributes>true</dynamic-attributes>
    <body-content>empty</body-content>
  </tag>
</taglib>
📝 Key Takeaways
  • SimpleTag uses one doTag() method instead of doStartTag/doEndTag/doAfterBody
  • SimpleTag objects are never reused — a new instance per invocation
  • SimpleTagSupport provides convenient defaults for all methods

🧠 Test Your Knowledge

3 Questions
Progress: 0 / 3