Calling another service with RestClient
Make outbound HTTP calls with timeouts, status handling and a typed interface.
Open this lesson in the learning hubKey points
RestClientis the modern blocking client;RestTemplateis in maintenance andWebClientis reactive.- Build it once as a
@Beanwith a base URL and shared headers, then inject it. Never build one per call. - Always set connect and read timeouts. Unset means a thread waits forever on a peer that never answers.
- A 4xx or 5xx throws by default. Use
onStatusto translate it into an exception of your own. - An
@HttpExchangeinterface gives you a typed client with no implementation to write or test. - Log the correlation id on the way out so one request can be followed across every service.
Example
@Configuration
class RatesClientConfig {
@Bean
RestClient ratesRestClient(RestClient.Builder builder) {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(Duration.ofSeconds(2)); // never leave these unset
factory.setReadTimeout(Duration.ofSeconds(3));
return builder
.baseUrl("https://rates.example.com")
.requestFactory(factory)
.defaultStatusHandler(HttpStatusCode::isError, (req, res) -> {
throw new RateUnavailableException(res.getStatusCode());
})
.build();
}
}
// Boot 3.4+ can set the same timeouts for every client from properties instead:
// spring.http.client.connect-timeout: 2s
// spring.http.client.read-timeout: 3s
// A typed client: declare the calls, Spring generates the implementation.
@HttpExchange("/rates")
interface RatesApi {
@GetExchange("/{currency}")
Rate byCurrency(@PathVariable String currency);
}
Every outbound call needs a timeout and an owner for its failure - the default is to wait forever.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Spring Boot course, and every lesson in it is listed on the Spring Boot contents page.