Companion code for "Global Exception Handling with ProblemDetail (RFC 9457) in Spring Boot 4". Thirteen failures under five handling setups (Boot defaults, the Boot flag, a ResponseEntityExceptionHandler advice, advice plus an ErrorController, a catch-all ordered first), validation errors, i18n, content negotiation, Security's 401/403, silent 500s and decoding on the client. 16 tests pin the behaviour. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01C3TETMrqVUWeFkNtz3Jbo3
68 lines
2.7 KiB
Plaintext
68 lines
2.7 KiB
Plaintext
# Profile: defaults (spring-boot 4.1.1, spring-framework 7.0.9)
|
|
|
|
## domain exception (OrderNotFoundException)
|
|
$ curl -X GET /orders/999
|
|
HTTP 500 Content-Type: application/json
|
|
{"timestamp":"2026-09-11T17:03:04.029Z","status":500,"error":"Internal Server Error","path":"/orders/999"}
|
|
|
|
## type mismatch (/orders/abc)
|
|
$ curl -X GET /orders/abc
|
|
HTTP 400 Content-Type: application/json
|
|
{"timestamp":"2026-09-11T17:03:04.063Z","status":400,"error":"Bad Request","path":"/orders/abc"}
|
|
|
|
## invalid body (@Valid)
|
|
$ curl -X POST /orders -d '{"sku":"","quantity":0,"customerEmail":"nope"}'
|
|
HTTP 400 Content-Type: application/json
|
|
{"timestamp":"2026-09-11T17:03:04.250Z","status":400,"error":"Bad Request","path":"/orders"}
|
|
|
|
## invalid @RequestParam (@Max)
|
|
$ curl -X GET /orders?limit=500
|
|
HTTP 400 Content-Type: application/json
|
|
{"timestamp":"2026-09-11T17:03:04.301Z","status":400,"error":"Bad Request","path":"/orders"}
|
|
|
|
## ErrorResponseException (OutOfStock)
|
|
$ curl -X POST /orders -d '{"sku":"SKU-2","quantity":3,"customerEmail":"[email protected]"}'
|
|
HTTP 409 Content-Type: application/json
|
|
{"timestamp":"2026-09-11T17:03:04.354Z","status":409,"error":"Conflict","path":"/orders"}
|
|
|
|
## ResponseStatusException
|
|
$ curl -X GET /orders/legacy/7
|
|
HTTP 410 Content-Type: application/json
|
|
{"timestamp":"2026-09-11T17:03:04.383Z","status":410,"error":"Gone","path":"/orders/legacy/7"}
|
|
|
|
## unknown path
|
|
$ curl -X GET /no-such-thing
|
|
HTTP 404 Content-Type: application/json
|
|
{"timestamp":"2026-09-11T17:03:04.412Z","status":404,"error":"Not Found","path":"/no-such-thing"}
|
|
|
|
## wrong HTTP method
|
|
$ curl -X DELETE /orders/1
|
|
HTTP 405 Content-Type: application/json
|
|
{"timestamp":"2026-09-11T17:03:04.437Z","status":405,"error":"Method Not Allowed","path":"/orders/1"}
|
|
|
|
## malformed JSON
|
|
$ curl -X POST /orders -d '{"sku":'
|
|
HTTP 400 Content-Type: application/json
|
|
{"timestamp":"2026-09-11T17:03:04.462Z","status":400,"error":"Bad Request","path":"/orders"}
|
|
|
|
## unexpected exception
|
|
$ curl -X GET /orders/boom
|
|
HTTP 500 Content-Type: application/json
|
|
{"timestamp":"2026-09-11T17:03:04.487Z","status":500,"error":"Internal Server Error","path":"/orders/boom"}
|
|
|
|
## exception in a servlet filter
|
|
$ curl -X GET /orders/1 [X-Tenant: BAD!]
|
|
HTTP 500 Content-Type: application/json
|
|
{"timestamp":"2026-09-11T17:03:04.509Z","status":500,"error":"Internal Server Error","path":"/orders/1"}
|
|
|
|
## 401 no credentials
|
|
$ curl -X GET /admin/orders
|
|
HTTP 401 Content-Type: application/json
|
|
{"timestamp":"2026-09-11T17:03:04.540Z","status":401,"error":"Unauthorized","path":"/admin/orders"}
|
|
|
|
## 403 wrong role
|
|
$ curl -X GET /admin/orders [AUTH:user:user]
|
|
HTTP 403 Content-Type: application/json
|
|
{"timestamp":"2026-09-11T17:03:04.735Z","status":403,"error":"Forbidden","path":"/admin/orders"}
|
|
|