Exception handling: @ExceptionHandler, @ControllerAdvice,… — Cracked Java
// Spring Framework & Spring Boot · Spring MVC & REST
MidCodingBig Tech

Exception handling: @ExceptionHandler, @ControllerAdvice, ResponseStatusException.

Spring routes any exception thrown by a handler to a HandlerExceptionResolver, and the mechanisms you reach for — @ExceptionHandler, @ControllerAdvice, ResponseStatusException — are progressively broader ways to plug into that. The goal is to translate exceptions into clean HTTP responses without try/catch clutter in your controllers.

@ExceptionHandler — local to a controller

A method annotated @ExceptionHandler(SomeException.class) inside a controller handles exceptions of that type thrown by that controller's methods. It can return a ResponseEntity, a ProblemDetail, or a body with @ResponseStatus.

@ExceptionHandler(OrderNotFoundException.class)
ResponseEntity<String> handle(OrderNotFoundException ex) {
    return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());
}

@ControllerAdvice — global handlers

Move those handlers into a @ControllerAdvice (or @RestControllerAdvice, which adds @ResponseBody) bean and they apply across all controllers. This is the standard place to centralize error mapping.

@RestControllerAdvice
class ApiExceptionHandler {
    @ExceptionHandler(OrderNotFoundException.class)
    ProblemDetail notFound(OrderNotFoundException ex) {
        ProblemDetail pd = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, ex.getMessage());
        pd.setTitle("Order not found");
        return pd;
    }
}

ResponseStatusException — throw status inline

When you don't want a dedicated exception class, throw ResponseStatusException directly with a status and reason — no advice needed:

throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Order " + id + " not found");

ProblemDetail — RFC 7807 (Spring 6)

Spring 6 standardizes error bodies as ProblemDetail (media type application/problem+json) with type, title, status, detail, instance fields plus extensions. Extend ResponseEntityExceptionHandler to get ProblemDetail responses for Spring's built-in exceptions (validation, 404, 405) for free, then override what you need.

@RestControllerAdvice
class GlobalHandler extends ResponseEntityExceptionHandler { /* override hooks */ }

How they compose

A thrown exception is matched first by the most specific @ExceptionHandler in the controller, then by @ControllerAdvice. ResponseStatusException is resolved by ResponseStatusExceptionResolver without any handler. Note @ControllerAdvice only sees exceptions from the handler, not from servlet Filters outside the dispatch.

Mark your status