Spring Boot

SpringBoot

Tutorial SpringBoot: Gestión de errores RestControllerAdvice

Aprende a manejar errores centralizados en APIs REST con @RestControllerAdvice y @ExceptionHandler en Spring Boot para mejorar tu código.

Aprende SpringBoot y certifícate

@ExceptionHandler y @RestControllerAdvice

La gestión centralizada de errores en Spring Boot permite manejar excepciones de forma consistente en toda la aplicación REST. En lugar de duplicar código de manejo de errores en cada controlador, Spring proporciona un mecanismo elegante para centralizar esta responsabilidad mediante anotaciones específicas.

Fundamentos de @ExceptionHandler

La anotación @ExceptionHandler permite definir métodos que capturan y procesan excepciones específicas dentro de un controlador. Este enfoque básico funciona bien cuando necesitas manejar errores particulares de un solo controlador.

@RestController
@RequestMapping("/api/usuarios")
public class UsuarioController {
    
    @Autowired
    private UsuarioService usuarioService;
    
    @GetMapping("/{id}")
    public Usuario obtenerUsuario(@PathVariable Long id) {
        return usuarioService.buscarPorId(id);
    }
    
    // Manejo local de excepciones
    @ExceptionHandler(UsuarioNoEncontradoException.class)
    public ResponseEntity<String> manejarUsuarioNoEncontrado(UsuarioNoEncontradoException ex) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND)
                .body("Usuario no encontrado: " + ex.getMessage());
    }
}

El método anotado con @ExceptionHandler intercepta automáticamente las excepciones del tipo especificado que ocurran en cualquier método del mismo controlador. Sin embargo, este enfoque tiene limitaciones cuando necesitas aplicar el mismo manejo de errores en múltiples controladores.

Introducción a @RestControllerAdvice

La anotación @RestControllerAdvice extiende las capacidades de manejo de errores a nivel global de la aplicación. Esta anotación combina @ControllerAdvice con @ResponseBody, lo que la hace ideal para APIs REST que devuelven respuestas JSON.

@RestControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(UsuarioNoEncontradoException.class)
    public ResponseEntity<ErrorResponse> manejarUsuarioNoEncontrado(UsuarioNoEncontradoException ex) {
        ErrorResponse error = new ErrorResponse(
            "USUARIO_NO_ENCONTRADO",
            ex.getMessage(),
            LocalDateTime.now()
        );
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
    }
    
    @ExceptionHandler(ValidationException.class)
    public ResponseEntity<ErrorResponse> manejarValidacion(ValidationException ex) {
        ErrorResponse error = new ErrorResponse(
            "DATOS_INVALIDOS",
            ex.getMessage(),
            LocalDateTime.now()
        );
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
    }
}

Creación de respuestas de error estructuradas

Para mantener consistencia en las respuestas de error, es recomendable crear una clase que represente la estructura estándar de los errores:

public class ErrorResponse {
    private String codigo;
    private String mensaje;
    private LocalDateTime timestamp;
    
    public ErrorResponse(String codigo, String mensaje, LocalDateTime timestamp) {
        this.codigo = codigo;
        this.mensaje = mensaje;
        this.timestamp = timestamp;
    }
    
    // Getters y setters
    public String getCodigo() { return codigo; }
    public void setCodigo(String codigo) { this.codigo = codigo; }
    
    public String getMensaje() { return mensaje; }
    public void setMensaje(String mensaje) { this.mensaje = mensaje; }
    
    public LocalDateTime getTimestamp() { return timestamp; }
    public void setTimestamp(LocalDateTime timestamp) { this.timestamp = timestamp; }
}

Manejo de múltiples tipos de excepciones

Un controlador de excepciones global puede manejar diferentes tipos de errores con métodos específicos para cada caso:

@RestControllerAdvice
public class GlobalExceptionHandler {
    
    // Errores de validación de Spring
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> manejarValidacionCampos(MethodArgumentNotValidException ex) {
        StringBuilder mensaje = new StringBuilder("Errores de validación: ");
        ex.getBindingResult().getFieldErrors().forEach(error -> 
            mensaje.append(error.getField()).append(" - ").append(error.getDefaultMessage()).append("; ")
        );
        
        ErrorResponse error = new ErrorResponse(
            "VALIDACION_FALLIDA",
            mensaje.toString(),
            LocalDateTime.now()
        );
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
    }
    
    // Errores de conversión de tipos
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ResponseEntity<ErrorResponse> manejarTipoIncorrecto(MethodArgumentTypeMismatchException ex) {
        String mensaje = String.format("El parámetro '%s' debe ser de tipo %s", 
            ex.getName(), ex.getRequiredType().getSimpleName());
        
        ErrorResponse error = new ErrorResponse(
            "TIPO_PARAMETRO_INCORRECTO",
            mensaje,
            LocalDateTime.now()
        );
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
    }
    
