Exception Handling with @ControllerAdvice

@ControllerAdvice centralizes error handling across every controller. With @ExceptionHandler methods returning ResponseEntity error bodies — or a quick ResponseStatusException — your API speaks in clean, consistent status codes.

Learn Exception Handling with @ControllerAdvice in our free Java course — a beginner-friendly interactive lesson with worked examples, a practice exercise…

Part of the free Java course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Before You Start

You should understand Java exceptions and how Spring REST controllers return responses. The validation lesson pairs well with this one.

What You'll Learn

The Big Idea — One Help Desk for the Whole Building

💡 Analogy: Without central handling, every office (controller) keeps its own first-aid kit and gives different answers when something goes wrong. @ControllerAdvice is a single help desk for the whole building: whenever any office raises a problem, it routes to the right specialist ( @ExceptionHandler ) who responds with a consistent, well-formatted answer — the right status code and a tidy error body — every time.

Controllers stay focused on the happy path; the advice handles the unhappy ones.

1️⃣ A Central Exception Handler

Annotate a class with @RestControllerAdvice and add an @ExceptionHandler method per error type. Each returns a ResponseEntity with the right status and a structured body. A catch-all prevents raw stack traces from leaking.

2️⃣ Raising Errors from a Controller

Throw a custom domain exception (handled by the advice) for reusable, meaningful errors, or a ResponseStatusException inline for quick one-offs. Both end up as the correct HTTP status.

3️⃣ How the Right Handler Is Chosen

Spring picks the handler whose exception type best matches what was thrown, falling back to a catch-all. Here is that "match by type" dispatch in plain Java you can run.

🧠 Quick Recall

Answer: the more specific ResourceNotFoundException handler; Exception is the fallback.

Answer: @ResponseBody — return values are serialized as the JSON response body.

🎯 YOUR TURN — Map a 409 Conflict

Add an @ExceptionHandler for a DuplicateEmailException that returns 409 Conflict .

🧩 MINI-CHALLENGE — One handler, two exceptions

Handle both IllegalArgumentException and IllegalStateException with a single handler returning 400.

Common Errors

Pro Tips

📋 Quick Reference

Element

Purpose

Note

@ControllerAdvice

cross-cutting advice

Spans all controllers

@RestControllerAdvice

advice + @ResponseBody

JSON bodies

@ExceptionHandler

map type to handler

Most specific wins

ResponseEntity

status + body

Explicit control

ResponseStatusException

inline status throw

Quick one-offs

400

Bad Request

Invalid input

404

Not Found

Missing resource

409

Conflict

Duplicate/state clash

500

Internal Server Error

Unexpected failure

📚 Resources / Keep Learning

❓ Frequently Asked Questions

🎉 Lesson Complete!

You can now centralize error handling with @ControllerAdvice , map exception types with @ExceptionHandler , return precise ResponseEntity error bodies, throw ResponseStatusException inline, and pick correct HTTP status codes.

Next up: DTOs & Mapping — why you should not expose entities, and how to convert between them cleanly.

Practice quiz

What does a class annotated with @ControllerAdvice provide?

  • Cross-cutting exception handling shared across controllers
  • A new controller endpoint
  • A database connection
  • A scheduled task

Answer: Cross-cutting exception handling shared across controllers. @ControllerAdvice centralizes exception handling (and other advice) across all controllers in one place.

What does @ExceptionHandler(SomeException.class) do?

  • Throws the exception
  • Maps that exception type to a handler method
  • Logs only
  • Disables the exception

Answer: Maps that exception type to a handler method. @ExceptionHandler binds a method to handle the listed exception type(s) when thrown by a controller.

What is the benefit of returning ResponseEntity from a handler?

  • It hides the body
  • It is required by Java
  • It caches the response
  • You control both the HTTP status and the response body

Answer: You control both the HTTP status and the response body. ResponseEntity lets you set the status code, headers, and body explicitly for the error response.

What does throwing a ResponseStatusException(HttpStatus.NOT_FOUND) result in?

  • A 200 response
  • A 404 response with that status
  • A compile error
  • A redirect

Answer: A 404 response with that status. ResponseStatusException maps directly to the given HTTP status, here 404 Not Found.

Which combination makes a @RestController-style advice that returns JSON bodies?

  • @Controller only
  • @ControllerAdvice + @ResponseBody, or @RestControllerAdvice
  • @Service
  • @Component only

Answer: @ControllerAdvice + @ResponseBody, or @RestControllerAdvice. @RestControllerAdvice = @ControllerAdvice + @ResponseBody, so handler return values become JSON bodies.

If two @ExceptionHandler methods could match, which is chosen?

  • A random one
  • The one for the most specific exception type
  • The first declared
  • Both run

Answer: The one for the most specific exception type. Spring picks the handler whose declared exception type is the most specific match for the thrown exception.

What status is conventional for a failed bean validation on a request body?

  • 201 Created
  • 403 Forbidden
  • 400 Bad Request
  • 500 Internal Server Error

Answer: 400 Bad Request. Invalid input is a client error, conventionally returned as 400 Bad Request.

Why centralize error handling in @ControllerAdvice instead of try/catch everywhere?

  • It runs faster
  • It avoids duplicated handling and gives consistent error responses
  • It removes exceptions
  • It is mandatory

Answer: It avoids duplicated handling and gives consistent error responses. Centralizing avoids repeating try/catch in every controller and yields uniform, consistent error responses.

What HTTP status best fits an unexpected server-side failure?

  • 400
  • 404
  • 500 Internal Server Error
  • 204

Answer: 500 Internal Server Error. Unhandled or unexpected server errors map to 500 Internal Server Error.

Can a single @ExceptionHandler handle multiple exception types?

  • No, only one
  • Only via inheritance
  • Only with reflection
  • Yes, by listing several classes in the annotation

Answer: Yes, by listing several classes in the annotation. You can pass an array of exception classes to @ExceptionHandler to handle several types with one method.

Continue this course

Related lessons