One of the things that has always bothered me about <jsp:include..>
is that it's not possible to pass non-String values into the included page as distinct inputs to the page. For example, I'd like to be able to do the following:
<c:forEach var="item" items="${listOfItems}">
<jsp:include page="mypage.jsp">
<jsp:attribute name="item" value="${item}/>
</jsp:include>
</c:forEach>
The idea being that, by declaring the item being passed in as an attribute inside the jsp:include node, the code is making it clear what the intent was... to supply that parameter to the included page.
The only mechanism currently available for doing this is to define the attribute "globally", and then let the included page read it from the global space. Unfortunately, this looses that same "intent" that using <jsp:param> provides. Additionally, it makes the code harder to debug, for the same reason that globals in any programming environment do.
Does anyone know of an implementation of an include mechanism that performs the functions of jsp:include, but allows for passing in non-String values? Or, if not, I'd be open to alternative ideas that preserve the same goal of intent and ease of debugging.
As a side note, I'd love to see a builtin "catch" mechanism for when the included page throws an error:
<abc:include page="mypage">
<abc:param name="something" value="some string value"/>
<abc:attribute name="somethingelse" value="${nonStringValue}"/>
<abc:catch var="ex">
The page failed, so the content it generated will not be sent to the output
stream. Instead, we can collapse the part of the page that it's content
would be... possibly putting a comment in the page with
<!-- There was an exception generating this module:
<c:out value="${ex.getMessage}/>
-->
</abc:catch>
</abc:include>
From the JSTL specification:
Nested scoped variables are only visible within the body of the action and are stored in "page" scope.
You can pass object references via request scope.
standardInclude.jsp:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:out value="${foo}" />
standardAction.jsp:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
//evil scriptlet
request.setAttribute("mylist", java.util.Arrays.asList("bar", "baz"));
%>
<c:forEach items="${mylist}" var="foo">
<c:set var="foo" scope="request" value="${foo}" />
<jsp:include page="standardInclude.jsp" />
<c:set var="foo" scope="request" value="${null}" />
</c:forEach>
You can use the catch tag to catch exceptions.
thrower.jsp:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:out value="OK: ${foo}" />
<%
//evil scriptlet
if ("bar".equals(request.getAttribute("foo")))
throw new java.io.IOException("oops");
%>
catcher.jsp:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
//evil scriptlet
request.setAttribute("mylist", java.util.Arrays.asList("bar", "baz"));
%>
<c:forEach items="${mylist}" var="foo">
<br />
<c:set var="foo" scope="request" value="${foo}" />
<c:catch var="ex">
<jsp:include page="thrower.jsp" />
</c:catch>
<c:if test="${ex ne null}">
<c:out value="Error for ${foo}" />
</c:if>
<c:set var="foo" scope="request" value="${null}" />
</c:forEach>
This will emit:
Error for bar
OK: baz
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With