Question

I want to forward request to a non-JSF page from JSF action method. I am using below code in my JSF action :

public String submitUserResponse() {
    // ...

    parseResponse("foo.jsp", request, response);

    // ...

    return "nextpage";
}  

private String parseResponse(String uri, HttpServletRequest request, HttpServletResponse response) {
    if (uri != null) { 
        RequestDispatcher dispatcher = request.getRequestDispatcher(uri);
        dispatcher.forward(request, response);
        return null;
    }

    // ...

    return "xxxx";
}

The submitUserResponse() action method is being called when user clicks the submit button from the JSF page and this method returns nextpage string. Here the request forwards to next JSF page in normal flow. But in my requirement, I need to forward request to next non-JSF page. It is going, but it is displaying below exception in server.

java.lang.IllegalStateException: Cannot forward after response has been committed

I observed that code lines between parseResponse(...) and return "nextpage"; are still being executed after forwarding my request using dispatched.forward(uri). Same thing happened with response.sendRedirect(url). How is this caused and how can I solve it?

Was it helpful?

Solution

Here my doubts are: 1.why next lines of code is being executed after forwarding my request using dispatched.forward(uri) . Same thing happening in response.sendRedirect("").

Because you didn't call return to jump out of the method block. The include(), forward() or sendRedirect() really doesn't have some magic that they automagically does that. Those are still just Java methods like any other (except of System#exit() of course). They will be invoked in order and the code will just continue until end of method block or return statement. It's just all about the code flow you write and control yourself.

That said, the normal JSF practice is that you should use ExternalContext#dispatch() or ExternalContext#redirect() for this (the first is applicable in your case). Not only it keeps your code free from unnecessary "under-the-hood" clutter in JSF code such as the Servlet API, but it also removes the need to call FacesContext#responseComplete() which you could also have done to fix your initial IllegalStateException problem.

In a nutshell: replace your code by

public void submitUserResponse(){
    String uri = "foo.jsp";
    FacesContext.getCurrentInstance().getExternalContext().dispatch(uri);
}  

That's all. No need to unnecessarily dig the Servlet request/response from under the JSF hoods. Note that the method is declared void. This is perfectly acceptable, although some know-it-better like IDE's will complain about it, if so, then just ignore it or replace by String and add return null;.

See also:

OTHER TIPS

This worked for me:

FacesContext.getCurrentInstance().getExternalContext().dispatch("/ServletUrl");

(pay special attention to the fwd slash '/')

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top