Introduction
JSF 2 javax.faces.application.ViewExpiredException
that arises due to the click on a link or button when session gets expired. This tutorial will show you how we can deal with ViewExpiredException
or view expired exception and we will show a meaningful message to the user with a link which will take him/her to the appropriate page instead of showing such technical message.
The resolution for ViewExpiredException
has been taken from https://weblogs.java.net/blog/edburns/archive/2009/09/03/dealing-gracefully-viewexpiredexception-jsf2 with a little modification.
JSF throws a ViewExpiredException
when a postback
is made to a view and, for whatever reason, that view cannot be restored. Usually this is due to a session timeout, but a custom state management solution could also cause this exception to be thrown.
So I will show you here how view gets expired, ViewExpiredException
thrown on the view and resolution for this application.
The application is JSF based Login application. This application just allows user to login and takes user to the home page after successful login.
We set the maximum interval time for a client for interacting with the session and after maximum interval time period the session gets expired. Hence we get the javax.faces.application.ViewExpiredException
on the view when we try to do something from the view.
Final Results
Login page
Login page is shown on context path access by using URL http://localhost:8080/jsf2-view-expired-exception/home.jsf.

Home Page
When user successfully logs in to the application by using credentials soumitra/soumitra.

On ViewExpiredException

On Resolution to ViewExpiredException

