Introduction
In a Spring Boot application, handling exceptions gracefully is crucial for providing meaningful error responses to clients. Instead of writing exception handling logic in each controller, we can use @ControllerAdvice
to centralize exception handling across the application.
What is @ControllerAdvice?
@ControllerAdvice
is a specialized component in Spring that allows you to handle exceptions globally across multiple controllers. It helps maintain cleaner code by separating exception handling logic from the main business logic.
Creating a Global Exception Handler using @ControllerAdvice
Step 1: Define Custom Exceptions
Let’s define a couple of custom exceptions:
package com.example.exception;
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
package com.example.exception;
public class BadRequestException extends RuntimeException {
public BadRequestException(String message) {
super(message);
}
}
Step 2: Implement the Global Exception Handler
Create a class annotated with @ControllerAdvice
to handle exceptions globally:
package com.example.advice;
import com.example.exception.ResourceNotFoundException;
import com.example.exception.BadRequestException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ControllerAdvice;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<Map<String, Object>> handleResourceNotFoundException(ResourceNotFoundException ex) {
Map<String, Object> errorDetails = new HashMap<>();
errorDetails.put("timestamp", LocalDateTime.now());
errorDetails.put("message", ex.getMessage());
return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
}
@ExceptionHandler(BadRequestException.class)
public ResponseEntity<Map<String, Object>> handleBadRequestException(BadRequestException ex) {
Map<String, Object> errorDetails = new HashMap<>();
errorDetails.put("timestamp", LocalDateTime.now());
errorDetails.put("message", ex.getMessage());
return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<Map<String, Object>> handleGlobalException(Exception ex) {
Map<String, Object> errorDetails = new HashMap<>();
errorDetails.put("timestamp", LocalDateTime.now());
errorDetails.put("message", "An unexpected error occurred");
return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Step 3: Use Exceptions in a Controller
Create a simple Spring Boot controller that triggers the exceptions:
package com.example.controller;
import com.example.exception.ResourceNotFoundException;
import com.example.exception.BadRequestException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/find")
public String findResource(@RequestParam(required = false) String id) {
if (id == null) {
throw new BadRequestException("ID parameter is missing");
}
if ("123".equals(id)) {
return "Resource found";
}
throw new ResourceNotFoundException("Resource with ID " + id + " not found");
}
}
Step 4: Testing the Application
1. Valid Request:
GET /find?id=123
Response: 200 OK
"Resource found"
2. Missing ID Parameter:
GET /find
Response: 400 Bad Request
{
"timestamp": "2024-03-18T12:00:00",
"message": "ID parameter is missing"
}
3. Invalid ID:
GET /find?id=999
Response: 404 Not Found
{
"timestamp": "2024-03-18T12:00:00",
"message": "Resource with ID 999 not found"
}
Conclusion
Using @ControllerAdvice
, we can effectively centralize and manage exception handling in Spring Boot applications. This approach enhances code maintainability, improves user experience, and ensures consistent error responses.