Gracefully Handling ViewExpiredException

On March 17, 2013, in Java EE 6, JSF, JSF 2.0, by lucasterdev

ViewExpiredException usually occurs whena postback is triggered after the Session has expired. Here are a couple of ways to handle it:

Method #1: just use web.xml

<error-page>
	<exception-type>javax.faces.application.ViewExpiredException</exception-type>
	<location>/ViewExpiredException.xhtml</location>
</error-page>

Method #2: use JSF’s ExceptionHandler mechanism

Create an ExceptionHandlerFactory

package foo;

import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerFactory;

public class MyExceptionHandlerFactory extends ExceptionHandlerFactory {

	private ExceptionHandlerFactory parent;

	// This injection is handled by JSF
	public MyExceptionHandlerFactory(ExceptionHandlerFactory parent) {
		this.parent = parent;
	}

	@Override
	public ExceptionHandler getExceptionHandler() {
		return new MyExceptionHandler(parent.getExceptionHandler());
	}

}

Implement your ExceptionHandler by extending ExceptionHandlerWrapper and overriding the handle() method

package foo;

import java.util.Iterator;
import java.util.logging.Logger;

import javax.faces.application.FacesMessage;
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;

public class MyExceptionHandler extends ExceptionHandlerWrapper {

	private ExceptionHandler wrapped;

	Logger log;
	FacesContext fc;

	public MyExceptionHandler(ExceptionHandler exceptionHandler) {
		wrapped = exceptionHandler;
		log = Logger.getLogger(this.getClass().getName());
		fc = FacesContext.getCurrentInstance();
	}

	@Override
	public ExceptionHandler getWrapped() {
		return wrapped;
	}

	@Override
	public void handle() {

		Iterator<ExceptionQueuedEvent> i = super.getUnhandledExceptionQueuedEvents().iterator();

		while (i.hasNext()) {

			Throwable t = i.next().getContext().getException();

			if (t instanceof ViewExpiredException) {
				try {
					// Handle the exception, for example:
					log.severe("ViewExpiredException occurred!");
					fc.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "An exception occurred",
							"ViewExpiredException happened!"));
					fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "ViewExpiredException");
				}
				finally {
					i.remove();
				}
			}

			/*
			else if (t instanceof SomeOtherException) {
				// handle SomeOtherException
			}
			*/

		}

		// let the parent handle the rest
		getWrapped().handle();
	}

}

Register your ExceptionHandlerFactory in faces-config.xml

<factory>
	<exception-handler-factory>foo.MyExceptionHandlerFactory</exception-handler-factory>
</factory>
Tagged with:  

Leave a Reply