Bird
Raised Fist0
Spring Bootframework~15 mins

@ExceptionHandler in controllers in Spring Boot - Deep Dive

Choose your learning style10 modes available
Overview - @ExceptionHandler in controllers
What is it?
@ExceptionHandler is a special annotation in Spring Boot used inside controller classes to catch and handle errors that happen during web requests. Instead of letting errors crash the app or show confusing messages, it lets you define methods that respond with clear, friendly error information. This helps keep your app stable and user-friendly when things go wrong.
Why it matters
Without @ExceptionHandler, every error in your web app might cause a confusing stack trace or a generic error page that users don’t understand. This makes your app look unreliable and hard to use. By using @ExceptionHandler, you can control how errors are shown, making your app more professional and easier to maintain. It also helps developers fix problems faster by giving clear error details.
Where it fits
Before learning @ExceptionHandler, you should understand basic Spring Boot controllers and how they handle web requests. After mastering it, you can explore global error handling with @ControllerAdvice and learn about custom error responses and logging strategies.
Mental Model
Core Idea
@ExceptionHandler catches specific errors in a controller and lets you decide how to respond instead of letting the error crash the app.
Think of it like...
Imagine a restaurant kitchen where a chef notices if a dish is burnt. Instead of serving a bad dish, the chef quickly fixes it or offers a replacement. @ExceptionHandler is like that chef, catching problems and handling them before the customer sees them.
┌─────────────────────────────┐
│       Controller Layer       │
│ ┌─────────────────────────┐ │
│ │  Request Handling Method │ │
│ └────────────┬────────────┘ │
│              │ Throws Error  │
│              ▼              │
│ ┌─────────────────────────┐ │
│ │  @ExceptionHandler Method│ │
│ └─────────────────────────┘ │
└─────────────────────────────┘
Build-Up - 6 Steps
1
FoundationBasic Controller Error Handling
🤔
Concept: Controllers can throw exceptions during request processing, which by default cause server errors.
In Spring Boot, when a controller method runs, it might throw an exception if something goes wrong, like a missing resource or invalid input. Without special handling, this exception causes a default error page or HTTP 500 response.
Result
Users see a generic error page or HTTP 500 status when an exception occurs.
Understanding that exceptions disrupt normal request flow is key to realizing why we need a way to handle them gracefully.
2
FoundationIntroduction to @ExceptionHandler Annotation
🤔
Concept: @ExceptionHandler marks a method to handle specific exceptions thrown in the same controller.
You add @ExceptionHandler above a method in your controller and specify which exception it handles. When that exception happens, Spring calls this method instead of showing a default error. This method can return a custom message, status code, or view.
Result
Exceptions are caught and handled by your custom method, improving user experience.
Knowing that you can catch exceptions locally in a controller helps keep error handling organized and specific.
3
IntermediateHandling Multiple Exception Types
🤔Before reading on: Do you think one @ExceptionHandler method can handle multiple exception types or only one? Commit to your answer.
Concept: A single @ExceptionHandler method can handle multiple exception classes by listing them.
You can specify multiple exception classes in the @ExceptionHandler annotation like @ExceptionHandler({IOException.class, SQLException.class}). This lets one method handle related errors together, reducing code duplication.
Result
Cleaner code with fewer methods handling similar exceptions.
Understanding this reduces boilerplate and helps group error handling logically.
4
IntermediateReturning Custom Responses from Handlers
🤔Before reading on: Will @ExceptionHandler methods always return views, or can they return JSON or other formats? Commit to your answer.
Concept: @ExceptionHandler methods can return any response type supported by Spring MVC, including JSON, views, or ResponseEntity.
You can return a ResponseEntity with a custom HTTP status and body, or a view name for an error page. For REST APIs, returning JSON with error details is common. This flexibility lets you tailor error responses to your app's needs.
Result
Users get meaningful error messages in the format your app expects.
Knowing you control the response format lets you build consistent and user-friendly APIs.
5
AdvancedScope of @ExceptionHandler in Controllers
🤔Before reading on: Does @ExceptionHandler catch exceptions thrown only in its controller or across the whole app? Commit to your answer.
Concept: @ExceptionHandler methods handle exceptions only within their own controller by default.
If an exception happens in another controller, its @ExceptionHandler won't catch it. To handle exceptions globally, you use @ControllerAdvice. This separation helps organize error handling by scope.
Result
Local handlers catch only local errors, global handlers catch app-wide errors.
Understanding scope prevents confusion about why some exceptions aren’t caught by your handler.
6
ExpertException Handler Method Signature Details
🤔Before reading on: Can @ExceptionHandler methods accept parameters like the exception object or request details? Commit to your answer.
Concept: @ExceptionHandler methods can accept parameters such as the exception, WebRequest, HttpServletRequest, or Model to customize handling.
Spring injects useful info into handler methods if you declare parameters like Exception ex, WebRequest request, or HttpServletResponse response. This lets you log details, inspect the request, or modify the response dynamically.
Result
More powerful and context-aware error handling.
Knowing about method parameters unlocks advanced customization and better error diagnostics.
Under the Hood
When a controller method throws an exception, Spring MVC looks for an @ExceptionHandler method in the same controller that matches the exception type. It uses reflection to find the best match and calls that method instead of propagating the error. The handler method’s return value is then processed as a normal controller response.
Why designed this way?
This design keeps error handling close to the controller logic, making it easier to manage related errors. It also allows separation of concerns by letting developers define global handlers separately. Alternatives like try-catch blocks inside methods were more verbose and scattered error handling.
┌───────────────┐
│ Controller    │
│ Method Called │
└───────┬───────┘
        │ Throws Exception
        ▼
