I need to access an application-scoped managed bean to modify certain properties from within an HttpSessionListener.
I already used something like the following:
@Override
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession session = se.getSession();
User user = userService.findBySessionId(session.getId());
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
ApplicationScopedBean appBean = (ApplicationScopedBean) externalContext.getApplicationMap().get("appBean");
appBean.getConnectedUsers().remove(user);
}
externalContext = FacesContext.getCurrentInstance().getExternalContext() causes a null pointer exception here already, and even if it didn’t I’m not sure appBean could be accessible the above way.
Any ideas?
The
FacesContextis only available in the thread serving the HTTP request initiated by the webbrowser which has invoked theFacesServlet. During a session destroy there’s not necessarily means of a HTTP request. Sessions are usually destroyed by a background thread managed by the container. This does not invoke a HTTP request through theFacesServlet. So you should not expect theFacesContextto be always there during the session destroy. Only when you callsession.invalidate()inside a JSF managed bean, then theFacesContextis available.If your application scoped managed bean is managed by JSF
@ManagedBean, then it’s good to know that JSF stores it under the covers as an attribute of theServletContext. TheServletContextin turn is available in the session listener byHttpSession#getServletContext().So, this should do:
If you’re running a Servlet 3.0 capable container, an alternative is to just let your application scoped bean implement
HttpSessionListenerand register itself as such upon construction. This way you have direct reference to theconnectedUsersproperty.Again another alternative is to keep the
Userin the session scope as a session scoped managed bean. You can then use the@PreDestroyannotation to mark a method which should be invoked when the session is destroyed.This has the additional benefit that the
Useris in EL context available as#{user}.