Enhance Your Spring Boot APIs with @ControllerAdvice and Custom Exceptions


Handling exceptions in a robust and user-friendly way is a crucial aspect of developing RESTful APIs. In Spring Boot, @ControllerAdvice and @ExceptionHandler provide a powerful mechanism to manage exceptions effectively. In this blog, we’ll explore how to use these annotations to create a global exception handling mechanism.

What is @ControllerAdvice?

@ControllerAdvice is a specialization of the @Component annotation which allows you to handle exceptions across the whole application in one global handling component. It can be used to apply common handling logic to multiple controllers.

What is @ExceptionHandler?

@ExceptionHandler is used to handle specific exceptions thrown by controller methods. It can be used within a @ControllerAdvice class or a specific controller class.

Step-by-Step Guide

1. Setting Up Your Spring Boot Project

Create a new Spring Boot project using your preferred method (Spring Initializr, IDE, etc.). Add the necessary dependencies such as spring-boot-starter-web.

2. Creating a Custom Exception

First, let's create a custom exception that our application can throw.

java
package com.example.demo.exception; public class ResourceNotFoundException extends RuntimeException { public ResourceNotFoundException(String message) { super(message); } }

3. Creating a Global Exception Handler with @ControllerAdvice

Next, create a class annotated with @ControllerAdvice to handle exceptions globally.

java
package com.example.demo.exception; 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; import java.time.LocalDateTime; @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ResourceNotFoundException.class) public ResponseEntity<ErrorDetails> handleResourceNotFoundException(ResourceNotFoundException ex, WebRequest request) { ErrorDetails errorDetails = new ErrorDetails(LocalDateTime.now(), ex.getMessage(), request.getDescription(false)); return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND); } @ExceptionHandler(Exception.class) public ResponseEntity<ErrorDetails> handleGlobalException(Exception ex, WebRequest request) { ErrorDetails errorDetails = new ErrorDetails(LocalDateTime.now(), ex.getMessage(), request.getDescription(false)); return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR); } }

In the GlobalExceptionHandler class, we have two methods annotated with @ExceptionHandler:

  • handleResourceNotFoundException: Handles ResourceNotFoundException.
  • handleGlobalException: Handles all other exceptions.

The ErrorDetails class used in the responses is a simple POJO:

java
package com.example.demo.exception; import java.time.LocalDateTime; public class ErrorDetails { private LocalDateTime timestamp; private String message; private String details; public ErrorDetails(LocalDateTime timestamp, String message, String details) { this.timestamp = timestamp; this.message = message; this.details = details; } // Getters and Setters }

4. Creating a Controller

Let's create a simple controller to demonstrate the exception handling.

java
package com.example.demo.controller; import com.example.demo.exception.ResourceNotFoundException; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class DemoController { @GetMapping("/resource") public String getResource(@RequestParam(required = false) String id) { if (id == null) { throw new ResourceNotFoundException("Resource not found with id: " + id); } return "Resource with id: " + id; } }

In this controller, if the id parameter is not provided, a ResourceNotFoundException is thrown.

5. Running the Application

Run your Spring Boot application. When you access /resource without an id parameter, you will receive a 404 Not Found response with a JSON body containing error details. If any other exception occurs, you will receive a 500 Internal Server Error response.

Conclusion

Using @ControllerAdvice and @ExceptionHandler in Spring Boot allows you to manage exceptions globally and in a more organized way. This approach leads to cleaner code and a better separation of concerns. By following the steps outlined above, you can ensure that your application handles exceptions gracefully, providing meaningful error messages to clients.

Feel free to expand this setup with more specific exceptions and handlers as needed. Happy coding!

Post a Comment

0 Comments