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.
javapackage 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.
javapackage 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
: HandlesResourceNotFoundException
.handleGlobalException
: Handles all other exceptions.
The ErrorDetails
class used in the responses is a simple POJO:
javapackage 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.
javapackage 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!
0 Comments