I always wondered why my application tends to hide exceptions. An exception occurs on the server side without getting visible on the client side. The client doesn’t show any reaction at all. Often you need a tool like FireBug to become aware there’s an error.
It took me a while to realize this only happens with AJAX requests, and that this is a well-known behavior in the JSF community. However, there’s at least one excellent book (also available at jsfatwork.irian.at) which doesn’t mention the problem. So maybe it’s worth spending a couple of minutes to write a small article on an old topic.
When an AJAX request runs on an error typically an error message is returned to the client. Unfortunately, JSF AJAX clients aren’t prepared to deal with arbitrary error messages, so they simply ignore them.
The standard approach to display errors
They can afford to do so because there’s a dedicated mechanism to show error messages in the servlet API. With servlets and JSP pages it suffices to register an error page in the
<error-page> <error-code>500</error-code> <location>/error.jsp</location> </error-page>
This also work with non-AJAX JSF views. However, there’s a better, more flexible alternative that also works with AXAX views.
To show an error message you have to configure an
ExceptionHandler. In general, the best way to do so is to use Omnifaces. Instead add a line to the
<factory> <exception-handler-factory> org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory </exception-handler-factory> </factory>
The behavior of the OmniFaces Exception handler is configured in the
<error-page> <exception-type> java.lang.NullPointerException </exception-type> <location>/npe.jsf</location> </error-page> <error-page> <exception-type> java.lang.Throwable </exception-type> <location>/error.jsf</location> </error-page>
Note that the error pages have to be JSF 2.0 pages. JSF or HTML won’t do.
That’s all you have to know. There’s only little additional information at the Omniface showcase. It’s just that simple.
Unless you’re writing portlets. Omnifaces isn’t compatible with portlets. So you have to implement the
ExceptionHandler and the
ExceptionHandlerFactory yourself. The Omnifaces classes may be a good starting point. Other good starting points might be the exception handlers of Olek Varaksin or JSF Spec leader Ed Burns.
Sneak preview: PrimeFaces 5
The upcoming version 5 of PrimeFaces is going to offer a nice alternative. Thomas Andraschko’s implementation follows a per-page approach: there’s a dedicated tag, <p:exceptionHandler> giving you fine-grained control over exception handling. On the first glance having to declare the exception handler on every individual page looks like a disadvantage. But then, you can simply move the exception handler tag to a template. Most people are using templates anyways, so for the majority of developers, Thomas’s approach is just as simple as the OmniFaces approach while being much more flexible and powerful.
If you want to have a look at the exception handler and don’t want to wait until mid-spring 2014 (the announced release date of PrimeFaces 5) you’ll have to build a developer version of PrimeFaces 5 from source.