┌─────────────────────┐
│ Spring MVC Dispatcher│
│  Finds @ExceptionHandler │
└───────┬─────────────┘
        │ Calls Handler Method
        ▼
┌─────────────────────┐
│ @ExceptionHandler    │
│ Method Executes      │
└─────────────────────┘
        │ Returns Response
        ▼
┌─────────────────────┐
│ Response Sent to User│
└─────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does @ExceptionHandler catch exceptions thrown anywhere in the app or only in its controller? Commit to your answer.
Common Belief:Many think @ExceptionHandler methods catch exceptions globally across the whole application.
Tap to reveal reality
Reality:@ExceptionHandler methods only catch exceptions thrown within their own controller class.
Why it matters:Assuming global coverage leads to missing errors in other controllers and confusion about why some exceptions are not handled.
Quick: Can @ExceptionHandler methods only return views, or can they return JSON or other types? Commit to your answer.
Common Belief:Some believe @ExceptionHandler methods must return view names or HTML pages only.
Tap to reveal reality
Reality:They can return any response type supported by Spring MVC, including JSON, ResponseEntity, or plain text.
Why it matters:Limiting response types restricts API design and user experience, especially for RESTful services.
Quick: Does @ExceptionHandler catch runtime exceptions only, or checked exceptions too? Commit to your answer.
Common Belief:People often think @ExceptionHandler only works with runtime exceptions.
Tap to reveal reality
Reality:It can handle any exception type declared in the annotation, checked or unchecked.
Why it matters:Misunderstanding this can cause developers to miss handling important checked exceptions.
Quick: Is it necessary to annotate every exception handler method with @ResponseBody to return JSON? Commit to your answer.
Common Belief:Some believe @ResponseBody is always needed on @ExceptionHandler methods to return JSON.
Tap to reveal reality
Reality:If the controller or class is annotated with @RestController or @ResponseBody, it's not needed on the handler method.
Why it matters:Unnecessary annotations clutter code and confuse developers about response handling.
Expert Zone
1
Exception handler methods can be overloaded with different exception types, but Spring picks the most specific match, which can cause subtle bugs if not carefully ordered.
2
Using @ExceptionHandler inside @RestControllerAdvice allows combining global and local handlers with priority control, which is often overlooked.
3
Exception handlers can modify HTTP headers and status codes dynamically, enabling fine-grained control over API error contracts beyond simple messages.
When NOT to use
Avoid using @ExceptionHandler for cross-cutting error handling across multiple controllers; instead, use @ControllerAdvice for global handling. Also, for very simple apps, try-catch blocks or default error pages might suffice.
Production Patterns
In production, developers often combine @ExceptionHandler with logging frameworks to record error details, use custom error response objects for consistent API errors, and integrate with monitoring tools. They also separate validation errors from system errors using different handlers.
Connections
Middleware in Express.js
Both handle errors in web request pipelines but in different frameworks and languages.
Understanding @ExceptionHandler helps grasp how web frameworks manage errors locally, similar to middleware error handlers in Node.js.
Try-Catch Blocks in Programming
@ExceptionHandler is like a centralized try-catch for controller methods.
Knowing traditional try-catch helps understand why @ExceptionHandler improves code by separating error handling from business logic.
Customer Service Escalation
Both involve catching problems early and deciding how to respond or escalate.
Seeing error handling as customer service clarifies why catching and responding properly improves user satisfaction and system reliability.
Common Pitfalls
#1Defining @ExceptionHandler method without specifying exception type.
Wrong approach:@ExceptionHandler public String handleError() { return "error"; }
Correct approach:@ExceptionHandler(Exception.class) public String handleError(Exception ex) { return "error"; }
Root cause:Spring needs to know which exceptions to handle; omitting the exception type causes the handler not to be registered properly.
#2Returning a view name from @ExceptionHandler in a REST controller expecting JSON.
Wrong approach:@ExceptionHandler(ResourceNotFoundException.class) public String handleNotFound() { return "errorPage"; }
Correct approach:@ExceptionHandler(ResourceNotFoundException.class) public ResponseEntity> handleNotFound() { Map body = Map.of("error", "Resource not found"); return ResponseEntity.status(HttpStatus.NOT_FOUND).body(body); }
Root cause:Mixing view-based and REST response styles causes clients to get unexpected HTML instead of JSON.
#3Expecting @ExceptionHandler in one controller to catch exceptions from another controller.
Wrong approach:Controller A has @ExceptionHandler for NullPointerException, but exception thrown in Controller B is not caught.
Correct approach:Use @ControllerAdvice with @ExceptionHandler to catch exceptions globally across controllers.
Root cause:Misunderstanding the scope of @ExceptionHandler leads to unhandled exceptions.
Key Takeaways
@ExceptionHandler lets you catch and handle exceptions locally inside a Spring Boot controller, improving error responses.
It supports handling multiple exception types and returning any response format, including JSON and views.
Handlers only catch exceptions thrown within their own controller unless combined with @ControllerAdvice for global handling.
You can customize handler methods with parameters like the exception object and request details for richer error processing.
Understanding the scope and method signatures of @ExceptionHandler prevents common bugs and helps build robust web applications.

