Example - Calculating Prime Numbers

This section provides a tutorial example to calculate prime numbers using a JSTL Core library c:forEach tag. But example works. But it is not perfect, because it has no break statement.

As my second JSTL core example, JstlPrimeNumbers.jsp, is to calculate if a given number is prime number or not.

<?xml version="1.0"?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
   xmlns:c="http://java.sun.com/jsp/jstl/core" version="2.1"> 
<!-- JstlPrimeNumbers.jspx - It doesn't work, can not change the index
 - Copyright (c) 2012, HerongYang.com, All Rights Reserved.
-->
<jsp:directive.page contentType="text/html"/>
<html><body>
<p>Checking prime numbers:</p>
<c:set var="upperLimit" value="${20}"/>
<c:forEach var="i" begin="${3}" end="${upperLimit}">
 <c:set var="isPrime" value="${true}"/>
 <c:forEach var="j" begin="${2}" end="${i-1}">
  <c:if test="${i%j == 0}">
   <c:set var="isPrime" value="${false}"/>
   <!-- We should break the loop here -->
  </c:if>
 </c:forEach>
 <c:choose>
  <c:when test="${isPrime}">
   <c:out value="${i} is a prime number."/><br/>
  </c:when>
  <c:otherwise>
   <c:out value="${i} is a not prime number."/><br/>
  </c:otherwise>
 </c:choose>
</c:forEach>
</body></html>
</jsp:root>

I am not showing you the output here. But the output is correct. Trust me. As you can see in the source code, I am not breaking the loop on "j" when "i" has already been approved as a non-prime number, because I don't know how.

One of the emails I received after publishing the above notes suggests me to insert a Java break statement through a scriptlet to break the "forEach" tag. To try this idea, I revised my JSP page to JstlPrimeNumbersRevised.jsp:

<?xml version="1.0"?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
   xmlns:c="http://java.sun.com/jsp/jstl/core" version="2.1"> 
<!-- JstlPrimeNumbersRevised.jsp - Compilation error
 - Copyright (c) 2012, HerongYang.com, All Rights Reserved.
-->
<jsp:directive.page contentType="text/html"/>
<html><body>
<p>Checking prime numbers:</p>
<c:set var="upperLimit" value="${20}"/>
<c:forEach var="i" begin="${3}" end="${upperLimit}">
 <c:set var="isPrime" value="${true}"/>
 <c:forEach var="j" begin="${2}" end="${i-1}">
  <c:if test="${i%j == 0}">
   <c:set var="isPrime" value="${false}"/>
   <jsp:scriptlet>break;</jsp:scriptlet>
  </c:if>
 </c:forEach>
 <c:choose>
  <c:when test="${isPrime}">
   <c:out value="${i} is a prime number."/><br/>
  </c:when>
  <c:otherwise>
   <c:out value="${i} is a not prime number."/><br/>
  </c:otherwise>
 </c:choose>
</c:forEach>
</body></html>
</jsp:root>

If the scriptlet statement can merge with the JSTL tags nicely, the logic will work. However if you view this page on Tomcat 7, you will get a compilation error saying that there is an unreachable statement:

HTTP Status 500 - Unable to compile class for JSP:

type Exception report

message Unable to compile class for JSP:

description The server encountered an internal error 
   that prevented it from fulfilling this request.

exception
org.apache.jasper.JasperException: Unable to compile class for JSP: 

An error occurred at line: 8 in the jsp file: 
/JstlPrimeNumbersRevised.jspx
Unreachable code

5:  - Copyright () 2012, HerongYang.com, All Rights Reserved.
6: -->
7: <jsp:directive.page contentType="text/html"/>
8: <html><body>
9: <p>Checking prime numbers:</p>
10: <c:set var="upperLimit" value="${20}"/>
11: <c:forEach var="i" begin="${3}" end="${upperLimit}">

Stacktrace:
   org.apache.jasper.compiler.DefaultErrorHandler.javacError()
   org.apache.jasper.compiler.ErrorDispatcher.javacError()
   org.apache.jasper.compiler.JDTCompiler.generateClass()
   org.apache.jasper.compiler.Compiler.compile()
   org.apache.jasper.compiler.Compiler.compile()
   org.apache.jasper.compiler.Compiler.compile()
   org.apache.jasper.JspCompilationContext.compile()
   org.apache.jasper.servlet.JspServletWrapper.service()
   org.apache.jasper.servlet.JspServlet.serviceJspFile()
   org.apache.jasper.servlet.JspServlet.service()
   javax.servlet.http.HttpServlet.service()
...

If you open the converted Java class file of the JSP page, JstlPrimeNumbersRevised_jspx.java, you will see:

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/7.0.32
   ...
 */
