jsfprimefacessession-timeoutexpired-sessions

Automatically perform action in client side when the session expires


I want to display in a <p:growl> that the session has expired.

I found many methods to handle session expiration like:

But I couldn't push a faces message to <p:growl>.

To the point, how can I automatically run some (JavaScript) code in client side when the HTTP session has automatically expired in server side?


Solution

  • You can use PrimeFaces idle monitor for this. User is redirected to logout action after timeout to invalidate the session. 2 minutes before a countdown dialog is shown to warn user. After moving the mouse again session is extended.

    PrimeFaces idle monitor and dialog is placed in a template you can add to every page which is involved:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml"
       xmlns:h="http://java.sun.com/jsf/html"
       xmlns:ui="http://java.sun.com/jsf/facelets"
       xmlns:p="http://primefaces.org/ui">
    
    <ui:composition>
       <h:form prependId="false">
          <p:idleMonitor
         timeout="#{session.maxInactiveInterval * 1000 - 125000}"
         onidle="startIdleMonitor()"
         onactive="timeoutDialog.hide()" />
    
          <p:dialog id="timeoutSession"
         header="#{msg['session.expire']}"
         widgetVar="timeoutDialog"
         showEffect="fade" hideEffect="fade"
         modal="true"
         width="400"
         height="110"
         closable="false"
         draggable="false"
         resizable="false"
         appendToBody="true"
         onHide="stopCount()"
         onShow="doTimer()">
         <br />
         <p>
            <span class="ui-icon ui-icon-alert" style="float: left; margin: 8px 8px 0;"/>
            <p:panel>
               #{msg['logoff.soon.1']}
               <span id="dialog-countdown" style="font-weight: bold"></span>
               #{msg['logoff.soon.2']}
            </p:panel>
         </p>
         <br />
         <p style="font-weight: bold;">#{msg['move.cursor']}</p>
          </p:dialog>
          <p:remoteCommand name="keepAlive" actionListener="#{auth.keepSessionAlive}" />
       </h:form>
       <script type="text/javascript">
          var TIME = 120; // in seconds
          var countTimer = TIME;
          var processTimer;
          var timer_is_on = 0;
          var redirectPage = "#{request.contextPath}/auth/j_verinice_timeout";
    
          var countDownDiv = "dialog-countdown";
          var txtCountDown = null;
          if (!txtCountDown)
            txtCountDown = document.getElementById(countDownDiv);
    
          function startIdleMonitor() {
            countTimer = TIME;
            txtCountDown.innerHTML = countTimer;
            timeoutDialog.show();
          }
          function timedCount() {
            txtCountDown.innerHTML = countTimer;
            if (countTimer == 0) {
                stopCount();
                window.location.href = redirectPage;
                return;
            }
            countTimer = countTimer - 1;
            processTimer = setTimeout("timedCount()", 1000);
          }
          function doTimer() {
            if (!timer_is_on) {
                timer_is_on = 1;
                timedCount();
            }
          }
          function stopCount() {
            clearTimeout(processTimer);
            timer_is_on = 0;
            keepAlive();
          }
          </script>
    </ui:composition>
    </html>
    

    To activate timeout handling in multiple pages include the timeout template in your layout template:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xml:lang="de-DE">
    <h:head>
      ...
    </h:head>
    <body>
      <ui:include src="/template/sessionTimeOut.xhtml" />
      <ui:include src="/nav.xhtml"/>>
      <ui:insert name="content">Default content</ui:insert>
      <ui:include src="/footer.xhtml"/>>
    </body>
    </html>
    

    A specific time out for your web application you can set in your web.xml:

    <!--?xml version="1.0" encoding="UTF-8"?-->
    <web-app>
       ...
       <session-config>
          <!-- Session idle timeout in min. -->
          <session-timeout>30</session-timeout>
        </session-config>
    </web-app>
    

    You can read more about this solution in this blog post: JSF and PrimeFaces: Session Timeout Handling