在@PostConstruct方法中重定向导致IllegalStateException

时间:2012-07-25 10:55:09

标签: redirect jsf-2 illegalstateexception

根据answer of BalusC,我使用了

FacesContext.getCurrentInstance().getExternalContext().redirect(url);

在我的@PostConstruct方法中阻止JSF呈现视图并重定向用户。但是,当我尝试运行代码时,我仍然遇到上述行的java.lang.IllegalStateException异常。

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)

更新:我在@PostConstruct方法中添加了以下行:

System.out.println("INIT " + FacesContext.getCurrentInstance().getExternalContext().isResponseCommitted());

我看到的是INIT true。我想知道在调用@PostConstruct方法之前是否应该提交响应?

如果你能给我一个建议,我将非常感激。

2 个答案:

答案 0 :(得分:3)

正如我的更新中所述,以下行打印了INIT true

System.out.println("INIT " + FacesContext.getCurrentInstance().getExternalContext().isResponseCommitted());

我终于找到了上述情况发生的原因。在我的网页上,在ManagedBean X(包含重定向功能)之前,UIComponent A引用了另一个ManagedBean Y,之前UIComponent B引用了UIComponent AManagedBean Y位于ManagedBean X之上在页面结构中。因此,redirect部分提交了回复,这使得{{1}}无法发送{{1}}请求。

答案 1 :(得分:2)

重定向在这里不起作用,因为即使响应已经完成并最终确定,JSF也不够智能,无法避免其通过生命周期事件的典型例程。

相反,您可以尝试从RequestDispatcher执行转发。转发与以下方式的重定向不同:

  • 由servlet内部执行
  • 浏览器无动于衷
  • 原始网址保持不变

以下是一些显示如何完成此操作的代码...

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);
}

通过执行此操作,您将过早地结束FacesServlet的执行并将其转发到另一个servlet上。我想,从这个其他servlet可以重定向到所需的位置。