web.xml
<session-config> <session-timeout>10</session-timeout> </session-config>
For detection session expired in web application, developers can use HttpSessionListener to detect session's expiration immediately whenever the container invoke the HttpSessionListener#sessionDestroyed event.
The below example is applyed for detecting data in session before timeout.
/** * * @author Wittakarn */ public class SimpleSessionListener implements HttpSessionListener, Serializable { @Override public void sessionCreated(HttpSessionEvent se) { System.out.println("session created : " + se.getSession().getId()); } @Override public void sessionDestroyed(HttpSessionEvent se) { HttpSession session = se.getSession(); UserSession user = (UserSession) session.getAttribute("userSession"); if(user != null) System.out.println("login user :" + user.getUsername()); /*Do some bussiness logic such as save audit logs to db, save logout history, and so on.*/ System.out.println("session destroyed :" + session.getId() + " Logging out user..."); } }
At last, definition session listener in web.xml.
<listener> <listener-class> com.wittakarn.listener.SimpleSessionListener </listener-class> </listener>
However, detection session expired by using HttpSessionListener cannot resolve some user's requirements. In the case of requirement, that require to popup dialog for notifing before session out. In this proposed, I would like to present Time Counter For Session Timeout Handling by applying JSF and primefaces 5.1.
index.xhtml
index.xhtml |
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui"> <h:head> <f:facet name="first"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"/> <meta name="apple-mobile-web-app-capable" content="yes" /> </f:facet> <title>Login</title> </h:head> <h:body> <h:form> <p:outputLabel value="user"/> <p:inputText value="#{loginBean.user.username}" required="true"/> <br/> <p:outputLabel value="password"/> <p:password value="#{loginBean.user.password}" required="true"/> <br/> <p:commandButton value="Login" process="@form" update="@form" action="#{loginBean.submit}"/> </h:form> </h:body> </html>
display.xhtml
display.xhtml |
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui"> <h:head> <f:facet name="first"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"/> <meta name="apple-mobile-web-app-capable" content="yes" /> </f:facet> <title>Display</title> </h:head> <h:body> <h:form> <p:outputLabel value="user "/> <p:outputLabel value="#{loginBean.user.username}"/> <p:outputLabel value=" login success..."/> <p:idleMonitor timeout="5000" onidle="PF('alertExpire').show();"> </p:idleMonitor> </h:form> <p:dialog header="Basic Dialog" widgetVar="alertExpire" onShow="startIdleMonitor()"> <h:outputText value="Your browser session is expiring in " /> <h:outputText id="dialog-countdown" style="font-weight: bold;"/> <h:outputText value=" second." /> <br/> <h:outputText value="Do you want to continue your session?" /> <h:form> <p:commandButton value="Yes" process="@this" update="@all" onclick="stopCount()"/> <p:commandButton value="No" process="@this" update="@all" action="#{loginBean.logout}"/> <p:remoteCommand name="logout" action="#{loginBean.logout}" /> </h:form> <script type="text/javascript"> var TIME = 10; // in seconds var countTimer = TIME; var processTimer; var timer_is_on = 0; var countDownDiv = "dialog-countdown"; var txtCountDown = null; if (!txtCountDown) txtCountDown = document.getElementById(countDownDiv); function startIdleMonitor() { countTimer = TIME; txtCountDown.innerHTML = countTimer; doTimer(); } function timedCount() { txtCountDown.innerHTML = countTimer; if (countTimer == 0) { stopCount(); logout(); 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; } </script> </p:dialog> </h:body> </html>
/** * * @author Wittakarn */ @ViewScoped @ManagedBean(name = "loginBean") public class LoginBean { @ManagedProperty(value = "#{userSession}") private UserSession user; public UserSession getUser() { return user; } public void setUser(UserSession user) { this.user = user; } public String submit(){ return "display.xhtml"; } public String logout(){ FacesContext.getCurrentInstance() .getExternalContext() .invalidateSession(); return "/index.xhtml?faces-redirect=true"; } }
UserSession.java
/** * * @author Wittakarn */ @SessionScoped @ManagedBean(name = "userSession") public class UserSession implements Serializable{ private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }