views:

10680

answers:

3

Is there a pure-Java equivalent to <jsp:forward page="..." /> that I can use within a <% ... %> block?

For example, I currently have a JSP page something like this:

<%
    String errorMessage = SomeClass.getInstance().doSomething();
    if (errorMessage != null) {
        session.setAttribute("error", errorMessage);
%>
<jsp:forward page="error.jsp" />
<%
    } else {
        String url = response.encodeRedirectURL("index.jsp");
        response.sendRedirect(url);
    }
%>

Having to break the <% ... %> block to use the jsp:forward is ugly and makes it harder to read due to indentation, among other things.

So, can I do the forward in the Java code without use the JSP tag?

Something like this would be ideal:

<%
    String errorMessage = SomeClass.getInstance().doSomething();
    if (errorMessage != null) {
        session.setAttribute("error", errorMessage);
        someObject.forward("error.jsp");
    } else {
        String url = response.encodeRedirectURL("index.jsp");
        response.sendRedirect(url);
    }
%>
+12  A: 

The someObject you are looking for is pageContext.

This object is implicitly defined in JSP, so you can use it like this:

pageContext.forward("<some relative jsp>");
adam
Good call! That's cleaner than getting the dispatcher explicitly.
erickson
+3  A: 

You really should try and avoid scriplets if you can, and in your case, a lot of what you are doing can be replaced with JSTL code. The following replacement for your example is much cleaner, IMO:

<%
  // Consider moving to a servlet or controller/action class
  String errorMessage = SomeClass.getInstance().doSomething();
  pageContext.setAttribute("errorMessage", errorMessage);
%>
<c:choose>
  <c:when test="${not empty errorMessage}">
    <c:set var="error" scope="session" value="${errorMessage}" />
    <jsp:forward page="error.jsp" />
  </c:when>
  <c:otherwise>
    <c:redirect url="index.jsp" />
  </c:otherwise>
</c:choose>

Ideally, you'd modify error.jsp so that the error message doesn't even need to be set in the session, but I didn't want to change your design too much.

Jack Leow
Can you please explain in your answer why scriptlets should be avoided in preference to JSTL?
Chris Carruthers
It's never been clear to me what the advantage of JSTL over plain scriptlets is. I've seen discussions that say that this allows non-programmers to create dynamic web pages because you don't have to know Java. But really now, just look at the example above: How is this NOT "programming"? Sure, it's not Java, but by any rational definition it is a programming language. So instead of learning and using Java, you can learn and use Java AND learn and use another language. What is gained, besides adding to the amount you have to learn?
Jay
I'm with the scriptlet people here. It's less code, avoids the clumsy `<c:when>` syntax, and faster, because the EL expression in the `when` is parsed as a string each time it's run, whereas the java code is compiled.
davidsheldon
@Jay et al, you do bring up a good point. In this case, JSP is simply being used (IMO, abused) as a programming language, as such it doesn't really matter. IMO, however, JSP should be used strictly as a templating engine, with only presentation logic (i.e., no controller logic, which is what we're doing here, or worse, business logic).
Jack Leow
I think there are good arguments to be made on both sides of "JSP as a programming language" versus "JSP as a template engine with servlets or whatever for business logic". (And I think the best argument AGAINST JSP as a programming language is: Sooner or later, you discover it's inadequate and have to do something else anyway. So why not do it sooner and be consistent?) But I really don't see the value of JSTL. It's just another programming language to learn, and a very weak one at that.
Jay
+1  A: 

A simple approach:

<%@page errorPage="Error.jsp" %>

<%
 String errorMessage = SomeClass.getInstance().doSomething();
 if (errorMessage != null) {
       throw new Exception(errorMessage); // Better throw the exception from doSomething()
 }
 pageContext.forward("index.jsp");
%>


Error.jsp
.........
<%@ page isErrorPage='true' %>
<%
out.print("Error!!!");  
out.print(exception.getMessage());
%>

Better approach:

Invoke the doSomething() from a servlet. Set your error page in web.xml

<error-page>
        <exception-type>java.lang.Exception</exception-type>
        <location>/WEB-INF/jsp/Error.jsp</location>
</error-page>
Personally -- and this is a totally personal preference, perhaps -- I think it's easier to do my flow control in JSP rather than with a combination of JSP, servlets, and web.xml settings. And the reason is illustrated by that sentence: If I do it all in JSP, then it's in one place, instead of three.
Jay