We're using an application build using Weblogic Workshop 10.3 and running on weblogic server 10.3. I'm trying to display a tree of data using recursive calls to a jsp page using <jsp:include>
. The problem I'm having is that after about 3-4 layers deep the page doesn't get rendered anymore. Log statements around the JSP include show the lines before an after it getting executed but the jsp never actually gets included. Log statements at the beginning of the jsp file indicate that not a single line inside the jsp is ever reached at that point.
views:
43answers:
2Technically, the limit depends on the servletcontainer make and the available heap memory. If you get too far, you will get a StackOverflowError
. For the chance you missed it, check the server-specific error logs once again.
I played around it using the following snippets:
test.jsp
:
<!DOCTYPE html>
<html lang="en">
<head>
<title>SO question 3440560</title>
</head>
<body>
<jsp:include page="include.jsp?count=${param.count}" />
</body>
</html>
include.jsp
:
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:if test="${param.count > 0}">
<p>include ${param.count}</p>
<jsp:include page="include.jsp?count=${param.count - 1}" />
</c:if>
A standard Tomcat 6.0.24 setup with default max heap memory of 64MB started to error after ~200 includes.
To get around this, you'd like to have an iterative include rather than a recursive include. the JSTL c:forEach
may be helpful in this.
Update: I am not sure about Weblogic, but Tomcat logs stderr to a different file than stdout. As to the depth, Weblogic might be a heavyweight server. There might be a lot of preceding method invocations before including the JSP.
If iteration is not a solution, then your only resort is tail recursion. Basically, pass the result around as method argument rather than relying on (waiting for) the method's return value, this way you save the stack. This is unfortunately not possible using plain jsp:include
. You'd like to write a tagfile and/or a helper class.
It works basically as follows:
public void renderHTML(List<Node> nodes, StringBuilder output) {
output.append("<li>" + node.getContent() + "</li>");
for (Node node : nodes) {
if (node.hasChildren()) {
output.append("<ul>");
renderHTML(node.getChildren(), output);
output.append("</ul>");
}
}
}
Perhaps you should use a proper tree component (Javascript Tree or tag library) ???