    // Captura general para excepciones no manejadas
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> manejarErrorGeneral(Exception ex) {
        ErrorResponse error = new ErrorResponse(
            "ERROR_INTERNO",
            "Ha ocurrido un error inesperado",
            LocalDateTime.now()
        );
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
    }
}

Acceso a información de la petición

Los métodos de manejo de excepciones pueden acceder a información adicional sobre la petición HTTP que causó el error:

@RestControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(AccesoDenegadoException.class)
    public ResponseEntity<ErrorResponse> manejarAccesoDenegado(
            AccesoDenegadoException ex, 
            HttpServletRequest request) {
        
        String mensaje = String.format("Acceso denegado al recurso: %s %s", 
            request.getMethod(), request.getRequestURI());
        
        ErrorResponse error = new ErrorResponse(
            "ACCESO_DENEGADO",
            mensaje,
            LocalDateTime.now()
        );
        return ResponseEntity.status(HttpStatus.FORBIDDEN).body(error);
    }
}

Configuración de alcance específico

@RestControllerAdvice permite limitar su alcance a controladores específicos mediante atributos de configuración:

// Solo aplica a controladores en el paquete especificado
@RestControllerAdvice(basePackages = "com.ejemplo.api.controladores")
public class ApiExceptionHandler {
    // Métodos de manejo de excepciones
}

// Solo aplica a controladores específicos
@RestControllerAdvice(assignableTypes = {UsuarioController.class, ProductoController.class})
public class EspecificoExceptionHandler {
    // Métodos de manejo de excepciones
}

Esta flexibilidad permite crear diferentes estrategias de manejo de errores para distintas partes de la aplicación, manteniendo la separación de responsabilidades y facilitando el mantenimiento del código.

Aprende SpringBoot online

Otras lecciones de SpringBoot

Accede a todas las lecciones de SpringBoot y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Spring Boot

Spring Boot

Introducción Y Entorno

Spring Boot Starters

Spring Boot

Introducción Y Entorno

Inyección De Dependencias

Spring Boot

Introducción Y Entorno

Crear Proyecto Con Spring Initializr

Spring Boot

Introducción Y Entorno

Crear Proyecto Desde Visual Studio Code

Spring Boot

Introducción Y Entorno

Controladores Spring Mvc

Spring Boot

Spring Mvc Con Thymeleaf

Vista En Spring Mvc Con Thymeleaf

Spring Boot

Spring Mvc Con Thymeleaf

Controladores Spring Rest

Spring Boot

Spring Mvc Con Thymeleaf

Open Api Y Cómo Agregarlo En Spring Boot

Spring Boot

Spring Mvc Con Thymeleaf

Servicios En Spring

Spring Boot

Spring Mvc Con Thymeleaf

Clientes Resttemplate Y Restclient

Spring Boot

Spring Mvc Con Thymeleaf

Rxjava En Spring Web

Spring Boot

Spring Mvc Con Thymeleaf

Métodos Post En Controladores Mvc

Spring Boot

Spring Mvc Con Thymeleaf

Métodos Get En Controladores Mvc

Spring Boot

Spring Mvc Con Thymeleaf

Formularios En Spring Mvc

Spring Boot

Spring Mvc Con Thymeleaf

Crear Proyecto Con Intellij Idea

Spring Boot

Spring Mvc Con Thymeleaf

Introducción A Los Modelos Mvc

Spring Boot

Spring Mvc Con Thymeleaf

Layouts Y Fragmentos En Thymeleaf

Spring Boot

Spring Mvc Con Thymeleaf

Estilización Con Bootstrap Css

Spring Boot

Spring Mvc Con Thymeleaf

Gestión De Errores Controlleradvice

Spring Boot

Spring Mvc Con Thymeleaf

Estilización Con Tailwind Css

Spring Boot

Spring Mvc Con Thymeleaf

Introducción A Controladores Rest

Spring Boot

Spring Rest

Métodos Get En Controladores Rest

Spring Boot

Spring Rest

Métodos Post En Controladores Rest

Spring Boot

Spring Rest

Métodos Delete En Controladores Rest

Spring Boot

Spring Rest

Métodos Put Y Patch En Controladores Rest

Spring Boot

Spring Rest

Gestión De Errores Restcontrolleradvice

Spring Boot

Spring Rest

Creación De Entidades Jpa

Spring Boot

Spring Data Jpa

Asociaciones De Entidades Jpa

Spring Boot