Practice

(1/5)
1. What is the main purpose of using @ExceptionHandler in a Spring Boot controller?
easy
A. To catch and handle exceptions thrown in controller methods
B. To define the URL path for a controller method
C. To inject dependencies into the controller
D. To configure database connections

Solution

  1. Step 1: Understand the role of @ExceptionHandler

    @ExceptionHandler is used to catch exceptions that occur in controller methods to prevent the app from crashing.
  2. Step 2: Identify what @ExceptionHandler does in controllers

    It allows sending user-friendly error messages and proper HTTP status codes when exceptions happen.
  3. Final Answer:

    To catch and handle exceptions thrown in controller methods -> Option A
  4. Quick Check:

    @ExceptionHandler catches exceptions [OK]
Hint: Remember: @ExceptionHandler handles errors in controllers [OK]
Common Mistakes:
  • Confusing @ExceptionHandler with URL mapping annotations
  • Thinking it injects dependencies
  • Assuming it configures database settings
2. Which of the following is the correct way to declare an exception handler method in a Spring Boot controller?
easy
A. @RequestMapping(Exception.class) public String handleError() { return "error"; }
B. @GetMapping(Exception.class) public String handleError() { return "error"; }
C. @Autowired(Exception.class) public String handleError() { return "error"; }
D. @ExceptionHandler(Exception.class) public String handleError() { return "error"; }

Solution

  1. Step 1: Identify the correct annotation for exception handling

    @ExceptionHandler is the annotation used to mark methods that handle exceptions.
  2. Step 2: Check the method signature

    The method should be annotated with @ExceptionHandler(Exception.class) and return a response, here a String view name.
  3. Final Answer:

    @ExceptionHandler(Exception.class) public String handleError() { return "error"; } -> Option D
  4. Quick Check:

    @ExceptionHandler syntax [OK]
