2010-10-15 4 views
14

Mon application Web a des utilisateurs qui se connectent. Il y a un timeout. Avant l'expiration de la session, je voudrais exécuter une méthode pour nettoyer certains verrous.Méthode Invoke juste avant l'expiration de la session

Je l'ai mis en place un sessionListener mais une fois que j'arrive public void sessionDestroyed(HttpSessionEvent event) la session est déjà parti et j'ai besoin des données qu'il contient, donc je voudrais exécuter une méthode (qui a besoin de la session en vie et être en mesure d'accéder FacesConfig.getCurrentInstance()) avant la session est réellement expirée.

Comment puis-je faire cela? Des idées? Ceci est ma session 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()); 
    } 
} 

Mais je reçois NullPointerException à FacesContext.getCurrentInstance().getApplication() soit parce getCurrentInstance est nulle ou getApplication retourne NULL

Répondre

17

Vous pouvez y parvenir en mettant en œuvre un HttpSessionBindingListener vous devez vous inscrire une session qui détient un verrou en appelant registerSession (la chaîne "sessionBindingListener" ne peut pas être modifiée). Le conteneur rappellera la méthode valueUnbound() après expiration de la session et avant la session est détruite.

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

Fonctionne comme un charme. +1 et accepté – pakore

+0

Je l'ai mis sous la classe 'UserBean', qui connaît' LockBean'. Je l'avais déjà implémenté à partir d'une question précédente, répondue par ... BalusC: D, donc j'avais juste besoin d'ajouter la ligne 'lock.unlock' et ça a marché. Merci à vous deux. – pakore

+0

L'implémentation de 'HttpSessionBindingListener' est en effet préférable. Vous n'avez qu'à vous assurer que 'registerSession()' est appelé lors d'une requête JSF (cependant, cette méthode est inutile si 'ObjectLock' est déjà un bean géré de session.) – BalusC

4

Une solution plus élégante:

il suffit d'ajouter une @PreDestroy Annotation à une session de haricots! Si la session va être détruite, elle appellera PreDestroy sur tous les SessionBeans à l'avance, là vous pouvez vous déconnecter et tout!

Bien que cela ne fonctionne pas actuellement avec de nombreux serveurs Application, semble être un segment peu clair de la spécification JSF. Donc aller avec la réponse acceptée (HttpSessionBindingListener) sera nécessaire, jusqu'à ce que @PreDestroy fonctionne comme prévu sur tous les serveurs.

Questions connexes