JSP and JSTL Tutorials - Herong's Tutorial Notes
Dr. Herong Yang, Version 3.09, 2006

Tags Working Together

Part:   1  2 

JSP/JSTL Tutorials - Herong's Tutorial Notes © Dr. Herong Yang

Using Cookies

Using JavaBean Classes

HTTP Response Header Lines

Non ASCII Characters

JSTL and Expression Language

File Upload

Execution Context

JSP Elements

JSP Standard Tag Libraries (JSTL)

JSP Custom Tag

... Table of Contents

Nested JSTL Tags

When tags are nested, JSP tag extension facility offers the child tag an access to the parent tag by the setParent() method call. You can take advantage of this access to design nested tags to work together to perform more complex functions.

As an example, I wrote two simple tags to perform a loop function with the ability to break out the loop conditionally.

Here is my loop tag, LoopTag.java:

/**
 * LoopTag.java
 * Copyright (c) 2003 by Dr. Herong Yang. All rights reserved.
 */
package herong;
import java.io.*;
import javax.servlet.jsp.tagext.*;
public class LoopTag extends TagSupport {
   public boolean stop = false; 
   public int doStartTag() {
      return EVAL_BODY_INCLUDE;
   }
   public int doAfterBody() {
      if (!stop) return EVAL_BODY_AGAIN;
      else return SKIP_BODY;
   }
}

The logic of the "loop" tag is very simple. It evaluates its body immediately once the tag is encountered. At the end of the evaluation, it checks its "stop" condition, if "stop" is false, it evaluates its body again. This loop will be stopped only if "stop" is set to true, during the body evaluation.

Here is the break tag, BreakTag.java:

/**
 * BreakTag.java
 * Copyright (c) 2003 by Dr. Herong Yang. All rights reserved.
 */
package herong;
import herong.*;
import javax.servlet.jsp.tagext.*;
public class BreakTag extends TagSupport {
   private Tag parent = null;
   public void setParent(Tag t) {
      parent = t;
   }
   public int doStartTag() {
      if (parent!=null) {
         LoopTag grandParent = (LoopTag) parent.getParent();
         if (grandParent!=null) grandParent.stop = true;
      }
      return SKIP_BODY;
   }
}

The logic of the "break" tag is a little bit more complex. To break the "loop" tag conditionally, we are expecting an "if" tag will be nested inside the "loop" tag to control the condition, and the "break" tag will be nested inside the "if" tag to break the loop. So the "break" tag is actually nested 2 levels down inside the "loop" tag. This is why I have to use "parent.getParent()" to get the grand parent to access the "loop" tag.

Here is the TLD file:

<?xml version="1.0"?>
<!DOCTYPE taglib PUBLIC 
 "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" 
 "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_2.dtd"> 
<!-- HyTaglib.tld
     Copyright (c) 2003 by Dr. Herong Yang
-->
<taglib>
<tlib-version>1</tlib-version>
<jsp-version>1.2</jsp-version> 
<short-name>Herong's Tag Library</short-name> 
<tag>
 <name>loop</name>
 <tag-class>herong.LoopTag</tag-class>
 <body-content>jsp</body-content>
</tag>
<tag>
 <name>break</name>
 <tag-class>herong.BreakTag</tag-class>
 <body-content>empty</body-content>
</tag>
<!-- other tags -->
</taglib>

Here is a test page, LoopTagTest.jsp:

<?xml version="1.0"?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" 
   xmlns:c="http://java.sun.com/jstl/core"
   xmlns:hy="urn:jsptld:/WEB-INF/tlds/HyTaglib.tld" version="1.2"> 
<!-- LoopTagTest.jsp
     Copyright (c) 2003 by Dr. Herong Yang
-->
<jsp:directive.page contentType="text/html"/>
<html><body>
<c:set var="i" value="${1}"/>
<c:set var="s" value="${0}"/>
<hy:loop>
 <c:set var="s" value="${s+i}"/>
 <c:set var="i" value="${i+1}"/>
 <c:if test="${i gt 10}">
  <hy:break/>
 </c:if>
</hy:loop>
<c:out value="Sum = ${s}"/><br/>
</body></html>
</jsp:root>

(Continued on next part...)

Part:   1  2 

Dr. Herong Yang, updated in 2006
JSP and JSTL Tutorials - Herong's Tutorial Notes - Tags Working Together