Hint: Use @ExceptionHandler with exception class to handle errors [OK]
Common Mistakes:
  • Using @RequestMapping or @GetMapping instead of @ExceptionHandler
  • Misusing @Autowired annotation
  • Missing the exception class in @ExceptionHandler
3. Given the following controller code snippet, what will be the HTTP status code returned when a NullPointerException occurs?
@RestController
public class MyController {
  @GetMapping("/test")
  public String test() {
    throw new NullPointerException("Null error");
  }

  @ExceptionHandler(NullPointerException.class)
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  public String handleNullPointer() {
    return "Null pointer error handled";
  }
}
medium
A. 200 OK
B. 400 Bad Request
C. 500 Internal Server Error
D. 404 Not Found

Solution

  1. Step 1: Identify the exception and handler

    The controller throws NullPointerException, which is caught by the method annotated with @ExceptionHandler(NullPointerException.class).
  2. Step 2: Check the response status annotation

    The handler method has @ResponseStatus(HttpStatus.BAD_REQUEST), so it sets the HTTP status to 400.
  3. Final Answer:

    400 Bad Request -> Option B
  4. Quick Check:

    @ResponseStatus sets HTTP code = 400 [OK]
Hint: Look for @ResponseStatus on @ExceptionHandler method [OK]
Common Mistakes:
  • Assuming default 500 error without @ResponseStatus
  • Confusing exception type with HTTP status
  • Ignoring the @ExceptionHandler method
4. Consider this controller code snippet:
@RestController
public class DemoController {
  @GetMapping("/demo")
  public String demo() {
    throw new IllegalArgumentException("Invalid argument");
  }

  @ExceptionHandler(NullPointerException.class)
  public String handleNull() {
    return "Null error";
  }
}

What will happen when the /demo endpoint is called?
medium
A. The exception will be handled by handleNull method
B. The response will be "Null error" with HTTP 200
C. The exception will not be handled and a 500 error is returned
D. The server will return HTTP 404 Not Found

Solution

  1. Step 1: Identify the thrown exception

    The method throws IllegalArgumentException, but the handler only catches NullPointerException.
  2. Step 2: Check if exception is handled

    Since no handler matches IllegalArgumentException, Spring Boot returns a default 500 Internal Server Error.
  3. Final Answer:

    The exception will not be handled and a 500 error is returned -> Option C
  4. Quick Check:

    Handler mismatch causes 500 error [OK]
Hint: Handler must match exception type exactly [OK]
Common Mistakes:
  • Assuming handler catches all exceptions
  • Thinking handler method runs for different exception types
  • Expecting 404 instead of 500 error
5. You want to create a global exception handler in Spring Boot that catches RuntimeException for all controllers and returns a JSON error message with HTTP status 500. Which approach correctly achieves this?
hard
A. Create a class annotated with @ControllerAdvice and define a method with @ExceptionHandler(RuntimeException.class) returning a JSON response and @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR).
B. Add @ExceptionHandler(RuntimeException.class) method inside each controller class returning a view name.
C. Use @RestController on a class with @ExceptionHandler(Exception.class) returning a String message.
D. Configure exception handling in application.properties file.

Solution

  1. Step 1: Understand global exception handling

    @ControllerAdvice allows defining exception handlers that apply to all controllers globally.
  2. Step 2: Define handler method for RuntimeException

    Use @ExceptionHandler(RuntimeException.class) with @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) to set status 500 and return JSON response.
  3. Final Answer:

    Create a class annotated with @ControllerAdvice and define a method with @ExceptionHandler(RuntimeException.class) returning a JSON response and @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR). -> Option A
  4. Quick Check:

    Global handler uses @ControllerAdvice + @ExceptionHandler [OK]
Hint: Use @ControllerAdvice for global exception handling [OK]
Common Mistakes:
  • Putting handlers only inside controllers for global effect
  • Using application.properties for exception handling
  • Not setting proper HTTP status in handler
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard