Spring Exception Handling

The spring framework uses HandlerExceptionResolver interface to handle exception. Exception handling with AOP can eliminate duplicate code exception handling, reducing lines of code for exception handling and better code maintenance. Exception handling increases the flexibility of unified design. We can easily apply different exception handling with a few lines of code and configuration changes. You can refractor the aspect of exception handling to provide more complete debugging information, such as serialized objects method argument that throws the exception!

Exception Hierarchy

Spring provides practical translation technology specific exceptions like SQLException to its own exception class hierarchy with the DataAccessException as the root exception. These exceptions wrap the original exception so there is never any risk that you may lose all information about what might have gone wrong. In addition to JDBC exceptions, spring can also wrap Hibernate-specific exceptions, converting the property, checked exceptions (in the case of previous versions of Hibernate Hibernate 3.0), a set of runtime exceptions centered (the same is true for JDO and JPA exceptions).

This allows handling most persistence exceptions, which are not recoverable, only in the appropriate layers, without annoying boilerplate, catch and throw blocks and exception declarations of DAOs.  The various template classes in springs support for various ORM frameworks. If one uses the interceptor base classes, then the application should be concerned with the management and JDOExceptions HibernateExceptions itself, preferably through the delegation of convertHibernateAccessException SessionFactoryUtils’ (..) or convertJdoAccessException methods respectively.

These methods convert the exceptions that are compatible with the exceptions in the exception hierarchy org.springframework.dao. As JDOExceptions unchecked, can simply be removed too, sacrificing generic DAO abstraction in terms of exceptions though.

Spring Exception Heirarchy
Spring Exception Heirarchy

There are different exception resolver for avoiding the use of HandlerExceptionResolver interface.

They are,

1)      SimpleMappingExceptionResolver.

2)      DefaultHandlerExceptionResolver.

3)      ResponseStatusExceptionResolver.

4)      AnnotationMethodHandlerExceptionResolver.

SimpleMappingExceptionResolver

This resolver should be configured in XML. The properties of this resolver are,

  • defaultErrorView: – If no mapping will be found then this view will be returned.
  • defaultStatusCode: – If the view hasn’t status code the defaultStatusCode will be applied once the view name was resolved.
  • statusCodes: – Map with “view name” to “status code” mapping.
  • ExceptionAttribute:- The name of attributes where exception is hold by default “exception” is used.
  • ExceptionMappings: – This is mapping concept which maps Exception “class name” to “view name”.

DefaultHandlerExceptionResolver

It has a pageNotFound logger which isorg.springframework.web.servlet.PageNotFound logger. It decides what to do depending on execution type; it is base class to extend when we want change default behavior:

  1. NoSuchRequestHandlingException: – No request handler method was found by default it sends 404 error.  404 errors is “Page not found error” or “Clueless”. It overrides handleNoSuchRequestHandlingMethod.
  2. HttpRequestMethodNotSupportedException: – No request handler method was found for the particular HTTP request method by default 405 error. 405 errors is “Method not allowed”. It overrides handleHttpRequestMethodNotSupported.
  3. HttpMediaTypeNotSupportedException: – No such HttpMessageConverter were found for the PUT or POSTed content by default 415 error. 415 errors is “Unsupported media type”. It overrides handleHttpMediaTypeNotSupported.
  4. HttpMediaTypeNotAcceptableException:- No HttpMessageConverter were found that were acceptable for the client Or accept header by default 406 error. 406 errors is “Not acceptable type”.It overrides handleHttpMediaTypeNotAcceptable.
  5. MissingServletRequestParameterException:-Required parameter is missing by default 400 error. 400 error is “Bad request type”. It overrides handleMissingServletRequestParameter.
  6. ConversionNotSupportedException :-WebDataBinder conversion cannot occur by default 500 error. 500 error is “Internal server error”. It overrides handleConversionNotSupported.
  7. TypeMismatchException :-WebDataBinder conversion error occurs by default 400. It overrides handleTypeMismatch.
  8. HttpMessageNotReadableException :-HttpMessageConverter cannot read from HTTP request by default 400 error. It overrides handleHttpMessageNotReadable.
  9. HttpMessageNotWritableException :-HttpMessageConverter cannot write to HTTP response by default 500 error. It overrides handleHttpMessageNotWritable.

ResponseStatusExceptionResolver

This resolver helps to use @ResponseStatus annotation. Once we annotate our Exception with @ResponseStatus annotation than the response will get status code from annotation.

  • ResponseStatus.value as status code (it is HttpStatus enum)
  • ResponseStatus.reason as reason or default HttpResponse reason if not set

Eg: – @ResponseStatus

@Target(value={TYPE,METHOD})

@Retention(value=RUNTIME)

@Documented

public @interface ResponseStatus

AnnotationMethodHandlerExceptionResolver

This exception resolver helps us to use @ExceptionHandler annotation, every method annotated by @ExceptionHandler will become exception handler. As parameters @ExceptionHandler need an array of Throwable and we also use @ResponseStatus to indicate status code.  The method signatures possibilities are vary so see documentation to get all the proper combinations of parameters and return types. The idea is pretty simple, for all the ExceptionHandler.value exception the exception -> Method handler is created, when Exception happens Method will be invoked.

Eg: – @ExceptionHandler

@Target(value=METHOD)

@Retention(value=RUNTIME)

@Documented

public @interface ExceptionHandler

Eg: – Example of null pointer exception

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class GeneralHandler {
private final Log logger = LogFactory.getLog(getClass());
@ExceptionHandler(NoSuchRequestHandlingMethodException.class)
public ModelAndView handleException (NoSuchRequestHandlingMethodException ex) {
ModelAndView mav = new ModelAndView();
logger.error("Exception found: " + ex);
return mav;
}
}