An @HttpExchange interface declares remote requests; its RestClient adapter still needs a base URL, timeouts and error policy.
Spring HTTP service client: the interface is a contract, not a transport policy
Keep the interface narrow
A pricing client can expose one quote lookup through @GetExchange and map the path parameter explicitly. HttpServiceProxyFactory creates a typed proxy backed by a RestClient adapter. That removes handwritten request assembly, but the underlying RestClient still decides connection and read timeouts, authentication, status handling and observability. The request factory is where much of the actual I/O behavior is chosen.
Define failure as part of the call
A 404 may mean a product is absent; a 503 may mean the pricing service is unavailable. Do not collapse both into null. Convert known status responses into typed application failures and pass an end-to-end deadline from the caller. Timeout budgeting and status retry rules should be reviewed beside the interface, even though they live in separate configuration.
Test the HTTP wire
Point the proxy at a stub server and verify the URL, encoded path variable, required headers and result mapping. Return a malformed body and a 503 in separate cases. A mocked Java interface call proves neither serialization nor error translation. The code is an integration sketch; add the project's auth interceptor and error handler before production use.
Implementation sketch
@HttpExchange("/v1/prices")
interface PricingClient {
@GetExchange("/{sku}")
PriceQuote quote(@PathVariable String sku);
}
RestClient restClient = RestClient.builder()
.baseUrl("https://pricing.internal")
.build();
PricingClient client = HttpServiceProxyFactory
.builderFor(RestClientAdapter.create(restClient)).build()
.createClient(PricingClient.class);Cost and verification
The proxy adds small dispatch overhead; network latency, connection pooling, body size and retries dominate. An unbounded read can hold a request thread and pooled connection.
Common Mistakes
- Do not mistake a typed interface for configured timeouts or status mapping.
- Do not test only the Java method signature and call it an HTTP integration test.
- Do not hide remote 404 and 503 responses behind the same null result.
Read next
Spring RestClient request factories: pin the transport you test, Spring HTTP client timeouts: bound the call inside the request deadline, Spring RestClient 503 response: count attempts before adding a retry, Spring HTTP service client retries: an interface cannot prove the server did not commit.
Related boundary
Spring HTTP service groups: configure one host policy for several interfaces
