JSF Session Timeout Handling

Here's my solution for session handling. When your session timed out, you will be redirected to the index page which is commonly the login page to login again.

package com.mypackage.web.session;

import javax.faces.FacesException;
import javax.faces.application.Application;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.http.HttpSession;

public class SessionPhaseListener implements PhaseListener {

private static final String homepage = "index.jsp";

@Override
public void afterPhase(PhaseEvent event) {
//Do anything
}

@Override
public void beforePhase(PhaseEvent event) {
FacesContext context = event.getFacesContext();
ExternalContext ext = context.getExternalContext();
HttpSession session = (HttpSession) ext.getSession(false);
boolean newSession = (session == null) || (session.isNew());
boolean postback = !ext.getRequestParameterMap().isEmpty();
boolean timedout = postback && newSession;
if (timedout) {
Application app = context.getApplication();
ViewHandler viewHandler = app.getViewHandler();
UIViewRoot view = viewHandler.createView(context, "/" + homepage);
context.setViewRoot(view);
context.renderResponse();
try {
viewHandler.renderView(context, view);
context.responseComplete();
} catch (Throwable t) {
throw new FacesException("Session timed out", t);
}
}
}

@Override
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
}

Once you created the class above that implements the PhaseListener, add this to you faces-config.xml. Note that the package name depends on your own Java packaging.
<lifecycle>
<phase-listener>com.mypackage.web.session.SessionPhaseListener</phase-listener>
</lifecycle>

How to Handle ViewExpiredException in JSF

Here's the solution on how to handle the ViewExpiredException in JSF. This occurs when your session timed out or you tried to invalidate the session when you logged out. I've used this code to my 2 previous projects and it really worked fine.

First, you just need to add Spring 2.5 to your project libraries. Download Spring 2.5 here and just copy the code below.

import javax.faces.application.ViewExpiredException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.util.StringUtils;

public class SessionTimeoutFilter implements Filter {

private String homePage = "index.jsp";

@Override
public void init(FilterConfig filter) throws ServletException {
//Filter initialized
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException {
if ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse)) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
if (isSessionCheckingNeeded(httpServletRequest)) {
if ((isInvalidSession(httpServletRequest))) {
String timeoutUrl = httpServletRequest.getContextPath() + "/faces/" + getHomePage();
httpServletResponse.sendRedirect(timeoutUrl);
return;
}
}
}

try {
chain.doFilter(request, response);
} catch (ViewExpiredException ve) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;

String timeoutUrl = httpServletRequest.getContextPath() + "/faces/" + getHomePage();
httpServletResponse.sendRedirect(timeoutUrl);

} catch (Exception e) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;

String timeoutUrl = httpServletRequest.getContextPath() + "/faces/" + getHomePage();

if (StringUtils.countOccurrencesOf(e.getMessage(), "could not be restored.") > 0) {
httpServletResponse.sendRedirect(timeoutUrl);
return;
}

httpServletResponse.sendRedirect(timeoutUrl);
return;
}
}

private boolean isInvalidSession(HttpServletRequest httpServletRequest) {

boolean sessionInValid = (httpServletRequest.getRequestedSessionId() != null)
&& !httpServletRequest.isRequestedSessionIdValid();
return sessionInValid;
}

private boolean isSessionCheckingNeeded(HttpServletRequest request) {

int counter = StringUtils.countOccurrencesOf(request.getRequestURL().toString(), getHomePage())
+ StringUtils.countOccurrencesOf(request.getRequestURL().toString(), getHomePage());

if (counter > 0) {
return false;
}
return true;
}

@Override
public void destroy() {
//Session destroyed
}

public String getHomePage() {
return homePage;
}

public void setHomePage(String homePage) {
this.homePage = homePage;
}
}