Tuesday 15 April 2014

Exception Handling and AJAX in a Java Servlet Container

The Servlet Spec provides a simple way to implement error pages for different types of exceptions that might be thrown by your application with the <error-page> element in your web.xml. However, just like container managed security, you need to make some small changes if you want to handle AJAX requests differently.

Once again this technique relies on your being able to differentiate AJAX requests from full page requests. In my app I have taken a conscious decision to make sure that any requests that are made asynchronously use a URL containing '/ajax/'. This simplifies life quite a lot, but if you don't want to do this you could use a query parameter such as ?ajax=true on all AJAX requests.

The simplest use-case is that you want to catch all exceptions thrown at runtime and forward the user to an error page if they are making a normal http request, and return a small snippet of error message if they are making use of some asynchronous functionality.

In this case you can put this in your web.xml:

  <error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/error</location>
  </error-page>


Then to handle the errors you would create a small servlet like this:

@WebServlet("/error")
public class ErrorServlet extends HttpServlet {
 @Override
 public void service(
  HttpServletRequest request, 
  HttpServletResponse response
 )throws ServletException {
  String uri = (String) request
    .getAttribute(
      RequestDispatcher.ERROR_REQUEST_URI
    );
  if (uri != null && uri.contains("/ajax/")) {
   response.setStatus(
    HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
   request.getServletContext()
    .getRequestDispatcher("/error.jsp")
    .forward(request, response);
  } else {
   request.getServletContext()
    .getRequestDispatcher("/error-page.jsp")
    .forward(request, response);
  }
 }

}

In a nutshell this code will forward to a jsp called error-page.jsp if the request is a normal http request. In the case of an AJAX request it returns an HTTP status code 500 and forwards to a different jsp that generates snippet of html with the error message, in case the JavaScript on the client wishes to display a message.

Of course you may want to handle different types of errors differently, which can be done using the configuration in web.xml to specify another Servlet. I handle validation errors from forms submitted via AJAX separately but in a similar way to this, putting the name of the fields and the messages in an object to be serialised to JSON, allowing the client to handle highlighting error fields and displaying messages.


No comments:

Post a Comment