An endpoint that fails the way an API should
Build POST /api/orders. It takes a customer id and a list of line items, and returns 201 with a Location header.
The interesting half is the failures. A missing customer id is 400. An unknown customer is 404. A duplicate idempotency key is 200 with the original order, not 201 and not 409. Every error body has the same shape, and none of them leaks a stack trace.
Example
- input
POST {"customerId": null, "items": []}output400 {"type":"validation","detail":"customerId must not be null","errors":[...]}One error shape for every failure, so a client can parse one thing.
Constraints
- No try/catch in the controller.
- Validation messages come from the constraint annotations, not from strings in the handler.
Hints
Hint 1
@Valid on the body plus @RestControllerAdvice for the handler.
Hint 2
MethodArgumentNotValidException is what @Valid throws — catch that, not Exception.
Hint 3
ProblemDetail is in Spring 6 and is already the shape you were about to invent.
Stuck? The lesson behind this problem: 🔗 Error handling
java
Tab indents · Escape first to tab out
Test cases
These are the specification. Run tests checks your answer against them.
| Case | Input | Expected |
|---|---|---|
| valid request | customerId=42, 2 items | 201 + Location: /api/orders/{id} |
| null customerId | customerId=null | 400, body.type = validation |
| unknown customer | customerId=999999 | 404 |
| replayed idempotency key | same key twice | 200 with the first order |