Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enchanced jsp:include implementation

Tags:

java

jsp

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>
like image 844
RHSeeger Avatar asked Aug 08 '10 17:08

RHSeeger


1 Answers

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 
like image 144
McDowell Avatar answered Sep 29 '22 00:09

McDowell