Contenido del Curso
Spring Boot Backend
Spring Boot Backend
Exception Handling
Exception handling in a REST API using Spring Boot is a crucial aspect of development that enables effective management of errors and informs clients about issues that have occurred on the server. Let’s examine this process in more detail.
How Does it Help to Notify the Client of Errors?
Error handling in a REST API helps standardize the format of error responses, making it easier for clients to work with the responses. This, in turn, informs them about the reasons for errors, allowing clients to understand what went wrong and how to correct the issue.
Additionally, such handling enables differentiation between types of errors, such as validation errors or access issues, making the error messages more accurate and useful.
Implementation of Exception Handling Using Annotations
Spring Boot provides several tools for exception handling. The main ones are the @ControllerAdvice
and @ExceptionHandler
annotations.
The @ControllerAdvice
annotation allows you to define global exception handlers for all controllers in the application, which helps centralize error handling and avoid code duplication.
Within a class annotated with @ControllerAdvice
, methods annotated with @ExceptionHandler
specify which types of exceptions a particular method should handle. This simplifies error management and makes the code cleaner and more organized.
GlobalExceptionHandler
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ApiException.class) public ResponseEntity<?> handleException(ApiException ex) { // error handling } }
Within this class, the handleException()
method will be invoked when an exception of type ApiException
occurs in the application. The @ExceptionHandler(ApiException.class)
annotation indicates that this method handles exceptions of this specific type.
Creating a Сustom Exception
But what exactly is the ApiException
? It is a custom exception created specifically for our API, and we can create our own exceptions and use them in our REST API.
You can learn about creating your own custom exceptions here.
ApiException
public class ApiException extends RuntimeException { // HTTP status code associated with this exception private final HttpStatus httpStatus; // Constructor to initialize the exception with a message and an HTTP status public ApiException(String message, HttpStatus httpStatus) { super(message); this.httpStatus = httpStatus; } // Getter method to retrieve the HTTP status public HttpStatus getHttpStatus() { return httpStatus; } }
This code defines the ApiException
class, which extends RuntimeException
and includes an additional field httpStatus
for storing the HTTP status. The class constructor takes a message and an HTTP status, which are then passed to the base constructor and stored in the httpStatus
field.
After this, we can throw an exception from our application:
Main
public BookResponseDTO updateBook(String id, BookRequestDTO book) { Book modelBook = MapperBook.dtoRequestToModel(book); Book repositoryBook = bookRepository.updateBook(id, modelBook); // If the book was not found in the repository, throw an ApiException with a NOT_FOUND status if (repositoryBook == null) { throw new ApiException("Not found book by id: " + id, HttpStatus.NOT_FOUND); } return MapperBook.modelToResponseDto(repositoryBook); }
This type of exception will be caught by a method handleException(ApiException ex)
designed to handle it, and within that method, we can define the logic for managing the exception.
The logic we want to implement is to catch exceptions related to the API and return a structured response containing error information along with the appropriate HTTP status.
Main
@ExceptionHandler(ApiException.class) public ResponseEntity<?> handleException(ApiException ex) { return new ResponseEntity<>(ErrorResponse .builder() .error(ex.getMessage()) .build(), ex.getHttpStatus() ); }
This code handles the ApiException
by creating a ResponseEntity
with error information. The handleException()
method constructs an ErrorResponse
object with the message from the exception and sets the HTTP status from the exception's httpStatus
field, returning this to the client.
We initialized the httpStatus
field when we throw the exception in our application.
ErrorResponse
is a class used to provide information about the error. It contains an error
field that displays the error description and is created using the @Data
and @Builder
annotations.
ErrorResponse
@Data @Builder public class ErrorResponse { private String error; }
The @Builder
annotation from Lombok
simplifies object creation by implementing the Builder pattern. It allows for a more readable and maintainable way to construct objects, especially those with many parameters. For example, you can create an ErrorResponse
instance like this:
The builder()
method initializes a new builder for the ErrorResponse
class. The error("ERROR")
method sets the error
field to "ERROR", and the build()
method constructs the final ErrorResponse
object with the specified value.
Error Handling in Our Application
Summary
Exception handling in a REST API centralizes error management by providing a consistent response format for the client. This simplifies the understanding and handling of errors, as clients receive clear and structured messages.
The use of @ControllerAdvice
and @ExceptionHandler
annotations allows for the customization of how different exceptions are handled, while custom exceptions can include additional information, such as HTTP status.
¡Gracias por tus comentarios!