Spring Boot @RestControllerAdvice Example

1. Introduction

The @RestControllerAdvice annotation in Spring Boot is used to handle exceptions across the entire application in a global, not duplicated manner. It is typically used in conjunction with the @ExceptionHandler annotation to define methods that handle exceptions thrown by controllers.

Key Points

1. @RestControllerAdvice is a specialization of the @ControllerAdvice annotation that includes the @ResponseBody to ensure responses are written directly to the HTTP response body.

2. It allows for the global handling of exceptions across multiple controllers.

3. Helps in building a cleaner error-handling mechanism by centralizing response handling.

2. Development Steps

1. Create a @RestControllerAdvice annotated class.

2. Define methods within this class using @ExceptionHandler.

3. Apply exception handling methods to specific exceptions or to all exceptions globally.

3. Implementation Example

// Step 1: Define custom exceptions
public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);
    }
}

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

// Step 2: Define the RestControllerAdvice class
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleAllExceptions(Exception ex) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An error occurred: " + ex.getMessage());
    }

    @ExceptionHandler(NullPointerException.class)
    public ResponseEntity<String> handleNullPointerException(NullPointerException ex) {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Null pointer exception caught: " + ex.getMessage());
    }

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<String> handleResourceNotFoundException(ResourceNotFoundException ex) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Resource not found: " + ex.getMessage());
    }

    @ExceptionHandler(InvalidDataException.class)
    public ResponseEntity<String> handleInvalidDataException(InvalidDataException ex) {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Invalid data provided: " + ex.getMessage());
    }
}

// Step 3: Example controller to demonstrate exception handling
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @GetMapping("/test")
    public String testMethod() {
        throw new NullPointerException("Test Null Pointer");
    }

    @GetMapping("/data")
    public String testData() {
        throw new InvalidDataException("Sample Invalid Data");
    }
}

Explanation:

1. GlobalExceptionHandler is annotated with @RestControllerAdvice, making it applicable to handle exceptions thrown by controllers across the entire application.

2. Custom exceptions ResourceNotFoundException and InvalidDataException are defined to handle specific business logic-related errors.

3. Within the GlobalExceptionHandler, methods are defined with @ExceptionHandler. Each method caters to different exceptions and provides appropriate HTTP responses.

4. MyController demonstrates the use of these handlers with methods that simulate throwing these exceptions, thus showcasing the global exception-handling mechanism.

Comments