2010-10-15 12 views
14

La mia webapp ha utenti che effettuano l'accesso. C'è un timeout. Prima che la sessione scada, vorrei eseguire un metodo per pulire alcuni blocchi.Invoca il metodo prima della scadenza della sessione

Ho implementato un sessionListener ma una volta raggiungo public void sessionDestroyed(HttpSessionEvent event) la sessione è già andato e ho bisogno di alcuni dati da esso, quindi vorrei eseguire un metodo (che ha bisogno viva la sessione e in grado di accedere FacesConfig.getCurrentInstance()) prima la sessione è effettivamente scaduta.

Come posso farlo? Qualche idea? Questa è la mia Sessione Listener:

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()); 
    } 
} 

Ma sto NullPointerException a FacesContext.getCurrentInstance().getApplication() perché o getCurrentInstance è nulla o getApplication restituisce il valore null

risposta

17

È possibile ottenere che mediante l'attuazione di un HttpSessionBindingListener è necessario registrare una sessione che detiene un blocco chiamando lo registerSession (la stringa "sessionBindingListener" non può essere modificata). Il contenitore richiamerà il metodo valueUnbound() dopo il timeout della sessione e prima dello la sessione viene distrutta.

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

Funziona come un fascino. +1 e accettato. – pakore

+0

L'ho messo nella classe 'UserBean', che conosce' LockBean'. L'avevo già implementato da una precedente domanda a cui ho risposto ... BalusC: D, quindi ho solo dovuto aggiungere la riga 'lock.unlock' e ha funzionato. Grazie a tutti e due. – pakore

+0

L'implementazione di 'HttpSessionBindingListener' è davvero migliore. Devi solo assicurarti che 'registerSession()' venga chiamato durante una richiesta JSF (tuttavia, quel metodo è inutile se 'ObjectLock' è già un bean gestito con scope di sessione. – BalusC

4

Ancora una soluzione elegante:

Basta aggiungere un annotazione @PreDestroy a una sessione-Bean! Se la Sessione sarà distrutta, chiamerà PreDestroy su tutti i SessionBeans in anticipo, lì potrai uscire e tutto!

Sebbene questo non funzioni attualmente con molti ApplicationServer, sembra essere un segmento non chiaro della specifica JSF. Sarà quindi necessaria la risposta accettata (HttpSessionBindingListener), fino a quando @PreDestroy funzionerà come previsto su tutti i server.

Problemi correlati