Let’s look at the source code step by step and try to understand how it happens.
Prerequisites
Eclipse Neon, Tomcat 9.0.24, JDK 1.8, JSF 2.2.4
Creating Project
Create a maven based web project with the following details:
Group Id: com.roytuts
Artifact Id: jsf2-view-expired-exception
Updating Build File
The default generated build file – pom.xml – does not include required dependencies, so we will update to include the required dependencies.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.roytuts</groupId>
<artifactId>jsf2-view-expired-exception</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<build>
<finalName>jsf2-view-expired-exception</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Updating Deployment Descriptor
We will update deployment descriptor file – web.xml – to configure our JSF 2 application.
We configure project stage to make sure it’s in development mode.
Our central Servlet class is FacesServlet
that handles requests and responses for clients.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>JSF 2 ViewExpiredException Resolution</display-name>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsf</welcome-file>
</welcome-file-list>
</web-app>
In the above web.xml file I will tell you a brief regarding the tags.
The following tag says that we are using development environment.
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
We need to tell the application that we are using Java Server Faces
.
All client requests/responses will pass through this central servlet – FacesServlet
.
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
We need to mention the URL pattern for handling the client requests/responses coming from a URL.
We can give other values like *.faces
, *.xhtml
, etc.
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
The below tag tells which page to show when applications starts up. The suffix after .
must be same as <url-pattern/>
.
<welcome-file-list>
<welcome-file>index.jsf</welcome-file>
</welcome-file-list>
Creating Managed Bean
We will create a JSF managed bean LoginMBean.java in Login application for login and logout operation.
Find the description for each line with the comment.
package com.roytuts.jsf2.viewexpiredexception.mbean;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;
@ManagedBean
@RequestScoped
public class LoginMBean {
// success or error message to be shown on the view
private String message;
// username
private String username;
// password
private String password;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
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;
}
// login action
public String doLogin() {
// check username is empty
if (username == null || username.trim().length() <= 0) {
setMessage("<span style=\"color:red;\">Username is required field</span>");
return null;
}
// check password is empty
if (password == null || password.length() <= 0) {
setMessage("<span style=\"color:red;\">Password is required field</span>");
return null;
}
// authenticate with username and password
if (!"soumitra".equalsIgnoreCase(username.trim()) && !"soumitra".equalsIgnoreCase(password)) {
// set error message if different credentials found. set color:red for error
// message
setMessage("<span style=\"color:red;\">Try with username: soumitra and password: soumitra</span>");
return null;
}
// get non-transacted session from facescontext
HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
// set maximum interval time period for client interacting with session. can be
// set in web.xml also
session.setMaxInactiveInterval(5);// in seconds
// put the username in session variable
session.setAttribute("username", username);
// redirect to home page after login. faces-redirect=true for completely
// redirecting to the new url
return "home.jsf?faces-redirect=true";
}
// logout action
public String doLogout() {
// invalidate the session along with all session variables for the facescontext
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
// redirect to login page
return "index.jsf?faces-redirect=true";
}
}
Creating View FIles
We need to create two views for this purpose, one is a login page and another is home page to be shown upon successful login.
Login Page – index.xhtml
The below page is used for login form where user will input credentials to login to the application.
<?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://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>JSF 2 - view expired exception solution</title>
</h:head>
<h:body>
<h2>Please login here</h2>
<p>
<!-- show success/error message. escape="false" for outputting the html as html in the view otherwise it will not parse the html tags -->
<h:outputText value="#{loginMBean.message}"
rendered="#{!empty loginMBean.message}" escape="false"/>
<h:form prependId="false">
<h:panelGrid>
<!-- username label -->
<h:outputLabel>Username:</h:outputLabel>
<!-- username input binding to backing bean property -->
<h:inputText value="#{loginMBean.username}"></h:inputText>
<!-- password label -->
<h:outputLabel>Password:</h:outputLabel>
<!-- password input binding to backing bean property -->
<h:inputSecret value="#{loginMBean.password}"></h:inputSecret>
<!-- login action binding to backing bean action method -->
<h:commandButton action="#{loginMBean.doLogin()}" value="Login" />
</h:panelGrid>
</h:form>
</p>
</h:body>
</html>
Home Page – home.xhtml
This page is shown upon successful login using the login page.
<?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://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>JSF 2 - view expired exception solution</title>
</h:head>
<h:body>
<h2>
<!-- show this message upon successful login -->
<span style="color: green;">You have successfully logged in</span>. <span
style="color: blue;">Welcome to your private area</span>
</h2>
<p>
<h:form prependId="false" rendered="#{!empty sessionScope.username}">
<!-- show this message upon successful login. #{sessionScope.username} - access session variable in view -->
<h:outputText
value="Welcome <span style='color:green;'>#{sessionScope.username}</span>"
escape="false" />
<!-- show this logout link upon successful login -->
<h:commandLink action="#{loginMBean.doLogout()}">Logout</h:commandLink>
</h:form>
</p>
</h:body>
</html>
Testing the Application
Now run the application into Tomcat server and try to login with username–soumitra and password–soumitra.
After 5 seconds try to clink on Logout link then you will get ViewExpiredException
.
So what happened ? Because session has expired after 5 seconds and we tried to click on the Logout link which exists as long as session lives and hence the session has expired so view cannot be restored.

