Reputation: 9266
According to the answer of BalusC, I used
FacesContext.getCurrentInstance().getExternalContext().redirect(url);
in my @PostConstruct
method to stop JSF from rendering the view and redirect users. However, when I try to run the code, I still ran into the java.lang.IllegalStateException
exception at the above line.
WARNING: StandardWrapperValve[Faces Servlet]: PWC1406: Servlet.service() for servlet Faces Servlet threw exception
java.lang.IllegalStateException
at org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:524)
at StudentManagedBean.CourseSummary.init(CourseSummary.java:55)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
UPDATE: I added the following line in my @PostConstruct
method:
System.out.println("INIT " + FacesContext.getCurrentInstance().getExternalContext().isResponseCommitted());
and what I saw was INIT true
. I wonder if the response is supposed to be committed BEFORE the @PostConstruct
method is called?
I'd be very grateful if you could give me an advice.
Upvotes: 3
Views: 4739
Reputation: 9266
As mentioned in my update, the following line printed INIT true
:
System.out.println("INIT " + FacesContext.getCurrentInstance().getExternalContext().isResponseCommitted());
I finally found why the above situation occurred. On my page, before the ManagedBean X
, which contains the redirect function, was referenced by UIComponent A
, another ManagedBean Y
was referenced beforehand by UIComponent B
that is placed above UIComponent A
in the page structure. As a consequence, the response was partially committed by ManagedBean Y
, which makes it impossible for ManagedBean X
to send a redirect
request.
Upvotes: 3
Reputation: 10463
A redirect will not work here, because even though the response has been completed and finalized, JSF is not smart enough to avoid its typical routine of running through the lifecycle events anyway.
Instead you can try doing a Forward from a RequestDispatcher. A Forward is different from a redirect in the following ways:
Here is some code that displays how this can be done...
RequestDispatcher dispatcher =
((ServletRequest) context.getExternalContext().getRequest())
.getRequestDispatcher("/j_spring_security_logout");
try {
dispatcher.forward((ServletRequest) context.getExternalContext().getRequest(),
(ServletResponse) context.getExternalContext().getResponse());
} catch (ServletException e) {
log.error("ServletException", e);
} catch (IOException e) {
log.error("IOException", e);
}
By doing this you are ending the execution of the FacesServlet prematurely and forwarding it onto a different servlet altogether. I imagine that from this other servlet it might be possible to redirect to the desired location.
Upvotes: 2