Pages

March 2, 2014

How To Implement Session Expired Alert using JSF, PrimeFaces and Java Script

You have to handle this issue at client side, because any solution that uses server side scripts initiates session time again. We can use java script for solving this issue.

Basically the solution has four steps.
1. After user logs into the system, a timer equals to the session time is set and count down is started.
2. Each server request the server side session time is restarted, so count down is restarted.
3. When the count down is close to 0, system shows additional time dialog to the user.
4. At the end of the count down, user is redirected to the exit page.

The implementation and demo is below. Java script code is placed in .xhtml document at this implementation but if you use a .js file you can paste the code in it.


Important code lines and explanations.

1.
if (document.getElementById('loggedInUserId') == null) {
  return;
}

With this code line we check the logged user info in rendered xhtml. So we sure that user logged in and ready for count down.
2.
<p:ajaxStatus onstart="statusDialog.show();" 
    onsuccess="statusDialog.hide();countDownInit();" />
With this code line we restart count down again with any ajax request. Because in each server request the server side session time is restarted.
3.
if (0 > minute) {
  exit();
  return;
}

At the end of the count down, we redirect current page to the exit page.
4.
<p:commandButton value="Yes" process="@this" 
    update="@none" oncomplete="additionalTimeDialog.hide();" />
<p:commandButton value="No" type="button" onclick="exit();" />

If the user clicks yes button to get extra time we send an ajax request using command button and close the additional time dialog. So with this request server side session time will be restarted.

If the use clikcs no button, we simply redirect user to the exit page.

index.xhtml
<?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:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:p="http://primefaces.org/ui"
  xmlns:f="http://java.sun.com/jsf/core">
  <h:head>
    <title>Facelet Title2</title>
  <script type="text/javascript">
    var countDownTime; //in miliseconds
    var sessionTime = 61000; //in miliseconds
    var whenToShowAdditionalTimeDialog = 60000; //in miliseconds 
    var isAdditionalTimeDialogShowed = false;
    var countDownStarted = false;
    var minute;
    var second;
    function countDownInit() {
      countDownTime = (new Date()).getTime();
      minute = 1;
      second = 00;
      countDownStarted = false;
    }
    function checkCountDown() {
      if (document.getElementById('loggedInUserId') == null) {
        return;
      }
      var now = (new Date()).getTime();
      if (now - countDownTime > (sessionTime - whenToShowAdditionalTimeDialog)) {
        additionalTimeDialog.show();
        countDownStarted = true;
      }
      if (countDownStarted) {
        second = second - 1;
        if (0 > second) {
          second = 59;
          minute = minute - 1;
        }
        if (0 > minute) {
          exit();
          return;
        }
        document.getElementById('additionalTimeDialog:minuteOutput').innerHTML = minute;
        document.getElementById('additionalTimeDialog:secondOutput').innerHTML = second;
      }
    } 
    function exit() {
      document.location.href = '/projectname/eng/loggedout.xhtml';
    }
    window.setInterval(checkCountDown, 1000);
    </script>
  </h:head>

  <h:body>
    <p:ajaxStatus onstart="statusDialog.show();" 
        onsuccess="statusDialog.hide();countDownInit();" />
    <p:dialog modal="true" widgetVar="statusDialog" header="Status" 
        draggable="false" closable="false">
      <p:graphicImage value="/image/ajaxloadingbar.gif" />
    </p:dialog>
    <p:dialog modal="true" widgetVar="additionalTimeDialog" header="Alert" 
         draggable="false" closable="false">
      <h:form id="additionalTimeDialog"> Your session time will be expired in 
        <h:outputText id="minuteOutput" /> : <h:outputText id="secondOutput" /> . 
            Do you want extra time ?
        <p:commandButton value="Yes" process="@this" update="@none" 
            oncomplete="additionalTimeDialog.hide();" />
        <p:commandButton value="No" type="button" onclick="exit();" />
      </h:form>
    </p:dialog>
    <h:form id="form" prependId="false">
      <p:remoteCommand name="sendRequest" update="@none" process="@this" />
      <h:panelGrid id="userform">
        <p:panelGrid columns="2" rendered="#{not testManagedBean.userLogged}">
          <h:outputLabel value="Name" />
          <p:inputText value="#{testManagedBean.name}" />
          <h:outputLabel value="Password" />
          <p:inputText value="#{testManagedBean.passWord}" />
          <p:separator />
          <p:commandButton value="Log in" action="#{testManagedBean.login}" 
                process=":form:userform" update=":form:userform" />
        </p:panelGrid>
        <p:panelGrid columns="2" rendered="#{testManagedBean.userLogged}">
          <h:outputLabel value="Name" />
          <h:outputText id="loggedInUserId" value="#{testManagedBean.name}" />
        </p:panelGrid>
        </h:panelGrid>
      </h:form>
  </h:body>
</html>
loggedout.xhtml

<?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:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:p="http://primefaces.org/ui"
  xmlns:f="http://java.sun.com/jsf/core">
  <h:head>
    <title>LoggedOut.xhtml</title>
  </h:head>
  <h:body>
    Logged out.
  </h:body>
</html>

Test.java
package controlleryonetici;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
@ManagedBean(name = "testManagedBean")
@ViewScoped
public class Test {
  private String name;
  private String passWord;
  private boolean userLogged = false;
  public String getPassWord() {
    return this.passWord;
  }
  public void setPassWord(final String passWord) {
    this.passWord = passWord;
  }
  public String getName() {
    return this.name;
  }
  public void setName(final String name) {
    this.name = name;
  }
  public void login() {
    if ("admin".equals(this.name) && "admin".equals(this.passWord))
      this.userLogged = true;
    }
    public boolean getUserLogged() {
      return this.userLogged;
    }
    public void setUserLogged(final boolean isUserLogged) {
      this.userLogged = isUserLogged;
  }
}
Demo

1. log in



2. alert



3. log out



No comments:

Post a Comment