2012-07-25 82 views
3

按照answer of BalusC,我用重定向在@PostConstruct方法导致IllegalStateException异常

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方法之前是否应该提交响应?

如果您能给我一个建议,我将不胜感激。

+0

我非常肯定,即使在PostConstruct中完成了Response,JSF生命周期的其余部分仍然会被执行。你从构造函数中得到这个错误吗?这是一个Ajax请求吗?你使用的是什么JSF实现和版本? – 2012-07-25 11:06:59

+0

我正在使用JSF 2.0。另外,我必须在'@ PostConstruct'中执行,因为我需要在重定向之前从我的EJB中调用一个函数。这也不是AJAX请求。 – 2012-07-25 11:11:09

+0

响应已被提交,因为响应头已被FacesServlet操纵。这与完成的响应不同,这意味着主体已经写入并完成,直到渲染阶段才发生。在响应提交后的任何时候重定向将导致IllegalStateException,因此您唯一的选择是转发。 – 2012-07-25 14:18:53

回答

3

正如我提到的更新,以下行打印INIT true

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

我终于找到了为什么上述情况的发生。在我的网页,以前ManagedBean X,其中包含重定向功能,被UIComponent A引用,另一个ManagedBean Y是事先通过UIComponent B是在页面结构上面摆放UIComponent A引用。因此,响应部分由ManagedBean Y承诺,这使得ManagedBean X无法发送redirect请求。

2

重定向在这里不起作用,因为即使响应已经完成并最终完成,JSF也不够聪明,无法避免它的典型例行程序遍历生命周期事件。

相反,您可以尝试从RequestDispatcher执行Forward操作。 A正向是从重定向不同在以下几个方面:

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

通过这样做,你将结束Face过早地将sServlet转发到不同的servlet上。我想从另一个servlet中可能会重定向到所需的位置。

+0

:(这是唯一的方法来实现我想要的?创建一个新的servlet对于我需要的简单重定向来说似乎有点太多了。 – 2012-07-25 13:25:05

+0

请在我的更新中看看这个问题:)。 – 2012-07-25 14:00:29

相关问题