Add problem-details: global exception handling with RFC 9457
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
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
# Profile: advice,errors (spring-boot 4.1.1, spring-framework 7.0.9)
|
||||
|
||||
## domain exception (OrderNotFoundException)
|
||||
$ curl -X GET /orders/999
|
||||
HTTP 404 Content-Type: application/problem+json
|
||||
{"detail":"Order 999 does not exist","instance":"/orders/999","status":404,"title":"Order not found","type":"https://ankurm.com/problems/order-not-found","orderId":999}
|
||||
|
||||
## type mismatch (/orders/abc)
|
||||
$ curl -X GET /orders/abc
|
||||
HTTP 400 Content-Type: application/problem+json
|
||||
{"detail":"Failed to convert 'id' with value: 'abc'","instance":"/orders/abc","status":400,"title":"Bad Request"}
|
||||
|
||||
## invalid body (@Valid)
|
||||
$ curl -X POST /orders -d '{"sku":"","quantity":0,"customerEmail":"nope"}'
|
||||
HTTP 400 Content-Type: application/problem+json
|
||||
{"detail":"The request body has 3 invalid field(s)","instance":"/orders","status":400,"title":"Bad Request","errors":[{"detail":"must not be blank","pointer":"#/sku"},{"detail":"must be a well-formed email address","pointer":"#/customerEmail"},{"detail":"must be greater than or equal to 1","pointer":"#/quantity"}]}
|
||||
|
||||
## invalid @RequestParam (@Max)
|
||||
$ curl -X GET /orders?limit=500
|
||||
HTTP 400 Content-Type: application/problem+json
|
||||
{"detail":"Validation failure","instance":"/orders","status":400,"title":"Bad Request","errors":[{"detail":"must be less than or equal to 100","parameter":"limit"}]}
|
||||
|
||||
## ErrorResponseException (OutOfStock)
|
||||
$ curl -X POST /orders -d '{"sku":"SKU-2","quantity":3,"customerEmail":"[email protected]"}'
|
||||
HTTP 409 Content-Type: application/problem+json
|
||||
{"detail":"Only 0 unit(s) of SKU-2 are available.","instance":"/orders","status":409,"title":"Out of stock","type":"https://ankurm.com/problems/out-of-stock","sku":"SKU-2","available":0}
|
||||
|
||||
## ResponseStatusException
|
||||
$ curl -X GET /orders/legacy/7
|
||||
HTTP 410 Content-Type: application/problem+json
|
||||
{"detail":"Legacy order ids were retired in 2024","instance":"/orders/legacy/7","status":410,"title":"Gone"}
|
||||
|
||||
## unknown path
|
||||
$ curl -X GET /no-such-thing
|
||||
HTTP 404 Content-Type: application/problem+json
|
||||
{"detail":"No static resource no-such-thing.","instance":"/no-such-thing","status":404,"title":"Not Found"}
|
||||
|
||||
## wrong HTTP method
|
||||
$ curl -X DELETE /orders/1
|
||||
HTTP 405 Content-Type: application/problem+json
|
||||
{"detail":"Method 'DELETE' is not supported.","instance":"/orders/1","status":405,"title":"Method Not Allowed"}
|
||||
|
||||
## malformed JSON
|
||||
$ curl -X POST /orders -d '{"sku":'
|
||||
HTTP 400 Content-Type: application/problem+json
|
||||
{"detail":"Failed to read request","instance":"/orders","status":400,"title":"Bad Request"}
|
||||
|
||||
## unexpected exception
|
||||
$ curl -X GET /orders/boom
|
||||
HTTP 500 Content-Type: application/problem+json
|
||||
{"detail":"An unexpected error occurred. Quote errorId when reporting it.","instance":"/orders/boom","status":500,"title":"Internal Server Error","errorId":"a3838ab0-afd2-4bbd-85b5-15e9a309c1f8"}
|
||||
|
||||
## exception in a servlet filter
|
||||
$ curl -X GET /orders/1 [X-Tenant: BAD!]
|
||||
HTTP 500 Content-Type: application/problem+json
|
||||
{"detail":"An unexpected error occurred.","instance":"/orders/1","status":500,"title":"Internal Server Error"}
|
||||
|
||||
## 401 no credentials
|
||||
$ curl -X GET /admin/orders
|
||||
HTTP 401 Content-Type: application/problem+json
|
||||
{"detail":"Authentication is required to access this resource","instance":"/admin/orders","status":401,"title":"Unauthorized","type":"https://ankurm.com/problems/authentication-required","scheme":"Basic"}
|
||||
|
||||
## 403 wrong role
|
||||
$ curl -X GET /admin/orders [AUTH:user:user]
|
||||
HTTP 403 Content-Type: application/problem+json
|
||||
{"detail":"Your credentials do not grant access to this resource","instance":"/admin/orders","status":403,"title":"Forbidden","type":"https://ankurm.com/problems/access-denied"}
|
||||
|
||||
Reference in New Issue
Block a user