Global Exception Handling in Spring REST APIs

In RESTful web services, handling errors gracefully and returning meaningful responses is crucial. Spring Boot makes it easy to handle exceptions globally using @ControllerAdvice and @ExceptionHandler.

๐Ÿ”ง What is @ControllerAdvice?

@ControllerAdvice is a specialized annotation in Spring used to handle exceptions globally across the whole application. It can be used to define global error handling logic for all controllers in one place.

✅ Benefits

  • Centralized exception handling
  • Cleaner and reusable code
  • Standardized error responses

๐Ÿ“ฆ 1. Create a Custom Exception

public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);
    }
}

๐Ÿ“ฆ 2. Create a Global Exception Handler

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<Map<String, Object>> handleNotFound(ResourceNotFoundException ex) {
        Map<String, Object> error = new HashMap<>();
        error.put("timestamp", LocalDateTime.now());
        error.put("status", HttpStatus.NOT_FOUND.value());
        error.put("error", "Not Found");
        error.put("message", ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<Map<String, Object>> handleGeneric(Exception ex) {
        Map<String, Object> error = new HashMap<>();
        error.put("timestamp", LocalDateTime.now());
        error.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
        error.put("error", "Internal Server Error");
        error.put("message", ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

๐Ÿ‘จ‍๐Ÿ’ป 3. Use the Exception in Controller

@RestController
@RequestMapping("/api/employees")
public class EmployeeController {

    @GetMapping("/{id}")
    public ResponseEntity<Employee> getEmployee(@PathVariable Long id) {
        Employee employee = employeeRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Employee not found with id " + id));
        return ResponseEntity.ok(employee);
    }
}

๐Ÿงช Sample Error Response (JSON)

{
  "timestamp": "2025-05-17T14:38:45.123",
  "status": 404,
  "error": "Not Found",
  "message": "Employee not found with id 10"
}

๐Ÿ“Œ Summary

  • @ControllerAdvice enables global exception handling across all controllers.
  • @ExceptionHandler handles specific exception types.
  • Clean, centralized, and consistent error handling improves maintainability.

๐Ÿ”— Related Posts

๐Ÿ› ️ CRUD API with Oracle

Step-by-step guide to build a Spring Boot REST API with Oracle DB integration.

๐Ÿท️ Spring REST Annotations

Learn about @GetMapping, @PostMapping, and other REST annotations in Spring Boot.

๐Ÿ” @Controller vs @RestController

Understand the key differences between @Controller and @RestController.

๐Ÿšจ Java Exception Best Practices

How to handle exceptions effectively in Java with tips and coding examples.