Spring MVC @ControllerAdvice Annotation Example
October 11, 2023
Spring @ControllerAdvice
annotation is a specialization of @Component
. The classes annotated with @ControllerAdvice
are auto detected by classpath scanning. The use of @ControllerAdvice
is advising all or selected controllers for @ExceptionHandler
, @InitBinder
and @ModelAttribute
annotations. What we have to do is, create a class annotated with @ControllerAdvice
and create a method which will be annotated with @ExceptionHandler
for global exception handling, @InitBinder
for global init binding and @ModelAttribute
for global model attributes addition. Whenever a request hits the controller for any @RequestMapping
and if there is no locally defined exception handler, the globally defined class annotated with @ControllerAdvice
is served.
@ControllerAdvice
has attributes as annotations, assignableTypes and basePackages . To work with @ControllerAdvice
, we need to use @EnableWebMvc
annotation in our JavaConfig.
Using @ControllerAdvice
Find the sample class using@ControllerAdvice
annotation. Here we are declaring methods for @ExceptionHandler
, @InitBinder
and @ModelAttribute
to understand how to use it. We are using basePackages attribute of @ControllerAdvice
to limit the controller classes. This attribute can be assigned with the array of base packages of controllers which can be used by @ControllerAdvice
class, if basePackages attribute is not used, then all controllers in classpath annotated with @Controller
will be served by our @ControllerAdvice
class.
GlobalControllerAdvice.java
@ControllerAdvice(basePackages = {"com.concretepage.controller"} ) public class GlobalControllerAdvice { @InitBinder public void dataBinding(WebDataBinder binder) { SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy"); dateFormat.setLenient(false); binder.registerCustomEditor(Date.class, "dob", new CustomDateEditor(dateFormat, true)); } @ModelAttribute public void globalAttributes(Model model) { model.addAttribute("msg", "Welcome to My World!"); } @ExceptionHandler(FileNotFoundException.class) public ModelAndView myError(Exception exception) { ModelAndView mav = new ModelAndView(); mav.addObject("exception", exception); mav.setViewName("error"); return mav; } }
error.jsp
<html> <head> <title> Global Error </title> </head> <body> <h1>${exception.message}</h1> </body> </html>
Create Controller
Find the controller with a@RequestMapping
method. Here we have also defined a controller specific @InitBinder
method.
MyWorldController.java
@Controller @RequestMapping("/myworld") public class MyWorldController { @Autowired private UserValidator userValidator; @RequestMapping(value="signup", method = RequestMethod.GET) public ModelAndView user(){ return new ModelAndView("user","user",new User()); } @InitBinder public void dataBinding(WebDataBinder binder) { binder.addValidators(userValidator); } @RequestMapping(value="save", method = RequestMethod.POST) public String createUser(@ModelAttribute("user") @Valid User user,BindingResult result, ModelMap model) throws FileNotFoundException { if(result.hasErrors()) { return "user"; } if(user.getName().equals("exception")) { throw new FileNotFoundException("Error found."); } System.out.println("Name:"+ user.getName()); System.out.println("Date of Birth:"+ user.getDob()); return "success"; } }
1. The exception FileNotFoundException thrown in the controller is not being handled locally, so it will be handled by global exception handling class that is annotated by
@ControllerAdvice
.
2. For the date validation, we have no local
WebDataBinder
configuration, it will be handled by global @InitBinder
method.
3.
@ModelAttribute
for "msg" key is not added in the controller locally. So the method annotated with @ModelAttribute
in the GlobalControllerAdvice class is used.