Thursday, August 4, 2011

Simple Session Timeout Handling with Seam/JSF/Facelets

I took Christian's great post http://relation.to/Bloggers/ImplementingGracefulSessionTimeoutWithSeamJSFAndJQuery and simplified it for my use.  My solution uses the same session checking mechanism, but assumes all pages should be handled the same, and that we just want to kick the user back to the landing page instead of the fancy stuff Christian did. Leave a comment if you need any of the code explained.

I'm assuming you're using Facelets, so you have some layout.xhtml (or whatever) that all your pages are using.  Just add this to the <head>:

<s:remote include="httpSessionChecker"/>
<script type="text/javascript">
var sessionChecker = Seam.Component.getInstance("httpSessionChecker");


   function alertTimeout(newSession) {
       if (newSession) {
           clearInterval(sessionTimeoutInterval);
           window.location = '#{facesContext.externalContext.request.contextPath}';
           alert('Your session has expired.  You have been logged out.');
       }
   }


        var sessionTimeoutInterval = setInterval('sessionChecker.isNewSession(alertTimeout)', '#{httpSessionChecker.timeout}'*1000+3000);
</script>


For Seam Remoting, add the jboss-seam-remoting.jar to your project and this to your web.xml:

 <servlet>
  <servlet-name>Seam Resource Servlet</servlet-name>
  <servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>Seam Resource Servlet</servlet-name>
  <url-pattern>/seam/resource/*</url-pattern>
 </servlet-mapping>



Create the HttpSessionChecker (modified from Christian's):


@Name("httpSessionChecker")
@Scope(ScopeType.APPLICATION)
public class HttpSessionChecker {

@WebRemote
    public boolean isNewSession() {
return ServletContexts.instance().getRequest().getSession().isNew();
    }

public int getTimeout() {
return ServletContexts.instance().getRequest().getSession().getMaxInactiveInterval();
}
}

For simplicity and safety, your best bet is to match all of the timeout times.  You want to match your web.xml, components.xml, and the server timeout.  Here's 30 minutes for all of them (a normal default):

  • your web.xml
 <session-config>
  <session-timeout>30</session-timeout>
 </session-config>
  • components.xml
<core:manager concurrent-request-timeout="500"
conversation-timeout="1800000" conversation-id-parameter="cid"
parent-conversation-id-parameter="pid" />
  • C:\jboss-5.1.0.GA\server\default\deployers\jbossweb.deployer\web.xml
   <session-config>
      <session-timeout>30</session-timeout>
   </session-config>

That should be it.  Now if they leave any page for 30 minutes, it will redirect them to the landing page, and alert them that their session expired.  Its not fancy, but its a good default to start with.