In Spring MVC Exceptions can be handled at three levels.
1.Controller Based
We can define exception handler methods in our controller classes. All we need is to annotate these methods with @ExceptionHandler annotation. This annotation takes the Exception class as an argument. So if we have defined one of these for Exception class, then all the exceptions thrown by our request handler method will have handled.
These exception handler methods are just like other request handler methods and we can build error response and respond with a different error page. We can also send a JSON error response, that we will look later on in our example.
@ExceptionHandler({SpringException.class})
.
.
@RequestMapping(value = "/addStudent", method = RequestMethod.POST)
@ExceptionHandler({SpringException.class})
public String addStudent(@ModelAttribute("HelloWeb") Student student, ModelMap model)
{
if (student.getName().length() < 5)
throw new SpringException("Given name is too short");
else
model.addAttribute("name", student.getName());
if (student.getAge() < 10)
throw new SpringException("Given age is too low");
else
model.addAttribute("age", student.getAge());
model.addAttribute("id", student.getId());
return "result";
}
.
.
.
If there are multiple exception handler methods defined, then handler method that is closest to the Exception class is used. For example, if we have two handler methods defined for IOException and Exception and our request handler method throws IOException, then the handler method for IOException will get executed.
2.Global Exception Handler-The handler methods in Global Controller Advice is same as Controller based exception handler methods and used when controller class is not able to handle the exception.@ControllerAdvice is a annotation provided by Spring allowing you to write global code that can be applied to a wide range of controllers, varying from all controllers to a chosen package or even a specific annotation. The annotation could be applied at Package Level, Class Level and at Annotation Level.
Package Level Application
@ControllerAdvice("my.chosen.package")
@ControllerAdvice(value = "my.chosen.package")
@ControllerAdvice(basePackages = "my.chosen.package")
Package Level Application – This will apply across all the classes inside the package where MyClass.class is placed.
@ControllerAdvice(basePackageClasses = MyClass.class)
Controller Level
Controller advice can be limited to certain controllers (not methods) by using one of the values of the @ControllerAdvice annotation, e.g.
@ControllerAdvice(assignableTypes = {MyController1.class, MyController2.class})
Controller identified by Annotation
If you want to apply it to controllers with certain annotations. The below snippet would only assist controllers annotated with @RestController (which it covers by default) but will not include @Controller annotated classes.
@ControllerAdvice(annotations = RestController.class)
3.HandlerExceptionResolver – can be implemented by the application to resolve exceptions thrown during processing an HTTP request. The exception can be thrown by one of the application’s handler methods or outside of it but during processing a request. The method, HandlerExceptionResolver#resolveException(), returns an instance of ModelAndView specifying an error page. The Implementations are typically registered as beans in the application context. The application registered HandlerExceptionResolvers will only be invoked if the exception is not already handled by the default HandlerExceptionResolvers. We can, however, change the order of the resolvers so that a given resolver can be invoked first.
@ExceptionHandler vs HandlerExceptionResolver vs @ControllerAdvice
@ExceptionHandler works at the Controller level and it is only active for that particular Controller, not globally for the entire application.
@ControllerAdvice used for global error handling in the Spring MVC application.It also has full control over the body of the response and the status code.
HandlerExceptionResolver-This will resolve any exception thrown by the application. It is used to resolve standard Spring exceptions to their corresponding HTTP Status Codes. It does not have control over the body of the response, means it does not set anything to the body of the Response.It does map the status code on the response but the body is null.