Exception Handling in a RESTful Service with @ControllerAdvice
J.P. MorganSoftware Engineer · OnsiteLast updated
This problem tests your ability to design a centralized exception handling mechanism in a Java Spring environment, ensuring consistent API error responses and proper abstraction of internal implementation details.
The Problem
You are building a RESTful service for a banking application. You need to ensure that regardless of where an error occurs in your service layer, the client receives a consistent, standardized JSON response that follows a predefined contract. Furthermore, you must ensure that sensitive stack traces or internal server details are never exposed to the client.
Requirements
- Define a standard error response structure (e.g.,
ErrorResponse) that includes a timestamp, an HTTP status code, a human-readable error message, and a unique internal trace ID. - Implement a centralized exception handler using
@ControllerAdviceto intercept specific exceptions (e.g.,UserNotFoundException,InsufficientFundsException, and genericException). - Map these custom exceptions to appropriate HTTP status codes (e.g.,
404 Not Foundfor missing resources,422 Unprocessable Entityfor business logic violations).
Task
Write a Java implementation consisting of:
- A POJO class
ErrorResponse. - A global exception handler class
GlobalExceptionHandlerusing@ControllerAdvice. - A brief explanation of how you would generate and log the
traceIdso that it correlates with server-side logs.
Example
If a UserNotFoundException is thrown, the client should receive a 404 status with the body:
{
"timestamp": "2023-10-27T10:00:00Z",
"status": 404,
"message": "User with ID 123 not found.",
"traceId": "a1-b2-c3-d4"
}
Hints
Hint 1
Consider using the @ExceptionHandler annotation on methods within your @ControllerAdvice class to map specific exception types to response entities.
Hint 2
Use a request-scoped bean or a thread-local variable to generate a unique correlation ID at the start of each request for the traceId field.
Hint 3
Ensure the generic Exception handler is marked with @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) to catch unhandled runtime errors and prevent leakage.
Follow-up questions
- How would you handle validation errors, such as those thrown by @Valid annotations, within this centralized framework?
- If your application grows to have dozens of business exceptions, how would you prevent the GlobalExceptionHandler class from becoming too large and unmaintainable?
- How does your implementation change if you need to internationalize the error messages based on the 'Accept-Language' header of the incoming request?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.