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; preferirRuntimeException. - 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?