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?
This worked for me:
FacesContext.getCurrentInstance().getExternalContext().dispatch("/ServletUrl");
(pay special attention to the fwd slash '/')
Because you didn't call
return
to jump out of the method block. Theinclude()
,forward()
orsendRedirect()
really doesn't have some magic that they automagically does that. Those are still just Java methods like any other (except ofSystem#exit()
of course). They will be invoked in order and the code will just continue until end of method block orreturn
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()
orExternalContext#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 callFacesContext#responseComplete()
which you could also have done to fix your initialIllegalStateException
problem.In a nutshell: replace your code by
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 byString
and addreturn null;
.See also: