Session timeout and ViewExpiredException handling on JSF/PrimeFaces ajax request Session timeout and ViewExpiredException handling on JSF/PrimeFaces ajax request ajax ajax

Session timeout and ViewExpiredException handling on JSF/PrimeFaces ajax request


Exceptions which are thrown during ajax requests have by default totally no feedback in the client side. Only when you run Mojarra with project stage set to Development and use <f:ajax>, then you will get a bare JavaScript alert with the exception type and message. But other than that, and in PrimeFaces, there's by default no feedback at all. You can however see the exception in the server log and in the ajax response (in the webbrowser's developer toolset's "Network" section).

You need to implement a custom ExceptionHandler which does basically the following job when there's a ViewExpiredException in the queue:

String errorPageLocation = "/WEB-INF/errorpages/expired.xhtml";context.setViewRoot(context.getApplication().getViewHandler().createView(context, errorPageLocation));context.getPartialViewContext().setRenderAll(true);context.renderResponse();

Alternatively, you could use the JSF utility library OmniFaces. It has a FullAjaxExceptionHandler for exactly this purpose (source code here, showcase demo here).

See also:


A merge between the answer of @BalusC and this post, I solved my problem!

My ExceptionHandlerWrapper:

public class CustomExceptionHandler extends ExceptionHandlerWrapper {    private ExceptionHandler wrapped;    CustomExceptionHandler(ExceptionHandler exception) {        this.wrapped = exception;    }    @Override    public ExceptionHandler getWrapped() {        return wrapped;    }    @Override    public void handle() throws FacesException {        final Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator();        while (i.hasNext()) {            ExceptionQueuedEvent event = i.next();            ExceptionQueuedEventContext context                    = (ExceptionQueuedEventContext) event.getSource();            // get the exception from context            Throwable t = context.getException();            final FacesContext fc = FacesContext.getCurrentInstance();            final Map<String, Object> requestMap = fc.getExternalContext().getRequestMap();            final NavigationHandler nav = fc.getApplication().getNavigationHandler();            //here you do what ever you want with exception            try {                //log error ?                //log.log(Level.SEVERE, "Critical Exception!", t);                if (t instanceof ViewExpiredException) {                    requestMap.put("javax.servlet.error.message", "Session expired, try again!");                    String errorPageLocation = "/erro.xhtml";                    fc.setViewRoot(fc.getApplication().getViewHandler().createView(fc, errorPageLocation));                    fc.getPartialViewContext().setRenderAll(true);                    fc.renderResponse();                } else {                    //redirect error page                    requestMap.put("javax.servlet.error.message", t.getMessage());                    nav.handleNavigation(fc, null, "/erro.xhtml");                }                fc.renderResponse();                // remove the comment below if you want to report the error in a jsf error message                //JsfUtil.addErrorMessage(t.getMessage());            } finally {                //remove it from queue                i.remove();            }        }        //parent hanle        getWrapped().handle();    }}

My ExceptionHandlerFactory:

public class CustomExceptionHandlerFactory extends ExceptionHandlerFactory {    private ExceptionHandlerFactory parent;    // this injection handles jsf    public CustomExceptionHandlerFactory(ExceptionHandlerFactory parent) {        this.parent = parent;    }    @Override    public ExceptionHandler getExceptionHandler() {        ExceptionHandler handler = new CustomExceptionHandler(parent.getExceptionHandler());        return handler;    }}

My faces-config.xml

<?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>            your.package.here.CustomExceptionHandlerFactory        </exception-handler-factory>    </factory></faces-config>


I am using Mojarra 2.1.7 in Production mode with JBoss 7. After the session expires, AJAX calls return an error XML document. You can easily catch this error using the usual onerror handler of f:ajax.

<script type="text/javascript">    function showError(data) {        alert("An error happened");        console.log(data);    }</script><h:commandLink action="...">    <f:ajax execute="..." render="..." onerror="showError"/></h:commandLink>