Search code examples
ajaxjsfprimefacesmyfacesviewexpiredexception

How to handle ViewExpiredException by showing JavaScript alert?


I've read the question Handle ViewExireException/ajax and display a Primefaces dialog and the answer from BalusC. I'd want to handle the ViewExpiredException by showing the alert with information to refresh the page. I've taken the suggestion from BalusC to user RequestContextto put JavaScript to execute, and I've removed the JSF redirection because I'm not using it:

@Override
public void handle() throws FacesException {
    for (Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator(); i.hasNext();) {
        ExceptionQueuedEvent event = i.next();
        ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
        Throwable t = context.getException();
        if (t instanceof ViewExpiredException) {
            ViewExpiredException vee = (ViewExpiredException) t;
            try {
                log.info("Catched ViewExpiredException for view {}", vee.getViewId());
                RequestContext.getCurrentInstance().execute("handleViewExpired("+vee.getViewId()+")");
                return;
            } finally {
                i.remove();
            }
        } 
    }
    // At this point, the queue will not contain any ViewExpiredEvents.
    // Therefore, let the parent handle them.
    getWrapped().handle();

}

The problem is, I got NullPointerException when executing the handle method from wrapped handler. I've added the return clause, and after adding it, the effect was the same:

[30.01.13 15:45:59:140 CET] 0000002e ErrorPageWrit E An exception occurred javax.faces.FacesException: java.lang.NullPointerException at org.apache.myfaces.shared_impl.context.ExceptionHandlerImpl.wrap(ExceptionHandlerImpl.java:241) at org.apache.myfaces.shared_impl.context.ExceptionHandlerImpl.handle(ExceptionHandlerImpl.java:156) at my.project.web.handler.ViewExpiredExceptionExceptionHandler.handle(ViewExpiredExceptionExceptionHandler.java:59) at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:191) at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)

So, the parent handle method is executed, thought there should be the return from method (The info string is logged).

I'm using PrimeFaces 3.4 and MyFaces 2.0.7, everything on WebSphere 7.

I don't understand what is happening here. Is it possible to achieve what I want, and if so, what I'm doing wrong?


Solution

  • The best way was to handle that exception on client side. It's very simple few-liner and it's completly transparent:

    var originalPrimeFacesAjaxResponseFunction = PrimeFaces.ajax.AjaxResponse;
    PrimeFaces.ajax.AjaxResponse = function(data, status, xhr) {
      var errorName = $(data.documentElement).find("error-name").text();
      if (errorName == 'javax.faces.application.ViewExpiredException') {
        alert('View has expired, redirection will follow');
        window.location.reload();
      } else {
        originalPrimeFacesAjaxResponseFunction.apply(this, arguments);
      }
    };
    

    No 2 new classes on server, no faces-config.xml changes, this is what I love in programming.