Global Exception Handling
@RestControllerAdvice
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(
ResourceNotFoundException ex) {
log.warn("Resource not found: {}", ex.getMessage());
return ResponseEntity.status(404).body(
ErrorResponse.of("NOT_FOUND", ex.getMessage()));
}
@ExceptionHandler(ValidationException.class)
public ResponseEntity<ErrorResponse> handleValidation(
ValidationException ex) {
log.warn("Validation failed: {}", ex.getMessage());
return ResponseEntity.status(422).body(
ErrorResponse.of("VALIDATION_ERROR", ex.getMessage()));
}
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ErrorResponse> handleBusiness(
BusinessException ex) {
log.error("Business error: {}", ex.getMessage());
return ResponseEntity.status(409).body(
ErrorResponse.of(ex.getCode(), ex.getMessage()));
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGeneral(Exception ex) {
log.error("Unexpected error", ex);
return ResponseEntity.status(500).body(
ErrorResponse.of("INTERNAL_ERROR",
"An unexpected error occurred"));
}
}
Custom Exceptions
@ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
@ResponseStatus(HttpStatus.CONFLICT)
public class BusinessException extends RuntimeException {
private final String code;
public BusinessException(String code, String message) {
super(message);
this.code = code;
}
}
Error Response DTO
@Data
public class ErrorResponse {
private String code;
private String message;
private String traceId;
private Instant timestamp;
public static ErrorResponse of(String code, String message) {
ErrorResponse error = new ErrorResponse();
error.setCode(code);
error.setMessage(message);
error.setTraceId(MDC.get("traceId"));
error.setTimestamp(Instant.now());
return error;
}
}
Exception Patterns
Custom Exceptions
public class NotFoundException extends RuntimeException {
public NotFoundException(String message) {
super(message);
}
}
Handling
- Catch specific exceptions
- Handle at appropriate layer
- Log with context
- Return meaningful errors
Best Practices
- Use unchecked exceptions for bugs
- Use checked exceptions for recoverable
- Don't catch and ignore
- Include correlation IDs
Key Points
- Understanding Global Exception Handling is essential for production systems
- Always consider scalability and maintainability
- Test thoroughly before deploying to production
- Monitor performance and set up alerting
Common Patterns
- Validation: Always validate input at the boundary
- Error Handling: Use structured error responses
- Logging: Log key events for debugging
- Testing: Unit, integration, and load tests
- Documentation: Keep docs updated with code changes
Practice Problems
Design and implement a solution for Global Exception Handling in a backend system. Consider scalability, error handling, and production readiness.
Solution
// Global Exception Handling implementation
// Key aspects: validation, error handling, logging, testing
public class GlobalExceptionHandling {
// Production-ready implementation
}Identify and handle edge cases for Global Exception Handling. What happens under high load, with invalid input, or during failures?
Solution
// Edge case handling:
// 1. Null/empty input -> validation
// 2. High load -> rate limiting, queuing
// 3. Failures -> retries, circuit breaker
// 4. Concurrent access -> locks, idempotencyWrite a testing strategy for Global Exception Handling. Include unit tests, integration tests, and performance tests.
Solution
// Test plan:
// - Unit: 80% coverage target
// - Integration: API contracts
// - Performance: latency, throughput
// - Chaos: failure injectionQuiz
1. What does @RestControllerAdvice do?
2. Why use a custom ErrorResponse class?
3. What is the primary purpose of Global Exception Handling?
4. What is a common mistake when implementing Global Exception Handling?
Flashcards
Question
@RestControllerAdvice purpose?
Click to reveal answer
Answer
Global exception handling for all controllers
Question
Why custom ErrorResponse DTO?
Click to reveal answer
Answer
Standardize error format across all endpoints
Question
What is Global Exception Handling?
Click to reveal answer
Answer
Global Exception Handling is a key concept in backend development.
Question
When to use Global Exception Handling?
Click to reveal answer
Answer
Use Global Exception Handling when building production systems that require reliability, scalability, and maintainability.
Question
Global Exception Handling best practices
Click to reveal answer
Answer
Follow SOLID principles, write clean code, test thoroughly, document decisions, and monitor in production.
Revision Notes
Key Takeaways
- 1.@RestControllerAdvice provides global exception handling
- 2.Create custom exceptions with HTTP status codes
- 3.ErrorResponse DTO standardizes error responses
- 4.Log all exceptions, never expose stack traces to clients
Interview Tips
- •Implement global exception handling
- •Design error response formats
Cheat Sheet
Global Exception Handling
- @RestControllerAdvice: Global handler
- @ExceptionHandler: Method per exception type
- Custom exceptions: Extend RuntimeException with status
- ErrorResponse DTO: { code, message, traceId, timestamp }
- Log: Warnings for expected, errors for unexpected