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
124 lines
3.9 KiB
Plaintext
124 lines
3.9 KiB
Plaintext
# Profile: advice
|
|
|
|
## RestClient GET /orders/999 -> ex.getResponseBodyAs(ProblemDetail.class)
|
|
{
|
|
"exception": "org.springframework.web.client.HttpClientErrorException$NotFound",
|
|
"status": 404,
|
|
"contentType": "application/problem+json",
|
|
"problemDetail": {
|
|
"type": "https://ankurm.com/problems/order-not-found",
|
|
"title": "Order not found",
|
|
"status": 404,
|
|
"detail": "Order 999 does not exist",
|
|
"instance": "/orders/999",
|
|
"properties": {
|
|
"orderId": 999
|
|
}
|
|
}
|
|
}
|
|
|
|
## RestClient GET /orders?limit=500 -> ex.getResponseBodyAs(ProblemDetail.class)
|
|
{
|
|
"exception": "org.springframework.web.client.HttpClientErrorException$BadRequest",
|
|
"status": 400,
|
|
"contentType": "application/problem+json",
|
|
"problemDetail": {
|
|
"type": "null",
|
|
"title": "Bad Request",
|
|
"status": 400,
|
|
"detail": "Validation failure",
|
|
"instance": "/orders",
|
|
"properties": {
|
|
"errors": [
|
|
{
|
|
"parameter": "limit",
|
|
"detail": "must be less than or equal to 100"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
|
|
## RestClient GET /orders/boom -> ex.getResponseBodyAs(ProblemDetail.class)
|
|
{
|
|
"exception": "org.springframework.web.client.HttpServerErrorException$InternalServerError",
|
|
"status": 500,
|
|
"contentType": "application/problem+json",
|
|
"problemDetail": {
|
|
"type": "null",
|
|
"title": "Internal Server Error",
|
|
"status": 500,
|
|
"detail": "An unexpected error occurred. Quote errorId when reporting it.",
|
|
"instance": "/orders/boom",
|
|
"properties": {
|
|
"errorId": "d09000a5-d6bf-438d-a1a0-527d7cd9d6b7"
|
|
}
|
|
}
|
|
}
|
|
|
|
# Profile: defaults
|
|
|
|
## RestClient GET /orders/999 -> ex.getResponseBodyAs(ProblemDetail.class)
|
|
{
|
|
"exception": "org.springframework.web.client.HttpServerErrorException$InternalServerError",
|
|
"status": 500,
|
|
"contentType": "application/json",
|
|
"problemDetail": {
|
|
"type": "null",
|
|
"title": "Internal Server Error",
|
|
"status": 500,
|
|
"detail": null,
|
|
"instance": "null",
|
|
"properties": {
|
|
"timestamp": "2026-09-11T17:05:01.408Z",
|
|
"error": "Internal Server Error",
|
|
"path": "/orders/999"
|
|
}
|
|
}
|
|
}
|
|
|
|
## RestClient GET /orders?limit=500 -> ex.getResponseBodyAs(ProblemDetail.class)
|
|
{
|
|
"exception": "org.springframework.web.client.HttpClientErrorException$BadRequest",
|
|
"status": 400,
|
|
"contentType": "application/json",
|
|
"problemDetail": {
|
|
"type": "null",
|
|
"title": "Bad Request",
|
|
"status": 400,
|
|
"detail": null,
|
|
"instance": "null",
|
|
"properties": {
|
|
"timestamp": "2026-09-11T17:05:01.620Z",
|
|
"error": "Bad Request",
|
|
"path": "/orders"
|
|
}
|
|
}
|
|
}
|
|
|
|
## RestClient GET /orders/boom -> ex.getResponseBodyAs(ProblemDetail.class)
|
|
{
|
|
"exception": "org.springframework.web.client.HttpServerErrorException$InternalServerError",
|
|
"status": 500,
|
|
"contentType": "application/json",
|
|
"problemDetail": {
|
|
"type": "null",
|
|
"title": "Internal Server Error",
|
|
"status": 500,
|
|
"detail": null,
|
|
"instance": "null",
|
|
"properties": {
|
|
"timestamp": "2026-09-11T17:05:01.660Z",
|
|
"error": "Internal Server Error",
|
|
"path": "/orders/boom"
|
|
}
|
|
}
|
|
}
|
|
|
|
# ProblemDetail with one extension member, serialised three ways
|
|
{
|
|
"Spring Boot's JsonMapper bean": "{\"detail\":\"demo\",\"status\":409,\"title\":\"Conflict\",\"sku\":\"SKU-2\"}",
|
|
"JsonMapper.builder().build()": "{\"detail\":\"demo\",\"instance\":null,\"properties\":{\"sku\":\"SKU-2\"},\"status\":409,\"title\":\"Conflict\",\"type\":null}",
|
|
"new JsonMapper()": "{\"detail\":\"demo\",\"instance\":null,\"properties\":{\"sku\":\"SKU-2\"},\"status\":409,\"title\":\"Conflict\",\"type\":null}"
|
|
}
|