Implementing Global Exception Handling with @ControllerAdvice

To implement global exception handling in a Spring application, the @ControllerAdvice annotation is used. It allows you to centralize exception handling across multiple controllers.

Below is an example of how you can implement global exception handling with @ControllerAdvice in your application:


1. Define a Global Exception Handler

Create a class with the @ControllerAdvice annotation to handle exceptions globally. Within this class, use the @ExceptionHandler annotation on methods to define specific exception handling logic.

package org.kodejava;

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 org.springframework.web.context.request.WebRequest;

// Marks this class as a global exception handler
@ControllerAdvice
public class GlobalExceptionHandler {

    // Handle specific exceptions
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<?> handleResourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
        ErrorResponse errorResponse = new ErrorResponse(
                HttpStatus.NOT_FOUND.value(),
                ex.getMessage(),
                request.getDescription(false));
        return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
    }

    // Handle global exceptions (for all other exceptions)
    @ExceptionHandler(Exception.class)
    public ResponseEntity<?> handleGlobalException(Exception ex, WebRequest request) {
        ErrorResponse errorResponse = new ErrorResponse(
                HttpStatus.INTERNAL_SERVER_ERROR.value(),
                "An unexpected error occurred",
                request.getDescription(false));
        return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

2. Create a Custom Exception Class (Optional)

Define specific exception classes for your business use cases. For example, a ResourceNotFoundException for handling “not found” errors.

package org.kodejava;

public class ResourceNotFoundException extends RuntimeException {

    private static final long serialVersionUID = 1L;

    public ResourceNotFoundException(String message) {
        super(message);
    }
}

3. Create an Error Response Model

Create a class to structure the error response data consistently.

package org.kodejava;

public class ErrorResponse {

    private int statusCode;
    private String message;
    private String details;

    public ErrorResponse(int statusCode, String message, String details) {
        this.statusCode = statusCode;
        this.message = message;
        this.details = details;
    }

    // Getters and Setters
    public int getStatusCode() {
        return statusCode;
    }

    public void setStatusCode(int statusCode) {
        this.statusCode = statusCode;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getDetails() {
        return details;
    }

    public void setDetails(String details) {
        this.details = details;
    }
}

4. Throw Custom Exceptions in Your Controller

You can now throw the ResourceNotFoundException or other exceptions in your controllers, and let the global exception handler process them.

package org.kodejava;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class TestController {

    @GetMapping("/resource")
    public String getResource() {
        throw new ResourceNotFoundException("Resource not found with ID");
    }
}

5. Test the Application

When you access the /api/resource endpoint, the global exception handler will catch the ResourceNotFoundException and return a structured error response. Example response:

{
  "statusCode": 404,
  "message": "Resource not found with ID",
  "details": "uri=/api/resource"
}

Advantages of Using @ControllerAdvice

  1. Centralized Exception Handling: Removes the need to write exception handling in multiple controllers.
  2. Improved Readability: Controllers are cleaner as they no longer handle exceptions.
  3. Reusability: Reuse the exception handler for different types of exceptions across the application.
  4. Custom Responses: Provides flexibility to return consistent error responses.

This implementation ensures your application has a robust and maintainable error-handling mechanism using Spring’s @ControllerAdvice.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.