🌱 Spring Boot Q42 / 56

What is the difference between @RestControllerAdvice and @ControllerAdvice?

AI-Powered Answer ✓ Answered

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.

java
@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.

java
@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: @RestControllerAdvice implicitly includes @ResponseBody for all its handler methods, while @ControllerAdvice does not. Methods in @ControllerAdvice need @ResponseBody explicitly if they are to return data directly into the HTTP response body.
  • Intended Use Case: @ControllerAdvice is more general and can be used for both traditional MVC applications (returning views) and REST applications (when @ResponseBody is added). @RestControllerAdvice is specifically tailored for RESTful web services, assuming that all responses will be data (JSON/XML).
  • Return Type Handling: @ControllerAdvice methods typically return ModelAndView or String (view name) by default, or an object if @ResponseBody is present. @RestControllerAdvice methods 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 or ModelAndView objects 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 @ResponseBody or @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.