Unravel › Java concepts › APIs and web
Central error handling and ProblemDetail
Instead of try/catch in every controller, one advice class maps each exception type to an HTTP status and a consistent error body, so clients always get the same shape of error.
Learn these first
At a glance
A hospital triage desk.
- 1@RestControllerAdvice marks a class that applies to all controllersInside, @ExceptionHandler(OrderNotFoundException.class) methods receive the exception and return the response.
- 2Return a ResponseEntity or use @ResponseStatus(HttpStatus.NOT_FOUND) to set the statusProblemDetail (RFC 9457) is the standard JSON error format: type, title, status, detail.
- 3ResponseStatusException lets code throw an error with a status inline, handy for small cases, but a domain exception plus an advice class keeps services free of HTTP words
- 4Extend ResponseEntityExceptionHandler to also customise the built-in errors (malformed JSON, missing parameter, validation failures) in the same format
- Specific handlers win over general ones, so keep a final @ExceptionHandler(Exception.class) that logs the stack trace and returns a generic 500 without leaking internals to the client
- Log once, in the advice, not in every layer
- When a handler method throws, DispatcherServlet asks its HandlerExceptionResolver chain
@RestControllerAdvicepublic class ApiErrors { @ExceptionHandler(OrderNotFoundException.class) public ProblemDetail notFound(OrderNotFoundException e) { ProblemDetail p = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage()); p.setTitle("Order not found"); return p; }}- line 1 uses RestControllerAdvice, the core of Central error handling and ProblemDetail
- line 3 uses ExceptionHandler, the core of Central error handling and ProblemDetail
- line 4 uses ProblemDetail, the core of Central error handling and ProblemDetail
- line 5 uses ProblemDetail, the core of Central error handling and ProblemDetail
Read the full explanation (about 1 min)
Instead of try/catch in every controller, one advice class maps each exception type to an HTTP status and a consistent error body, so clients always get the same shape of error.
A mental model
A hospital triage desk. Wherever the patient arrives from, the desk decides the urgency label (404, 409, 500) and writes the same form every time.
How it works
@RestControllerAdvice marks a class that applies to all controllers. Inside, @ExceptionHandler(OrderNotFoundException.class) methods receive the exception and return the response.
Return a ResponseEntity or use @ResponseStatus(HttpStatus.NOT_FOUND) to set the status. ProblemDetail (RFC 9457) is the standard JSON error format: type, title, status, detail.
ResponseStatusException lets code throw an error with a status inline, handy for small cases, but a domain exception plus an advice class keeps services free of HTTP words.
Extend ResponseEntityExceptionHandler to also customise the built-in errors (malformed JSON, missing parameter, validation failures) in the same format.
Going deeper
Specific handlers win over general ones, so keep a final @ExceptionHandler(Exception.class) that logs the stack trace and returns a generic 500 without leaking internals to the client.
Log once, in the advice, not in every layer. Logging and rethrowing at each level makes one failure appear ten times.
Never put exception messages from the database or security layers directly in the response; they reveal table names and rules to attackers.
Under the hood
When a handler method throws, DispatcherServlet asks its HandlerExceptionResolver chain. ExceptionHandlerExceptionResolver finds the best-matching @ExceptionHandler first in the controller itself, then in advice beans ordered by @Order.
Common mistakes
- Returning the raw exception message to the client.
- Catching
Exceptionin a controller and returning 200 with an error text. - Handlers that return the wrong status so clients retry non-retryable errors.
- Logging the same stack trace at several layers.
How Unravel recognises it
When you paste code, Unravel looks for these signs of central error handling and problemdetail. Spotting them yourself is a good habit when you read unfamiliar code:
- Annotations:
@ControllerAdvice@RestControllerAdvice@ExceptionHandler - Types:
ProblemDetailResponseStatusExceptionResponseEntityExceptionHandlerErrorResponseHandlerExceptionResolverErrorControllerErrorAttributes
Part of a learning path
- Inside Spring Boot · previous: Servlets, filters and interceptors · next: Spring Boot Actuator and health checks
Related concepts
Frequently asked questions
What is Central error handling and ProblemDetail?
Instead of try/catch in every controller, one advice class maps each exception type to an HTTP status and a consistent error body, so clients always get the same shape of error.
What are the most common mistakes with Central error handling and ProblemDetail?
Returning the raw exception message to the client. Catching Exception in a controller and returning 200 with an error text. Handlers that return the wrong status so clients retry non-retryable errors. Logging the same stack trace at several layers.
How can I see Central error handling and ProblemDetail in real code?
Paste your own Java into Unravel and it will point out where central error handling and problemdetail appears, explain how it works at the detail level you choose, and draw the flow of the code around it.