2010-10-15 19 views
14

Mi aplicación web tiene usuarios que inician sesión. Hay un tiempo de espera. Antes de que la sesión expire, me gustaría ejecutar un método para limpiar algunos bloqueos.Método de invocación justo antes de que la sesión caduque

he implementado un sessionListener pero una vez que llegue public void sessionDestroyed(HttpSessionEvent event) la sesión ya se ha ido y necesito algunos datos de él, así que le gustaría ejecutar un método (que necesita la sesión activa y ser capaz de acceder FacesConfig.getCurrentInstance()) antes la sesión en realidad ha expirado.

¿Cómo puedo hacer eso? ¿Algunas ideas? Este es mi sesión de escucha:

public class MySessionListener implements HttpSessionListener { 

    private static final Logger log = LoggerFactory.getLogger(MySessionListener.class); 

    public MySessionListener() { 

    } 

    public void sessionCreated(HttpSessionEvent event) { 
     log.debug("Current Session created : " 
       + event.getSession().getId()+ " at "+ new Date()); 
    } 

    public void sessionDestroyed(HttpSessionEvent event) { 
     // get the destroying session... 

     HttpSession session = event.getSession(); 
     prepareLogoutInfoAndLogoutActiveUser(session); 

     log.debug("Current Session destroyed :" 
       + session.getId()+ " Logging out user..."); 

     /* 
     * nobody can reach user data after this point because 
     * session is invalidated already. 
     * So, get the user data from session and save its 
     * logout information before losing it. 
     * User's redirection to the timeout page will be 
     * handled by the SessionTimeoutFilter. 
     */ 

     // Only if needed 
    } 

    /** 
    * Clean your logout operations. 
    */ 
    public void prepareLogoutInfoAndLogoutActiveUser(HttpSession httpSession) { 
     UserBean user = FacesContext.getCurrentInstance().getApplication().evaluateExpressionGet(FacesContext.getCurrentInstance(), "#{user}", UserBean.class); 
     LockBean lock = FacesContext.getCurrentInstance().getApplication().evaluateExpressionGet(FacesContext.getCurrentInstance(), "#{lock}", LockBean.class); 
     lock.unlock(user.getUsername()); 
     log.info("Unlocked examination for user: "+user.getUsername()); 
    } 
} 

Pero estoy NullPointerException en FacesContext.getCurrentInstance().getApplication() porque o getCurrentInstance es nulo o getApplication devuelve NULL

Respuesta

17

Puede lograr que mediante la implementación de un HttpSessionBindingListener necesita registrar una sesión que mantiene un candado llamando al registerSession (la cadena "sessionBindingListener" no se puede cambiar). El contenedor devolverá la llamada al método valueUnbound() después de que se agotó el tiempo de espera de la sesión y antes de que se destruya la sesión.

public class ObjectLock implements Serializable,HttpSessionBindingListener { 
    public void valueBound(HttpSessionBindingEvent event) { 
     log.info("valueBound:" + event.getName() + " session:" + event.getSession().getId()); 

    } 

    public void registerSession() { 
     FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("sessionBindingListener", this ); 
     log.info("registered sessionBindingListener" ); 
    } 

    public void valueUnbound(HttpSessionBindingEvent event) { 
     log.info("valueUnBound:" + event.getName() + " session:" + event.getSession().getId()); 
       // add you unlock code here: 
     clearLocksForSession(event.getSession().getId()); 
    } 
} 
+0

Funciona como un encanto. +1 y aceptado. – pakore

+0

Lo puse bajo la clase 'UserBean', que conoce' LockBean'. Ya había implementado esto desde una pregunta anterior respondida por ... BalusC: D, así que solo necesitaba agregar la línea 'lock.unlock' y funcionó. Gracias a los dos. – pakore

+0

Implementar 'HttpSessionBindingListener' es realmente mejor. Solo necesita asegurarse de que se llama a 'registerSession()' durante una solicitud de JSF (sin embargo, ese método es inútil si 'ObjectLock' ya es un bean administrado con ámbito de sesión. – BalusC

4

Uno más elegante solución:

Sólo añadir una anotación @PreDestroy a una sesión de Bean! Si la sesión va a ser destruida, llamará a PreDestroy en todas las SessionBeans de antemano, ¡allí podrá desconectarse y todo!

Aunque esto actualmente no funciona con muchos ApplicationServers, parece ser un segmento poco claro de la especificación JSF. Por lo tanto, será necesario recurrir a la respuesta aceptada (HttpSessionBindingListener), hasta que @PreDestroy funcione según lo previsto en todos los servidores.

Cuestiones relacionadas