What is the difference between @RestControllerAdvice and @ControllerAdvice?
Both `@ControllerAdvice` and `@RestControllerAdvice` are Spring annotations used for global handling of exceptions, model attributes, and data binding across multiple controllers. They allow you to centralize cross-cutting concerns for controllers, providing a mechanism similar to Aspect-Oriented Programming (AOP). The primary difference lies in how they handle method return types, particularly in the context of RESTful services.
@ControllerAdvice
@ControllerAdvice is a specialization of @Component that allows you to apply advice (like @ExceptionHandler, @InitBinder, or @ModelAttribute) to controllers globally. When used with @ExceptionHandler methods, it allows you to define how exceptions should be handled across all or a subset of controllers. By default, methods within a @ControllerAdvice class behave like regular controller methods, meaning they can return ModelAndView objects or view names.
It does *not* implicitly add @ResponseBody to its methods. If you want an @ExceptionHandler method in @ControllerAdvice to return a JSON/XML response, you must explicitly annotate that method with @ResponseBody.
@ControllerAdvice
public class MyControllerAdvice {
@ExceptionHandler(ResourceNotFoundException.class)
public ModelAndView handleResourceNotFoundException(ResourceNotFoundException ex) {
ModelAndView mav = new ModelAndView("error-page");
mav.addObject("message", ex.getMessage());
mav.addObject("status", HttpStatus.NOT_FOUND.value());
return mav;
}
@ExceptionHandler(IllegalArgumentException.class)
@ResponseBody // Must be explicit for JSON/XML response
public ErrorResponse handleIllegalArgumentException(IllegalArgumentException ex) {
return new ErrorResponse(HttpStatus.BAD_REQUEST.value(), ex.getMessage());
}
}
@RestControllerAdvice
@RestControllerAdvice is a convenience annotation that combines @ControllerAdvice and @ResponseBody. It is specifically designed for RESTful web services. When you annotate a class with @RestControllerAdvice, all @ExceptionHandler methods (and other handler methods) within that class automatically inherit the behavior of @ResponseBody.
This means that any value returned by methods in a @RestControllerAdvice class (e.g., from an @ExceptionHandler) will be automatically serialized into the HTTP response body (typically JSON or XML, depending on the client's Accept header and available converters), without needing to explicitly add @ResponseBody to each method.
@RestControllerAdvice
public class MyRestControllerAdvice {
@ExceptionHandler(ResourceNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public ErrorResponse handleResourceNotFoundException(ResourceNotFoundException ex) {
// @ResponseBody is implicitly applied here
return new ErrorResponse(HttpStatus.NOT_FOUND.value(), ex.getMessage());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, String> handleValidationExceptions(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getAllErrors().forEach((error) -> {
String fieldName = ((FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage);
});
return errors;
}
}
Key Differences Summarized
- Implicit
@ResponseBody:@RestControllerAdviceimplicitly includes@ResponseBodyfor all its handler methods, while@ControllerAdvicedoes not. Methods in@ControllerAdviceneed@ResponseBodyexplicitly if they are to return data directly into the HTTP response body. - Intended Use Case:
@ControllerAdviceis more general and can be used for both traditional MVC applications (returning views) and REST applications (when@ResponseBodyis added).@RestControllerAdviceis specifically tailored for RESTful web services, assuming that all responses will be data (JSON/XML). - Return Type Handling:
@ControllerAdvicemethods typically returnModelAndVieworString(view name) by default, or an object if@ResponseBodyis present.@RestControllerAdvicemethods typically return objects that get serialized into JSON/XML responses.
When to Use Which
- Use
@ControllerAdvice: In traditional Spring MVC applications where you primarily return view names orModelAndViewobjects from your controllers and global exception handlers. You might also use it in a mixed application where some controllers return views and others (annotated with@ResponseBodyor@RestController) return data, and you want a single advice class for all. - Use
@RestControllerAdvice: In Spring RESTful web services (APIs) where all your controllers are@RestControllers, and you consistently return data (JSON/XML) rather than views. It simplifies the code by automatically applying@ResponseBody, making your exception handling classes cleaner for REST APIs.
Conclusion
The choice between @ControllerAdvice and @RestControllerAdvice primarily depends on the nature of your application. For pure REST APIs, @RestControllerAdvice is the more convenient and idiomatic choice as it aligns with the expectation of returning data directly. For traditional MVC applications or mixed environments, @ControllerAdvice offers more flexibility, though it requires explicit @ResponseBody for data-returning methods.