Saltar a contenido

Excepciones personalizadas

Crear excepciones personalizadas permite expresar claramente las condiciones de error de la aplicación y tratarlas de forma específica en el ControllerAdvice.

¿Por qué usarlas?

  • Identificar semánticamente errores de dominio (por ejemplo FormNotFoundException).
  • Permitir mapeos HTTP específicos y mensajes claros para el cliente.
  • Facilitar pruebas unitarias (lanzar y capturar excepciones esperadas).

Ejemplos comunes

1) Excepción para recurso no encontrado

public class EntityNotFoundException extends RuntimeException {
  public EntityNotFoundException(String message) {
    super(message);
  }
}

2) Excepción para malas peticiones

public class BadRequestException extends RuntimeException {
  public BadRequestException(String message) {
    super(message);
  }
}

3) Conflicto / estado inválido

public class ConflictException extends RuntimeException {
  public ConflictException(String message) {
    super(message);
  }
}

Alternativa: @ResponseStatus

Si se prefiere, se puede anotar la excepción con @ResponseStatus para asociar un HttpStatus por defecto:

@ResponseStatus(HttpStatus.NOT_FOUND)
public class EntityNotFoundException extends RuntimeException {
  public EntityNotFoundException(String message) { super(message); }
}

Nota: aun usando @ResponseStatus, muchas aplicaciones prefieren centralizar respuestas en @ControllerAdvice para mantener el formato de error consistente.

Uso en Service

public FormDto get(UUID id) {
  Form form = repo.findById(id)
      .orElseThrow(() -> new EntityNotFoundException("Form con id " + id + " no existe"));
  return mapper.map(form, FormDto.class);
}

Buenas prácticas

  • Crear jerarquía si conviene (AppException extends RuntimeException, y subclases específicas).
  • No usar excepciones comprobadas (checked) para control de flujo en servicios; preferir RuntimeException.
  • Incluir mensajes claros y, si es necesario, metadata adicional (códigos internos, campos inválidos) en una estructura de error separada.

¿Quieres que añada una clase AppException base y ejemplos de pruebas unitarias que verifiquen que el ControllerAdvice devuelve los códigos esperados?