Global Exception Handling
One place to catch all errors. Clean JSON, not ugly stack traces.
The Hospital Emergency Ward Analogy:
Imagine if someone gets injured on the streets of Hyderabad. Instead of treating them on the road wherever they fell, an ambulance brings them to the central Emergency Ward (ER) of a hospital. The ER doctors assess the injury and provide the right treatment.
In Spring Boot, @RestControllerAdvice is that central ER. Whenever an exception “falls” anywhere in your controllers, Spring’s ambulance catches it and brings it to your global exception handler. You then write the logic to return a proper HTTP status and JSON message.
- @RestControllerAdvice: A combination of
@ControllerAdviceand@ResponseBody. It catches exceptions thrown by all controllers globally. - @ExceptionHandler: Defines which specific exception class this method will handle.
- Custom Exceptions: You can create your own exceptions (e.g.,
ResourceNotFoundException) and map them to specific HTTP statuses (404, 400, etc).
// 1. Custom Error Response Class
package com.devinhyderabad;
import java.time.LocalDateTime;
public class ErrorResponse {
private LocalDateTime timestamp;
private int status;
private String message;
public ErrorResponse(int status, String message) {
this.timestamp = LocalDateTime.now();
this.status = status;
this.message = message;
}
// Getters
public LocalDateTime getTimestamp() { return timestamp; }
public int getStatus() { return status; }
public String getMessage() { return message; }
}// 2. Custom Exception
package com.devinhyderabad;
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
// 3. The Global Handler
package com.devinhyderabad;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
// Handle our custom 404 exception
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
ErrorResponse error = new ErrorResponse(404, ex.getMessage());
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
// Handle generic runtime exceptions (500 error)
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<ErrorResponse> handleRuntimeException(RuntimeException ex) {
ErrorResponse error = new ErrorResponse(500, "An internal server error occurred");
return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
}Now, if any controller throws new ResourceNotFoundException("Book not found"), the client receives: {"timestamp":"2023-10-25T...","status":404,"message":"Book not found"}.
Interview Question: “What is the difference between @ControllerAdvice and @RestControllerAdvice?”
Answer: @ControllerAdvice was used in traditional Spring MVC. If a method returns a JSON response, you must add @ResponseBody to it. @RestControllerAdvice is the modern equivalent (Spring 4.3+) that automatically adds @ResponseBody to all methods, ensuring everything returns JSON.
Enterprise Note: Never expose raw Java stack traces to the client. Stack traces reveal your database structure, package names, and library versions, which hackers can use to exploit your system. Always catch exceptions in @RestControllerAdvice and return generic messages for 500 errors.
Key Takeaways
- ✅ @RestControllerAdvice catches exceptions globally across all controllers
- ✅ @ExceptionHandler maps specific exceptions to HTTP status codes
- ✅ Custom exceptions like ResourceNotFoundException improve API clarity
- ✅ Never expose raw stack traces to clients — security risk for enterprise apps
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login