Vai al contenuto

Step 06 — Exception handling RFC 7807

Obiettivo: errori standardizzati, interoperabili, leggibili.

Perché RFC 7807

ProblemDetail è uno standard IETF per rappresentare errori HTTP. Vantaggi:

  • Stesso formato in tutti i client (SDK, frontend).
  • Estendibile: si possono aggiungere campi custom senza rompere la spec.
  • Spring 6+ lo supporta nativamente.

Esempio di errore

HTTP/1.1 404 Not Found
Content-Type: application/problem+json

{
  "type": "https://federicocalo.dev/errors/not-found",
  "title": "Resource not found",
  "status": 404,
  "detail": "Project with id '9b1f...' not found",
  "resourceType": "Project",
  "identifier": "9b1f...",
  "timestamp": "2026-05-20T18:25:43Z"
}

Implementazione

GlobalExceptionHandler.java (estratto)
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ProblemDetail handleNotFound(ResourceNotFoundException ex) {
        ProblemDetail p = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, ex.getMessage());
        p.setType(URI.create("https://federicocalo.dev/errors/not-found"));
        p.setTitle("Resource not found");
        p.setProperty("resourceType", ex.getResourceType());
        p.setProperty("identifier", ex.getIdentifier());
        p.setProperty("timestamp", Instant.now());
        return p;
    }
    // ... altri handler
}

Mappature

Eccezione HTTP type
ResourceNotFoundException 404 /errors/not-found
MethodArgumentNotValidException 400 /errors/validation
HttpMessageNotReadableException, MethodArgumentTypeMismatchException 400 /errors/bad-request
InvalidStateTransitionException, ProjectArchivedException, DataIntegrityViolationException 409 /errors/conflict
Tutte le altre Exception 500 /errors/internal (con log!)

Pitfall

Mai serializzare lo stack trace in produzione

Configura server.error.include-stacktrace: never nel profilo prod.

Custom exception per ogni cosa

Non serve. Tre/quattro tipi di eccezione di business + il fallback generico bastano.

Esercizi

  1. Aggiungi un handler per OptimisticLockingFailureException → HTTP 409 con messaggio dedicato.
  2. Includi un campo traceId nel ProblemDetail (preso da MDC).
  3. Discuti vantaggi/svantaggi di esporre type come URL canonico (RFC 7807) vs. codice opaco.

Riferimenti nel codice