在HttpSessionListener中初始化JSF SessionScoped bean时出现StackOverflow错误

时间:2011-11-01 00:08:09

标签: jsf servlets jsf-2 httpsession servlet-listeners

继续我的previous question,我正在尝试在应用程序的会话首次启动时初始化会话范围的JSF bean,因此无论用户在Web上访问哪个页面,该bean都可供用户使用申请第一。我的自定义监听器:

public class MyHttpSessionListener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        if (FacesContext.getCurrentInstance().getExternalContext().getSessionMap()
                .get("mySessionBean") == null) {
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap()
                    .put("mySessionBean", new MySessionBean());
        }
    }
}

然而,这给了我一个堆栈溢出错误。似乎put()类中的SessionMap方法尝试创建新的HttpSession,从而导致我的侦听器发生无限循环。如何在应用程序的会话首次启动时初始化JSF会话范围的bean,而不会遇到此问题?

我正在使用JSF 2和Spring 3,在WebSphere 7上运行。

谢谢!

1 个答案:

答案 0 :(得分:2)

此时会话尚未完全创建。只有当侦听器方法离开时,会话才会被放入上下文中,并由request.getSession()提供,因为JSF的getSessionMap()正在使用。

相反,您应该从event参数中获取会话并使用其setAttribute()方法。 JSF在那里查找并存储会话范围的托管bean,如果已经存在则不会创建新的。

public void sessionCreated(HttpSessionEvent event) {
    event.getSession().setAttribute("mySessionBean", new MySessionBean());
}

请注意,我删除了多余的nullcheck,因为那时不可能会话bean已经存在。


对具体问题

无关,实际上你应该永远不要依赖于不由JSF管理的实现中存在的FacesContext。很可能会在非JSF请求期间创建会话。