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

Spring WebClient exchangeToMono: decode the response inside its callback

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

The response passed to exchangeToMono has a bounded ownership window; choose a body decoder or error path before returning.

Inspect status with the body in scope

A shipping service returns 200 with a label, 404 when a parcel is missing, and 503 during maintenance. exchangeToMono lets the caller choose a decoder by status. After the returned publisher completes, any unconsumed response body is released; code farther downstream cannot decode it later. Return a domain error for known 404 and a service error for 5xx. Status policy should be consistent across blocking and reactive clients.

Keep size and time bounded

A bodyToMono call can buffer a response into memory. Choose a maximum in-memory size and a connection/read timeout suited to the payload. A reactive chain does not make an unbounded body safe. For a stream, use Flux and preserve backpressure rather than collecting every item. The deadline budget still includes waiting for a pooled connection, remote work and decoding.

Exercise disposal and status

Return a 503 with a body, a malformed 200 body, and a response that never completes. Assert typed errors and that the connection pool remains usable after each case. The snippet shows a status branch; exact error mapping and codecs need a stub-server integration test.

Implementation sketch

Java
return shippingClient.get().uri("/labels/{parcelId}", parcelId)
    .exchangeToMono(response -> {
        if (response.statusCode().value() == 200) {
            return response.bodyToMono(ShippingLabel.class);
        }
        if (response.statusCode().value() == 404) {
            return Mono.error(new ParcelMissing(parcelId));
        }
        return response.createError();
    });

Cost and verification

Decoding a whole body retains up to the configured buffer limit. Leaking connections or allowing unlimited responses reduces throughput well before CPU is saturated.

Common Mistakes

  • Do not save ClientResponse for body decoding after exchangeToMono completes.
  • Do not treat every non-200 response as a missing parcel.
  • Do not collect an unbounded response stream into one List.

Read next

Spring HTTP service client: the interface is a contract, not a transport policy, Spring RestClient 503 response: count attempts before adding a retry, Spring HTTP client timeouts: bound the call inside the request deadline, Reactive HTTP service client: the proxy returns a publisher, not a completed call.

spring
spring-boot
web-apis
webclient-response-ownership
Storage details