|
JSTL - Core Library
Part:
1
2
3
4
(Continued from previous part...)
I am not showing you the output here. But it 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/jstl/core" version="1.2">
<!-- JstlPrimeNumbersRevised.jsp - Compilation error
Copyright (c) 2004 by Dr. Herong Yang
-->
<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, you will get a compilation error saying that there is
an unreachable statement. If you open the converted Java class file of the JSP page,
JstlPrimeNumbersRevised_jsp.java, you will see:
......
/* ---- c:forEach ---- */
org.apache.taglibs.standard.tag.el.core.ForEachTag _jspx_th_c_fo...
_jspx_th_c_forEach_1.setPageContext(pageContext);
_jspx_th_c_forEach_1.setParent(_jspx_th_c_forEach_0);
_jspx_th_c_forEach_1.setVar("j");
_jspx_th_c_forEach_1.setBegin("${2}");
_jspx_th_c_forEach_1.setEnd("${i-1}");
try {
int _jspx_eval_c_forEach_1 = _jspx_th_c_forEach_1.doStartTag();
if (_jspx_eval_c_forEach_1 != javax.servlet.jsp.tagext.Tag.SKI...
do {
/* ---- c:if ---- */
org.apache.taglibs.standard.tag.el.core.IfTag _jspx_th_c_i...
_jspx_th_c_if_0.setPageContext(pageContext);
_jspx_th_c_if_0.setParent(_jspx_th_c_forEach_1);
_jspx_th_c_if_0.setTest("${i%j == 0}");
int _jspx_eval_c_if_0 = _jspx_th_c_if_0.doStartTag();
if (_jspx_eval_c_if_0 != javax.servlet.jsp.tagext.Tag.SKIP...
do {
if (_jspx_meth_c_set_2(_jspx_th_c_if_0, pageContext))
return;
break;
int evalDoAfterBody = _jspx_th_c_if_0.doAfterBody();
if (evalDoAfterBody != javax.servlet.jsp.tagext.BodyTa...
break;
} while (true);
}
if (_jspx_th_c_if_0.doEndTag() == javax.servlet.jsp.tagext...
return;
_jspx_tagPool_c_if_test.reuse(_jspx_th_c_if_0);
int evalDoAfterBody = _jspx_th_c_forEach_1.doAfterBody();
if (evalDoAfterBody != javax.servlet.jsp.tagext.BodyTag.EV...
break;
} while (true);
}
if (_jspx_th_c_forEach_1.doEndTag() == javax.servlet.jsp.tagex...
return;
} catch (Throwable _jspx_exception) {
_jspx_th_c_forEach_1.doCatch(_jspx_exception);
} finally {
_jspx_th_c_forEach_1.doFinally();
_jspx_tagPool_c_forEach_var_end_begin.reuse(_jspx_th_c_forEach...
}
if (_jspx_meth_c_choose_0(_jspx_th_c_forEach_0, pageContext))
return;
int evalDoAfterBody = _jspx_th_c_forEach_0.doAfterBody();
if (evalDoAfterBody != javax.servlet.jsp.tagext.BodyTag.EVAL_BOD...
break;
......
The reason for the compilation error is clear. The c:forEach tag has been converted to a Java "while"
loop by the JSTL 1.0 tag class - 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.
Can someone confirm that if JSTL 1.1 is still converting c:if into a "while" loop?
Part:
1
2
3
4
|