Chapter 5.3☕ 16 min read

Global Exception Handling

One place to catch all errors. Clean JSON, not ugly stack traces.

01The Concept: Central Emergency Ward

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.

02Technical Explanation
  1. @RestControllerAdvice: A combination of @ControllerAdvice and @ResponseBody. It catches exceptions thrown by all controllers globally.
  2. @ExceptionHandler: Defines which specific exception class this method will handle.
  3. Custom Exceptions: You can create your own exceptions (e.g., ResourceNotFoundException) and map them to specific HTTP statuses (404, 400, etc).
03Full Working Code: Clean Error Responses
// 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; }
}
04Error Response and Custom Exception
// 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"}.

05Why It Matters / Interview Note

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