En este tema, aprenderemos cómo manejar excepciones en aplicaciones RESTful utilizando Spring Boot. El manejo adecuado de excepciones es crucial para proporcionar respuestas claras y útiles a los clientes de nuestra API, así como para mantener la robustez y la seguridad de nuestra aplicación.

Contenido

Introducción al Manejo de Excepciones

El manejo de excepciones en una API RESTful implica capturar errores que ocurren durante la ejecución de las solicitudes y devolver respuestas adecuadas al cliente. Spring Boot proporciona varias formas de manejar excepciones, desde el manejo de excepciones específicas en los controladores hasta el manejo global de excepciones.

Tipos de Excepciones en Spring Boot

En Spring Boot, las excepciones pueden clasificarse en dos categorías principales:

  1. Excepciones Controladas (Checked Exceptions): Son excepciones que el compilador obliga a manejar. Ejemplo: IOException.
  2. Excepciones No Controladas (Unchecked Exceptions): Son excepciones que no están obligadas a ser manejadas por el compilador. Ejemplo: NullPointerException.

Manejo Global de Excepciones

Para manejar excepciones de manera global en Spring Boot, podemos utilizar la anotación @ControllerAdvice. Esta anotación permite definir una clase que manejará las excepciones lanzadas por los controladores de nuestra aplicación.

Ejemplo de Manejo Global de Excepciones

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;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<?> resourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
        return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<?> globalExceptionHandler(Exception ex, WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
        return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

En este ejemplo, GlobalExceptionHandler maneja dos tipos de excepciones: ResourceNotFoundException y Exception. La clase ErrorDetails es una clase personalizada que contiene detalles sobre el error.

Clase ErrorDetails

import java.util.Date;

public class ErrorDetails {
    private Date timestamp;
    private String message;
    private String details;

    public ErrorDetails(Date timestamp, String message, String details) {
        super();
        this.timestamp = timestamp;
        this.message = message;
        this.details = details;
    }

    // Getters and Setters
}

Creación de Excepciones Personalizadas

Podemos crear nuestras propias excepciones personalizadas para manejar casos específicos en nuestra aplicación.

Ejemplo de Excepción Personalizada

public class ResourceNotFoundException extends RuntimeException {
    private static final long serialVersionUID = 1L;

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

Ejemplo Práctico

Vamos a crear un ejemplo práctico donde manejamos una excepción personalizada ResourceNotFoundException en un controlador REST.

Controlador REST

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/v1")
public class UserController {

    @GetMapping("/users/{id}")
    public ResponseEntity<User> getUserById(@PathVariable(value = "id") Long userId) throws ResourceNotFoundException {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("User not found for this id :: " + userId));
        return ResponseEntity.ok().body(user);
    }
}

En este ejemplo, si el usuario con el ID especificado no se encuentra, se lanza una ResourceNotFoundException.

Ejercicios Prácticos

  1. Ejercicio 1: Crea una excepción personalizada llamada InvalidInputException y maneja esta excepción en un controlador REST.
  2. Ejercicio 2: Modifica el GlobalExceptionHandler para manejar la excepción InvalidInputException y devolver un estado HTTP 400 (Bad Request).

Soluciones

Solución Ejercicio 1

public class InvalidInputException extends RuntimeException {
    private static final long serialVersionUID = 1L;

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

Solución Ejercicio 2

@ExceptionHandler(InvalidInputException.class)
public ResponseEntity<?> invalidInputExceptionHandler(InvalidInputException ex, WebRequest request) {
    ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
    return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
}

Conclusión

En esta sección, hemos aprendido cómo manejar excepciones en aplicaciones RESTful utilizando Spring Boot. Hemos visto cómo manejar excepciones de manera global, cómo crear excepciones personalizadas y cómo aplicar estos conceptos en un ejemplo práctico. El manejo adecuado de excepciones es esencial para construir APIs robustas y fáciles de usar.

En el próximo módulo, exploraremos cómo acceder a datos utilizando Spring Boot y Spring Data JPA.

Curso de Spring Boot

Módulo 1: Introducción a Spring Boot

Módulo 2: Conceptos Básicos de Spring Boot

Módulo 3: Construyendo Servicios Web RESTful

Módulo 4: Acceso a Datos con Spring Boot

Módulo 5: Seguridad en Spring Boot

Módulo 6: Pruebas en Spring Boot

Módulo 7: Funciones Avanzadas de Spring Boot

Módulo 8: Despliegue de Aplicaciones Spring Boot

Módulo 9: Rendimiento y Monitoreo

Módulo 10: Mejores Prácticas y Consejos

© Copyright 2024. Todos los derechos reservados