3 Replies Latest reply on May 3, 2011 3:43 AM by asioli

    How to add FacesMessage when customized Session object is expired

    janylj

      Hello,


      To my project, there is a customized Session which lives inside of HttpSession scope. It could expire before HttpSession expires. So I followed Jacob Orshalick's blog to implement when mySession expires, redirect user to the login page and display a message said Session time out and please login again. I am using Seam 2.0.1.GA.



           
      @Name("sessionListener")
      @Scope(ScopeType.SESSION)
      public class SessionListener {        
              @Observer("org.jboss.seam.beforePhase")
           public void beforePhase(PhaseEvent event) throws Exception {
                if(event.getPhaseId() == PhaseId.RESTORE_VIEW){               
                     //If the user is logged in and the session is expired raise the session expired event
                     if(isSessionExpired() && Identity.instance().isLoggedIn()) {     
                                    Events.instance().raiseEvent("org.jboss.seam.sessionExpired");
                     }               
                }
           }
           @Observer("org.jboss.seam.sessionExpired")
           public void sessionExpiredEventListener(){     
                FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Your session expired. Please login again...",null);
                faceMessages.add(msg);
              }
              @Observer("org.jboss.seam.afterPhase")
           public void flushMessages(PhaseEvent event) {
                PhaseId id = event.getPhaseId();
                if(id == PhaseId.INVOKE_APPLICATION){     
                     for(FacesMessage message : this.faceMessages){
                         FacesMessages.instance().add(message);
                     }
                     faceMessages.clear();          
                }
          }
      


      However, when the code enter after INVOKE APPLICATION phrase, the facesMessages
      object is already empty.  Then I debug through the flushMessages() method. The first time it is called is after RESTORE VIEW phrase, and the facesMessages still has content, but FacesMessages.instance() is not available. The second time it is called is still after RESTORE VIEW phrase, and the facesMessages content is gone. The third time is already after RENDER RESPONSE phrase, and facesMessages content is gone.


      Is there anyway to catch the sessionExpired event and add FacesMessage correctly? Thank you.

        • 1. Re: How to add FacesMessage when customized Session object is expired
          janylj

          I also tried to throw Exception instead of catching events.



               @Observer("org.jboss.seam.sessionExpired")
               public void sessionExpiredEventListener(){     
                    throw new NotLoggedInException();
               }


          Then in the pages.xml, I added:


              <exception class="org.jboss.seam.security.NotLoggedInException">
                  <end-conversation/>
                  <redirect view-id="/login.xhtml">
                      <message severity="ERROR">In order for you to resume your activities, please Log In.</message>
                  </redirect>
              </exception>



          However, the NotLoggedInException() is thrown, then:


          ERROR SeamPhaseListener.beforePhase:127 [] swallowing exception org.jboss.seam.security.NotLoggedInException 



          So when session expires, it doesn't even redirect to the login page.

          • 2. Re: How to add FacesMessage when customized Session object is expired
            janylj

            A couple clarifications of the original post. The sessionExpiredEventListener() should be:


                 @Observer("org.jboss.seam.sessionExpired")
                 public void sessionExpiredEventListener(){     
                      FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Your session expired. Please login again...",null);
                      faceMessages.add(msg);
                      Identity.instance().logout();
                 }



            A user case is:



            1. Let mySession expire on abc.xhtml page.

            2. Before RESTORE VIEW phrase, the org.jboss.seam.sessionExpired event is raised, a FacesMessage is added to this.faceMessages. Then logout is called.

            3. Identity.instance().logout() redirects to login.xhtml page.

            4. I guess before RESTORE VIEW phrase of the login.xhtml page, the sessionListener bean is instantiated again, which cause this.faceMessages content is lost. If it's true, why? The sessionListener bean is HttpSession scope. Although mySession expires, but HttpSession is not expired, why this bean is re-constructed.

            5. Login page is rendered without the error message.




            • 3. Re: How to add FacesMessage when customized Session object is expired
              asioli

              Hello


              Any luck solving this problem ? I think I have the same problem here... the Facesmessages don't survive the logout...


              Cheers,
                  Paolo