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?
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:
- How to navigate in JSF? How to make URL reflect current page (and not previous one)
- ExternalContext.dispatch() not working
This worked for me:
FacesContext.getCurrentInstance().getExternalContext().dispatch("/ServletUrl");
(pay special attention to the fwd slash '/')