Spring Data Jpa

Repositorios Spring Data

Spring Boot

Spring Data Jpa

Métodos Find En Repositorios

Spring Boot

Spring Data Jpa

Inserción De Datos

Spring Boot

Spring Data Jpa

Actualizar Datos De Base De Datos

Spring Boot

Spring Data Jpa

Borrar Datos De Base De Datos

Spring Boot

Spring Data Jpa

Consultas Jpql Con @Query En Spring Data Jpa

Spring Boot

Spring Data Jpa

Api Query By Example (Qbe)

Spring Boot

Spring Data Jpa

Api Specification

Spring Boot

Spring Data Jpa

Repositorios Reactivos

Spring Boot

Spring Data Jpa

Configuración Base De Datos Postgresql

Spring Boot

Spring Data Jpa

Configuración Base De Datos Mysql

Spring Boot

Spring Data Jpa

Introducción A Jpa Y Spring Data Jpa

Spring Boot

Spring Data Jpa

Configuración Base De Datos H2

Spring Boot

Spring Data Jpa

Testing Unitario De Componentes Y Servicios

Spring Boot

Testing Con Spring Test

Testing De Repositorios Spring Data Jpa

Spring Boot

Testing Con Spring Test

Testing Controladores Spring Mvc Con Thymeleaf

Spring Boot

Testing Con Spring Test

Testing Controladores Rest Con Json

Spring Boot

Testing Con Spring Test

Testing De Aplicaciones Reactivas Webflux

Spring Boot

Testing Con Spring Test

Testing De Seguridad Spring Security

Spring Boot

Testing Con Spring Test

Testing Con Apache Kafka

Spring Boot

Testing Con Spring Test

Introducción Al Testing

Spring Boot

Testing Con Spring Test

Introducción A Spring Security

Spring Boot

Seguridad Con Spring Security

Seguridad Basada En Formulario

Spring Boot

Seguridad Con Spring Security

Registro De Usuarios En Api Rest

Spring Boot

Seguridad Con Spring Security

Login De Usuarios En Api Rest

Spring Boot

Seguridad Con Spring Security

Validación Jwt En Api Rest

Spring Boot

Seguridad Con Spring Security

Autenticación Jwt Completa En Api Rest

Spring Boot

Seguridad Con Spring Security

Seguridad Jwt En Api Rest Reactiva Spring Webflux

Spring Boot

Seguridad Con Spring Security

Autenticación Y Autorización Con Anotaciones

Spring Boot

Seguridad Con Spring Security

Fundamentos De Autenticación Oauth

Spring Boot

Seguridad Con Spring Security

Autenticación Oauth Con Github

Spring Boot

Seguridad Con Spring Security

Testing Con Spring Security Test

Spring Boot

Seguridad Con Spring Security

Autenticación Oauth En Api Rest

Spring Boot

Seguridad Con Spring Security

Introducción A Spring Webflux

Spring Boot

Reactividad Webflux

Spring Data R2dbc

Spring Boot

Reactividad Webflux

Controlador Reactivo Basado En Anotaciones

Spring Boot

Reactividad Webflux

Controlador Reactivo Basado En Funciones

Spring Boot

Reactividad Webflux

Operadores Reactivos Básicos

Spring Boot

Reactividad Webflux

Operadores Reactivos Avanzados

Spring Boot

Reactividad Webflux

Cliente Reactivo Webclient

Spring Boot

Reactividad Webflux

Introducción E Instalación De Apache Kafka

Spring Boot

Mensajería Asíncrona

Crear Proyecto Con Apache Kafka

Spring Boot

Mensajería Asíncrona

Creación De Producers

Spring Boot

Mensajería Asíncrona

Creación De Consumers

Spring Boot

Mensajería Asíncrona

Kafka Streams En Spring Boot

Spring Boot

Mensajería Asíncrona

Integración Con Angular

Spring Boot

Integración Frontend

Integración Con React

Spring Boot

Integración Frontend

Integración Con Vue

Spring Boot

Integración Frontend

Accede GRATIS a SpringBoot y certifícate

Ejercicios de programación de SpringBoot

Evalúa tus conocimientos de esta lección Gestión de errores RestControllerAdvice con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender el uso básico de @ExceptionHandler para manejar excepciones en controladores individuales.
  • Aprender a centralizar el manejo de errores en toda la aplicación con @RestControllerAdvice.
  • Diseñar respuestas de error estructuradas y consistentes para APIs REST.
  • Implementar manejo de múltiples tipos de excepciones específicas y generales.
  • Configurar el alcance de @RestControllerAdvice para aplicar el manejo de errores a controladores específicos o paquetes.