REST Client and API Calls
Introduction
Your Spring Boot app often calls other HTTP APIs—payment gateways, SMS providers, or microservices. Spring Boot 3 recommends RestClient (modern) and WebClient (reactive). This chapter configures timeouts, sends GET/POST with JSON, handles errors, and compares choices for typical MVC apps.
Prerequisites
RestClient (Servlet Stack Default Choice)
Boot 3.2+ RestClient builder bean optional; create explicitly:
Code explanation:
connectTimeout— TCP connect limitreadTimeout— wait for response body
GET Request
DTO:
public record PostDto(Long id, String title, String body) {}Service:
Public test API: https://jsonplaceholder.typicode.com/posts/1
Adjust baseUrl for demos:
return builder.baseUrl("https://jsonplaceholder.typicode.com").build();POST With JSON Body
public record CreatePostRequest(String title, String body) {}
public PostDto createPost(CreatePostRequest request) {
return restClient.post()
.uri("/posts")
.body(request)
.retrieve()
.body(PostDto.class);
}Error Handling
import org.springframework.web.client.RestClientResponseException;
public PostDto fetchPostSafe(Long id) {
try {
return restClient.get()
.uri("/posts/{id}", id)
.retrieve()
.body(PostDto.class);
} catch (RestClientResponseException ex) {
throw new IllegalStateException("Upstream error: " + ex.getStatusCode(), ex);
}
}Fluent handler:
return restClient.get()
.uri("/posts/{id}", id)
.retrieve()
.onStatus(status -> status.is4xxClientError(), (req, res) -> {
throw new IllegalArgumentException("Not found: " + id);
})
.body(PostDto.class);Map upstream errors to your global exception handler.
RestTemplate (Legacy)
RestTemplate still works but is in maintenance mode—prefer RestClient for new servlet code:
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}WebClient (Reactive / Fluent)
Add dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>Use WebClient when app is reactive end-to-end; blocking RestClient is simpler in classic MVC.
Configuration Externalization
app:
upstream:
base-url: https://api.example.com
connect-timeout-ms: 3000
read-timeout-ms: 5000Bind with @ConfigurationProperties—chapter 14.
Resilience (Awareness)
Production calls add retries, circuit breakers (Resilience4j), and bulkheads when upstream fails often—not covered in depth here.
FAQ
RestClient bean not found?
Add spring-boot-starter-web; inject RestClient.Builder or define @Bean.
SSL certificate errors?
Import trust cert or configure SSL context—never disable verify in prod.
Pass auth header?
.defaultHeader("Authorization", "Bearer " + token)Or per request .header("Authorization", ...).
Connection pool?
RestClient with HttpComponentsClientHttpRequestFactory or JettyClientHttpRequestFactory for pooling under high load.
Timeouts ignored?
Confirm request factory attached to builder.
Log requests?
RestClient interceptors or Spring ClientHttpRequestInterceptor.