REST API und Fehlervertrag
REST-Schnittstellen mit stabilem Fehlervertrag, Problem Details und Tests entwerfen.
Lab-Bausteine
Die Seite ist als Arbeitsblatt aufgebaut: erst verstehen, dann Aufgabe bearbeiten, dann Lösungsskizze und Checkliste prüfen.
Lernziel
Du entwirfst eine REST-API, die Fehler nicht zufällig als Text zurückgibt, sondern einen stabilen, dokumentierten Fehlervertrag besitzt.
Ausgangslage
Ein Order-Service liefert bei Validierungsfehlern unterschiedliche JSON-Strukturen. Frontend, Tests und Support können Fehler dadurch nicht zuverlässig auswerten.
Aufgabe
- Definiere ein einheitliches Problem-Details-Modell.
- Mappe Domain-Fehler auf HTTP-Statuscodes.
- Dokumentiere Beispielantworten.
- Erstelle einen Test für einen typischen Fehlerfall.
Lösungsskizze
- Domain-Fehler bleiben fachlich.
- ControllerAdvice mappt technische HTTP-Antworten.
- Fehlercodes sind stabil und maschinenlesbar.
- Tests prüfen Status, Code und Struktur.
Typische Fehler
- Stacktrace im API-Response.
- HTTP 200 mit Fehlerobjekt.
- Jeder Controller baut Fehlerantworten selbst.
- Fehlercodes ändern sich ohne Versionierung.
Prüfcheckliste
- Problem-Details-Struktur ist dokumentiert.
- Mindestens ein Fehlerfall ist getestet.
- Fachlicher Fehlercode ist stabil.
- Kein interner Klassenname im Response.
Codebeispiel
Öffne diesen Abschnitt nur, wenn du die technische Umsetzung sehen möchtest. Der Codeblock ist farbig hervorgehoben und horizontal scrollbar.
package com.acme.order.adapter.rest;
import java.time.Instant;
import java.util.Map;
public record ProblemDetails(
String type,
String title,
int status,
String detail,
String errorCode,
Instant timestamp,
Map<String, Object> extensions
) {}
package com.acme.order.adapter.rest;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.time.Instant;
import java.util.Map;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(OrderAlreadyConfirmedException.class)
ProblemDetails alreadyConfirmed(OrderAlreadyConfirmedException ex) {
return new ProblemDetails(
"https://errors.acme.local/order/already-confirmed",
"Order already confirmed",
HttpStatus.CONFLICT.value(),
ex.getMessage(),
"ORDER_ALREADY_CONFIRMED",
Instant.now(),
Map.of("retryable", false)
);
}
}
{
"type": "https://errors.acme.local/order/already-confirmed",
"title": "Order already confirmed",
"status": 409,
"detail": "Order 4711 is already confirmed",
"errorCode": "ORDER_ALREADY_CONFIRMED",
"extensions": { "retryable": false }
}
Deep-Learning-Bezug
Dieses Lab gehört zu Stufe 6 – Praxislabor und Capstone. Die Stufe erklärt, warum das Lab in der Lernentwicklung genau an dieser Stelle steht.