Search code examples
jsfomnifacesdynatrace

Exception handling for Ajax requests in JSF using Omnifaces : always showing Status Code 200 instead of 500


we are currently adding a monitoring solution (Dynatrace) to our JSF web application. The monitoring solution checks for status codes that indicate an error to flag a problem in a user session. We are trying to use Omnifaces FullAjaxExceptionHander (see http://showcase.omnifaces.org/exceptionhandlers/FullAjaxExceptionHandler) to handle Ajax exception and render an error page. As you can see from the screen shot Omnifaces sets an error code of 500 but the status code on the POST shows up as 200 in Chrome. As Dynatrace doesn't see an error status code it does not flag this on the user session.

Any idea why the status code is not set on the response? I thought I saw it briefly come up with a status code of 500 on the POST in our system but now it is only showing 200 again. That's when I tried the example from the Omnifaces showcase and there I am only getting the 200 has well.

Screenshot of Omnifaces Showcase and status code received by browser


Solution

  • It's because it's technically a successful Ajax response. I.e. it has successfully delivered the error page content as part of <partial-response> in the Ajax response XML body.

    If the Ajax response would have status 500, then JSF wouldn't have parsed the Ajax response XML at all, but instead invoked the onerror handler which in turn fires any registered custom client side code. This is where things get complicated as it by default doesn't render anything while the FullAjaxExceptionHandler really wants to utilize the existing JSF Ajax rendering logic.

    Your best bet is to check if your monitoring service offers a Java based API to manually notify the error condition. And if so, then override one of the FullAjaxExceptionHandler methods to ping it. The shouldHandleExceptionRootCause() is a good candidate. There you can if necessary also perform an instanceof check on the exception to skip certain ones.

    I'm not familiar with Dynatrace, but in case you're using NewRelic, this is how it would look like:

    import com.newrelic.api.agent.NewRelic;
    
    public class CustomExceptionHandler extends FullAjaxExceptionHandler {
    
        @Override
        protected boolean shouldHandleExceptionRootCause(FacesContext context, Throwable exception) {
            try {
                NewRelic.noticeError(exception);
            }
            catch (Exception e) {
                // Log a WARN line
            }
    
            return true;
        }
    }
    

    Finally create a custom ExceptionHandlerFactory for it and replace the FullAjaxExceptionHandlerFactory in faces-config.xml with it.