...
//  c:forEach
org.apache.taglibs.standard.tag.rt.core.ForEachTag _jspx_th_c_005ff...
_jspx_th_c_005fforEach_005f0.setPageContext(_jspx_page_context);
_jspx_th_c_005fforEach_005f0.setParent(null);
// /JstlPrimeNumbersRevised.jspx(11,53) name = end type = int reqTi...
_jspx_th_c_005fforEach_005f0.setEnd(((java.lang.Integer) org.apache...
// /JstlPrimeNumbersRevised.jspx(11,53) name = begin type = int req...
_jspx_th_c_005fforEach_005f0.setBegin(((java.lang.Integer) org.apac...
// /JstlPrimeNumbersRevised.jspx(11,53) name = var type = java.lang...
_jspx_th_c_005fforEach_005f0.setVar("i");
int[] _jspx_push_body_count_c_005fforEach_005f0 = new int[] { 0 };
try {
  int _jspx_eval_c_005fforEach_005f0 = _jspx_th_c_005fforEach_005f0...
  if (_jspx_eval_c_005fforEach_005f0 != javax.servlet.jsp.tagext.Ta...
    do {
      if (_jspx_meth_c_005fset_005f1(_jspx_th_c_005fforEach_005f0, ...
        return;
      //  c:forEach
      org.apache.taglibs.standard.tag.rt.core.ForEachTag _jspx_th_c...
      _jspx_th_c_005fforEach_005f1.setPageContext(_jspx_page_contex...
      _jspx_th_c_005fforEach_005f1.setParent((javax.servlet.jsp.tag...
      // /JstlPrimeNumbersRevised.jspx(13,47) name = end type = int...
      _jspx_th_c_005fforEach_005f1.setEnd(((java.lang.Integer) org....
      // /JstlPrimeNumbersRevised.jspx(13,47) name = begin type = i...
      _jspx_th_c_005fforEach_005f1.setBegin(((java.lang.Integer) or...
      // /JstlPrimeNumbersRevised.jspx(13,47) name = var type = jav...
      _jspx_th_c_005fforEach_005f1.setVar("j");
      int[] _jspx_push_body_count_c_005fforEach_005f1 = new int[] {...
      try {
        int _jspx_eval_c_005fforEach_005f1 = _jspx_th_c_005fforEach...
        if (_jspx_eval_c_005fforEach_005f1 != javax.servlet.jsp.tag...
          do {
            //  c:if
            org.apache.taglibs.standard.tag.rt.core.IfTag _jspx_th_...
            _jspx_th_c_005fif_005f0.setPageContext(_jspx_page_conte...
            _jspx_th_c_005fif_005f0.setParent((javax.servlet.jsp.ta...
            // /JstlPrimeNumbersRevised.jspx(14,28) name = test typ...
            _jspx_th_c_005fif_005f0.setTest(((java.lang.Boolean) or...
            int _jspx_eval_c_005fif_005f0 = _jspx_th_c_005fif_005f0...
            if (_jspx_eval_c_005fif_005f0 != javax.servlet.jsp.tage...
              do {
                if (_jspx_meth_c_005fset_005f2(_jspx_th_c_005fif_00...
                  return;
break;
                int evalDoAfterBody = _jspx_th_c_005fif_005f0.doAft...
                if (evalDoAfterBody != javax.servlet.jsp.tagext.Bod...
                  break;
              } while (true);
            }
            if (_jspx_th_c_005fif_005f0.doEndTag() == javax.servlet...
              _005fjspx_005ftagPool_005fc_005fif_0026_005ftest.reus...
              return;
            }
            _005fjspx_005ftagPool_005fc_005fif_0026_005ftest.reuse(...
            int evalDoAfterBody = _jspx_th_c_005fforEach_005f1.doAf...
            if (evalDoAfterBody != javax.servlet.jsp.tagext.BodyTag...
              break;
          } while (true);
        }
        if (_jspx_th_c_005fforEach_005f1.doEndTag() == javax.servle...
          return;
        }
      } catch (java.lang.Throwable _jspx_exception) {
        while (_jspx_push_body_count_c_005fforEach_005f1[0]-- > 0)
          out = _jspx_page_context.popBody();
        _jspx_th_c_005fforEach_005f1.doCatch(_jspx_exception);
      } finally {
        _jspx_th_c_005fforEach_005f1.doFinally();
        _005fjspx_005ftagPool_005fc_005fforEach_0026_005fvar_005fen...
      }
      if (_jspx_meth_c_005fchoose_005f0(_jspx_th_c_005fforEach_005f...
        return;
      int evalDoAfterBody = _jspx_th_c_005fforEach_005f0.doAfterBod...
      if (evalDoAfterBody != javax.servlet.jsp.tagext.BodyTag.EVAL_...
        break;
    } while (true);
  }
...

The reason for the compilation error is clear. The c:forEach tag has been converted to a Java "while" loop - no surprise. However the c:if tag is also converted to a Java "while" loop - big surprise. The break statement provided by the scriptlet is placed in the middle of a while loop without if condition, and it causes the "code not reachable" compilation error.

So there is still no easy way to break a c:forEach tag.

Last update: 2012.

Table of Contents

 About This Book

 JSP (JavaServer Pages) Overview

 Tomcat 7 Installation on Windows Systems

 JSP Scripting Elements

 Java Servlet Introduction

 JSP Implicit Objects

 Syntax of JSP Pages and JSP Documents

 JSP Application Session

 Managing Cookies in JSP Pages

 JavaBean Objects and "useBean" Action Elements

 Managing HTTP Response Header Lines

 Non-ASCII Characters Support in JSP Pages

 Performance of JSP Pages

 EL (Expression Language)

 Overview of JSTL (JSP Standard Tag Libraries)

JSTL Core Library

 What Is JSTL Core Library?

 c:out Action Tag

 c:out Action Tag with EL Expressions

 c:set Action Tag

 c:if Action Tag

 c:choose Action Tag

 c:forEach Action Tag

 c:forTokens Action Tag

 Example - Dumping EL Implicit Objects

Example - Calculating Prime Numbers

 JSP Custom Tags

 JSP Java Tag Interface

 Custom Tag Attributes

 Multiple Tags Working Together

 File Upload Test Application

 Outdated Tutorials

 References

 PDF Printing Version