This test was prompted by reading a question on the Sun java forums and thought I would try it out. The JSP2.0 specification section JSP.13.8 contains an "Example Simple Tag Handler Scenario". I copy and pasted the code fragments and attempted to run it.
Environment: Apache Tomcat version 5.5.26 and 6.0.14 (tested on both) Java: 1.5
Code I am testing with: Jsp page:
<%@ taglib prefix="my" tagdir="/WEB-INF/tags" %>
<my:simpletag x="10">
<jsp:attribute name="y">20</jsp:attribute>
<jsp:attribute name="nonfragment">
Nonfragment Template Text
</jsp:attribute>
<jsp:attribute name="frag">
Fragment Template Text ${var1}
</jsp:attribute>
<jsp:body>
Body of tag that defines an AT_BEGIN
scripting variable ${var1}.
</jsp:body>
</my:simpletag>
And the tag file:
<%-- /WEB-INF/tags/simpleTag.tag --%>
<%@ attribute name="x" %>
<%@ attribute name="y" %>
<%@ attribute name="nonfragment" %>
<%@ attribute name="frag" fragment="true" %>
<%@ variable name-given="var1" scope="AT_BEGIN" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Some template text.
<c:set var="var1" value="${x+y}"/>
<jsp:invoke fragment="frag" varReader="var1"/>
Invoke the body:
<jsp:doBody/>
This code is directly copied from the PDF copy of the JSP2.0 specification.
It is also available as part of the JSP-API here
Minor change made - I changed the name of the tagfile from simpletag.tag to simpleTag.tag to match the invocation of it in the JSP.
I also tried copying from the PDF of the spec (adjusting quotes as necessary) - same result.
When I execute the page I end up with a standard 500 error Root cause: java.lang.ClassCastException: java.io.StringReader org.apache.jsp.tagVariableTest_jsp._jspService(tagVariableTest_jsp.java:62)
Line62 of the generated JSP turns out to be: var1 = (java.lang.String) _jspx_page_context.findAttribute("var1");
Ok, I can understand ClassCastException - it thinks that var1 should be a String, and the actual attribute is a StringReader. But why is it a StringReader? Where did the variable get created? And why is it attempting to do this assignment at all?
Can someone please point me in the right direction? What is wrong with the code/setup? Is this a known issue? I googled for it but couldn't seem to find anything.
Thanks, evnafets
Editing with resolution: The ClassCastException was being caused by the line in the tag:
<jsp:invoke fragment="frag" varReader="var1"/>
As mentioned here the varReader attribute specifies the attribute to store the evaluation result as a StringReader. The exception was caused by Tomcat generated code trying to retrieve the value of "var1" and cast it to a String. As a String is not a StringReader so, it raised an exception at that point.
I'm not sure if the coding error is they should have used the "var" instead of the "varReader" attribute, or they shouldn't have used either and just evaluated it as is. Removing that attribute completely prints out the fragment, and then the body both with the value of "var1":
Fragment Template Text 30. Invoke the body: Body of tag that defines an AT_BEGIN scripting variable 30
Making the attribute var="var1" executes the fragment, and stores the result to var1. The body is then evaluated with this new value of var1 resulting in:
Invoke the body: Body of tag that defines an AT_BEGIN scripting variable Fragment Template Text 30
Personally I think the first case makes more sense, but this code is presented as an example of the innerworkings, not best practice.
I still would have expected the example to compile/run in any case. I was fairly surprised when it didn't.