Now let’s continue to resolve the issue ViewExpiredException
.
Creating Exception Handler Class
We will create a class which extends ViewExpiredExceptionHandler
class which extends class ExceptionHandlerWrapper
.
For more information please go through https://weblogs.java.net/blog/edburns/archive/2009/09/03/dealing-gracefully-viewexpiredexception-jsf2.
package com.roytuts.jsf2.viewexpiredexception.handler;
import java.util.Iterator;
import java.util.Map;
import javax.faces.FacesException;
import javax.faces.application.NavigationHandler;
import javax.faces.application.ViewExpiredException;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.FacesContext;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;
public class ViewExpiredExceptionHandler extends ExceptionHandlerWrapper {
private ExceptionHandler handler;
public ViewExpiredExceptionHandler(ExceptionHandler handler) {
this.handler = handler;
}
@Override
public ExceptionHandler getWrapped() {
return handler;
}
// once we override getWrapped(), we need only override those methods we're
// interested in. In this case, we want to override only handle()
@Override
public void handle() throws FacesException {
// iterate over unhandler exceptions using the iterator returned from
// getUnhandledExceptionQueuedEvents().iterator()
for (Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator(); i.hasNext();) {
// The ExeceptionQueuedEvent is a SystemEvent from which we can get the actual
// ViewExpiredException
ExceptionQueuedEvent queuedEvent = i.next();
ExceptionQueuedEventContext queuedEventContext = (ExceptionQueuedEventContext) queuedEvent.getSource();
Throwable throwable = queuedEventContext.getException();
if (throwable instanceof ViewExpiredException) {
ViewExpiredException viewExpiredException = (ViewExpiredException) throwable;
FacesContext facesContext = FacesContext.getCurrentInstance();
// for ultimately showing a JSF page we want to extract some information from
// the exception and place it in request scope,
// so we can access it via EL in the page
Map<String, Object> map = facesContext.getExternalContext().getRequestMap();
NavigationHandler navigationHandler = facesContext.getApplication().getNavigationHandler();
try {
// we put the current view, where ViewExpiredException occurrs, in
// "currentViewId" variable
map.put("currentViewId", viewExpiredException.getViewId());
// leverage the JSF implicit navigation system and cause the server to navigate
// to the "viewExpired" page
// we will show viewExpired page with meaningful message. the view or page name
// is viewExpired.xhtml
// viewExpired.xhtml is put on the root path as index.xhtml file
navigationHandler.handleNavigation(facesContext, null, "viewExpired");
// render the response
facesContext.renderResponse();
} finally {
// we call remove() on the iterator. This is an important part of the
// ExceptionHandler usage contract.
// If you handle an exception, you have to remove it from the list of unhandled
// exceptions
i.remove();
}
}
}
getWrapped().handle();
}
}
Creating Exception Handler Factory Class
Create another class ViewExpiredExceptionHandlerFactory
which extends class ExceptionHandlerFactory
.
package com.roytuts.jsf2.viewexpiredexception.handler;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerFactory;
public class ViewExpiredExceptionHandlerFactory extends ExceptionHandlerFactory {
private ExceptionHandlerFactory factory;
public ViewExpiredExceptionHandlerFactory(ExceptionHandlerFactory factory) {
this.factory = factory;
}
// This method is called once per request must return a new ExceptionHandler
// instance each time it's called
@Override
public ExceptionHandler getExceptionHandler() {
// call the real ExceptionHandlerFactory and ask it to create the instance,
// which we then wrap in our custom ViewExpiredExceptionHandlerFactory class
ExceptionHandler handler = factory.getExceptionHandler();
handler = new ViewExpiredExceptionHandler(handler);
return handler;
}
}
Creating Faces Config
We create faces-config file with the below content.
Put faces-config.xml file under WEB-INF folder.
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
<factory>
<exception-handler-factory>com.roytuts.jsf2.viewexpiredexception.handler.ViewExpiredExceptionHandlerFactory</exception-handler-factory>
</factory>
</faces-config>
Creating View File
Create viewExpired.xhtml file with the below content. This is the page which will be shown upon ViewExpiredException
with meaningful message.
<?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://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>JSF 2 - view expired exception solution</title>
</h:head>
<h:body>
<h:form prependId="false">
<p>To protect your security, we have taken the liberty of logging
you out.</p>
<p>
<!-- We previously put the view, where ViewExpiredException occurred, in "currentViewId" variable -->
You were on page <span style="color: blue; font-weight: bold;">#{currentViewId}</span>.
</p>
<p>
<!-- Give user a link to go back to the appropriate page when ViewExpired occurrs -->
Please
<h:commandLink action="index.jsf?faces-redirect=true">Click Here</h:commandLink>
to go back to the Login page.
</p>
</h:form>
</h:body>
</html>
Re-testing the Application
Now again run the application in Tomcat server and login to the application and try to click on Logout link after 5 seconds.
Now you will get to see whatever there on viewExpired.xhtml file.

Source Code
Thanks for reading.