Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring WebClient status-specific decoding: consume one branch and close the rest

Last updated: 5 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

Use exchangeToMono when success, absence and failure have different body contracts, and keep decoding inside the exchange callback.

The status chooses the body type

A partner returns a receipt quote on success, an empty body for not-found and a problem document for other failures. retrieve is concise for a uniform success body, but exchangeToMono lets the client choose decoding based on status. The response body must be consumed or released within that exchange lifecycle; returning ClientResponse for later decoding breaks ownership. Response ownership covers the connection consequences of this boundary.

Preserve distinct business outcomes

A 404 for an optional quote can become Mono.empty, while a 401 or 503 must stay a failure. Do not turn every non-2xx into empty; that masks revoked credentials and partner outages as missing business data. The example delegates other failures to createError so the error body is handled by the client API. Add a separate bounded decoder when the partner's problem response needs structured fields, and keep codec memory limits in force for that error body too.

Test the release path

Feed a success body, an empty 404 and a failing response with a body through a test server. Reuse the connection after each path, and cancel a request while it is decoding to expose leaks. A downstream retry should be limited to operations that are safe to replay; decoding an error does not make a POST idempotent. Uncertain commit explains why a transport failure after a write needs a separate business key.

Implementation contract

Java
Mono<ReceiptQuote> quote(String receiptId) {
    return partnerClient.get()
        .uri("/quotes/{receiptId}", receiptId)
        .exchangeToMono(response -> {
            if (response.statusCode().is2xxSuccessful()) {
                return response.bodyToMono(ReceiptQuote.class);
            }
            if (response.statusCode().value() == 404) {
                return Mono.empty();
            }
            return response.createError();
        });
}

Cost and verification

Status inspection is constant work. Body decoding and error buffering dominate memory and latency; a missing-result branch saves object allocation, but retries or repeated misses can still produce high request volume.

Common Mistakes

  • Do not return ClientResponse for decoding after exchangeToMono completes.
  • Do not map authentication and service failures to the same empty result as a true 404.
  • Do not retry a write merely because its response body could not be decoded.

Read next

Spring WebClient exchangeToMono: decode the response inside its callback, Spring WebFlux codec memory budget: distinguish aggregation from streaming, Spring HTTP timeout after POST: the write may already exist, Spring RestClient 503 response: count attempts before adding a retry, Spring Boot tracing across RestClient: construct the client from Boot's builder.

Related delivery contract

Spring WebClient request audit: log route identity without payload leakage.

Related delivery contract

Spring WebClient attributes versus Reactor Context: choose the right request scope.

spring
spring-boot
web-apis
webclient-status-specific-decoding
Storage details