当会话超时时,为什么基于Phase Listener的JSF重定向不能用于AJAX请求?

时间:2012-06-21 18:44:43

标签: jsf-2

我有一个JSF Phase Listerner,用于检查用户是否已登录,如果没有,则将其重定向到登录页面。这适用于非ajax请求。但是,如果用户在一个页面上,在我的情况下,一个有一个primefaces数据表,并点击一个调用ajax请求的按钮 - 但他们的会话超时 - 代码被执行,发出重定向(使用ExternalContext#redirect),但用户未导航到登录页面。

知道为什么这不起作用吗?

这是我的阶段监听器:

private static final String IS_LOGGED_IN_INDICATOR = "loggedIn";
private static final String LOGIN_PAGE = "/login.jsp";

public PhaseId getPhaseId() {
    return PhaseId.RESTORE_VIEW;
}

public void beforePhase(PhaseEvent event) {
    ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
    HttpSession session = (HttpSession)ec.getSession(false);

    if (session==null || session.getAttribute(IS_LOGGED_IN_INDICATOR) == null) {
       try {
            ec.redirect(LOGIN_PAGE);
       }
       catch(IOException e) {
           // log exception...
       }            
    }
}

public void afterPhase(PhaseEvent event) {
    // no-op
}   

}

2 个答案:

答案 0 :(得分:3)

失败是因为ajax上下文试图从视图根获取渲染工具包,而根本没有视图根。它尚未在那时恢复。这导致NullPointerException中的PartialViewContext#createPartialResponseWriter()。反过来,这个异常不会被抛出,而是放在一个应该由自定义ExceptionHandler处理的ajax异常队列中。你显然没有任何一个。如果您创建/使用FullAjaxExceptionHandler之类的此类异常,则会显示此异常(有关详细信息,另请参阅this blog)。

要解决特定问题,请改为使用afterPhase()中的作业。然后完全恢复视图根,并且ajax上下文可以从中获取渲染工具包,以便编写专门的XML响应,该响应指示JavaScript中的JSF ajax引擎更改窗口位置。如果没有ajax,则不需要渲染工具包,因为重定向基本上只是设置响应头。

特定NullPointerException是否是Mojarra中的错误是一个不同的问题,可以更好地在他们自己的问题跟踪器上发布问题报告的风格。

答案 1 :(得分:-1)

这是因为你必须在XML中为Ajax请求发送一个特殊的响应才能进行重定向(检查this answer),我已经在这样的过滤器中实现了这个..

// Check if it's an Ajax Request 
if ("partial/ajax".equals(((HttpServletRequest) request).getHeader("Faces-Request"))) {
      //redirect 
      response.setContentType("text/xml");
      response.getWriter()
           .append("<?xml version=  \"1.0\" encoding=\"UTF-8\"?>")
           .printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>",url);

你应该将它移植到你的Phase Listener。