Files
spring-boot-demo/problem-details/docs/08-clients.md
T
asmhatreandClaude Opus 5 926250e1a9 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
2026-09-11 17:12:22 +00:00

1.6 KiB

8. The client side: decoding problems with RestClient

← 7. Silent 500s · Index

RestClient's default status handler throws HttpClientErrorException / HttpServerErrorException; getResponseBodyAs(ProblemDetail.class) decodes the body with the client's converters. /diag/decode reports what came back (client-decoding.txt).

What works

Extension members land in getProperties() - orderId, the errors list, errorId. The mixin works in both directions.

Two things to code defensively against

getType() is null when the server omitted it, which Spring Framework 7 servers do for every framework error (chapter 4). Treat null as about:blank.

Decoding succeeds on a body that is not a problem at all. Against the defaults profile the server sends Boot's application/json error, and it still decodes:

    "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"
        }
    }

Unknown members go into properties, so any JSON object "is" a ProblemDetail. Check the Content-Type is application/problem+json before believing you have one.