Spring Boot – Exception Handling (Deep Notes)

 


Spring Boot – Exception Handling (Deep Notes)

1. Core Classes in Spring Exception Handling

From the class diagram on page 1:

HandlerExceptionResolver (interface)
        |
HandlerExceptionResolverComposite
        |
AbstractHandlerExceptionResolver
        |
---------------------------------------------------
|                 |                              |
ExceptionHandlerExceptionResolver   ResponseStatusExceptionResolver   DefaultHandlerExceptionResolver

What each does:

Resolver Responsibility
ExceptionHandlerExceptionResolver Handles @ExceptionHandler & @ControllerAdvice
ResponseStatusExceptionResolver Handles exceptions annotated with @ResponseStatus
DefaultHandlerExceptionResolver Handles Spring framework exceptions like 404, 405

2. Exception Flow (Page 1 Diagram)

When an exception occurs:

  1. DispatcherServlet catches it
  2. Passes it to HandlerExceptionResolverComposite
  3. It tries resolvers in order (left → right):
    • ExceptionHandlerExceptionResolver
    • ResponseStatusExceptionResolver
    • DefaultHandlerExceptionResolver
  4. If none can handle → goes to DefaultErrorAttributes
  5. Builds final error response

3. Example: Unhandled Exception

From page 1:

@GetMapping("/get-user")
public String getUser() {
    throw new NullPointerException("throwing null pointer exception for testing");
}

Output (page 2):

{
  "timestamp": "...",
  "status": 500,
  "error": "Internal Server Error",
  "path": "/api/get-user"
}

Because:

  • No resolver handled it
  • DefaultErrorAttributes filled default values

4. Why Custom Exception also returns 500? (Page 2)

Even when you throw:

throw new CustomException(HttpStatus.BAD_REQUEST, "UserID is missing");

It still returns 500 because:

You are NOT returning ResponseEntity
So Spring’s resolvers decide the response


5. DefaultErrorAttributes (Page 3)

It builds default response fields:

  • timestamp
  • status
  • error
  • path
  • message (if allowed)

And finally:

return new ResponseEntity<>(body, status);

6. ExceptionHandlerExceptionResolver (Page 4)

Handles:

  • @ExceptionHandler
  • @ControllerAdvice

Controller Level Example

@ExceptionHandler(CustomException.class)
public ResponseEntity<String> handle(CustomException ex) {
    return ResponseEntity.status(ex.getStatus()).body(ex.getMessage());
}

Now response is controlled by you.


7. Multiple @ExceptionHandler (Page 4–5)

You can handle multiple exceptions:

@ExceptionHandler({CustomException.class, IllegalArgumentException.class})
public ResponseEntity<String> handleAll(Exception ex) {
    return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ex.getMessage());
}

8. Global Exception Handling (Page 5)

Problem with controller-level:

Code duplication

Solution:

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(CustomException.class)
    public ResponseEntity<String> handle(CustomException ex) {
        return new ResponseEntity<>(ex.getMessage(), ex.getStatus());
    }
}

9. Priority: Controller vs Global (Page 6)

If both exist:

Controller-level handler gets priority


10. If Two Handlers Can Handle Same Exception

Rule (page 6):

Spring chooses the most specific match first
Then parent class


11. ResponseStatusExceptionResolver (Page 6–7)

Handles exceptions annotated with:

@ResponseStatus(HttpStatus.BAD_REQUEST)
public class CustomException extends RuntimeException {}

Then:

throw new CustomException("UserID missing");

It will return 400 without @ExceptionHandler.


12. Conflict: @ExceptionHandler + @ResponseStatus (Page 7)

If both exist:

  • Spring uses ExceptionHandlerExceptionResolver first
  • @ResponseStatus is ignored

👉 Recommendation: Do not mix both


13. DefaultHandlerExceptionResolver (Page 8)

Handles:

  • MethodNotAllowed (405)
  • NoResourceFound (404)
  • MissingPathVariable
  • TypeMismatch, etc.

EXTRA REAL-WORLD POINTS

  • Always return ResponseEntity in handlers
  • Use ErrorResponse DTO
  • Log full stack trace, return safe message
  • Use @ControllerAdvice in microservices
  • Never expose internal exception messages

INTERVIEW QUESTIONS & ANSWERS

Q1. What is HandlerExceptionResolver?

Ans: Interface used by Spring to resolve exceptions to HTTP responses.


Q2. Resolver execution order?

Ans:

  1. ExceptionHandlerExceptionResolver
  2. ResponseStatusExceptionResolver
  3. DefaultHandlerExceptionResolver

Q3. Why custom exception returns 500?

Ans: Because no ResponseEntity is created, so DefaultErrorAttributes builds response.


Q4. Which has higher priority: controller or global?

Ans: Controller-level @ExceptionHandler.


Q5. When to use @ResponseStatus?

Ans: For simple static status mapping without ResponseEntity.


Q6. Can we use both @ResponseStatus and @ExceptionHandler?

Ans: Not recommended – leads to conflict.


Q7. What does DefaultHandlerExceptionResolver handle?

Ans: Spring framework exceptions like 404, 405.


 

Leave a Reply