In this article, I will compare the RestClient, WebClient, and RestTemplate libraries for calling REST APIs in Spring Boot applications. I will also provide recommendations on which one is the right choice for different situations.
I recently wrote an article about how to use WebClient synchronously in the Spring Web MVC stack and described if it is a good idea to call the WebClient block() operation in this case.
But after releasing Spring Boot 3.2, the story of calling REST APIs from a Spring Boot application has become even more complicated. By releasing Spring Boot 3.2, another new library has entered the game in this area: the RestClient library.
In this article, I will compare the three libraries: RestClient, WebClient, and RestTemplate libraries for calling REST APIs in Spring Boot applications. I will also give some recommendations of which one is the right choice for different situations.
What does RestTemplate lack from its competitors?
Before the emergence of the WebFlux stack, RestTemplate was the best choice to have a full-fledged synchronous HTTP client library for the Spring Framework since version 3.0. Before starting to know why we need to have another HTTP client library in Spring Framework, let’s get to know RestTemplate and its pros and cons.
In our example in this article, we have a hypothetical service called echo-service that provides echo REST API (using HTTP GET), and we want to call that API using these three libraries that Spring Boot provides us to see differences and similarities.
Calling the echo service using RestTemplate
Using the RestTemplate in Spring Boot is very straightforward. We can create it from the RestTemplateBuilder either inside our controller or service:
private final RestTemplate restTemplate;
public RestTemplateController(RestTemplateBuilder builder) {
this.restTemplate = builder.build();
}
Or in a separate configuration class:
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
Now we can use the RestTemplate bean.
@GetMapping("/echo/{message}")
public Echo echo(@PathVariable String message) {
return restTemplate.getForObject("http://localhost:8080/echo/" + message, Echo.class);
}
RestTemplate provides several groups of overloaded methods based on the Spring template pattern:
- XXXForObject (most straightforward)
- XXXForEntity (represent more information)
- exchange (more generalized with extra flexibility)
- execute (most generalized with full control)
RestTemplate supports the declarative HTTP interface!
Many Spring developers do not know that similar to WebClient and RestClient, the RestTemplate also supports defining an HTTP service as a Java interface using the @HttpExchange annotation. This feature in Spring Framework allows us to define an HTTP service as an interface.
@HttpExchange(url = "/echo")
public interface EchoService {
@GetExchange("/{message}")
Echo echo(@PathVariable String message);
}
Now, we should create a proxy to perform requests through a RestTemplate instance:
@Bean
public EchoService echoService() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory("http://localhost:8080"));
RestTemplateAdapter adapter = RestTemplateAdapter.create(restTemplate);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
return factory.createClient(EchoService.class);
}
RestTemplate pros and cons
Like any library, RestTemplate has its pros and cons:
Pros:
- Switchable underlying HTTP client library
- Supports declarative HTTP interface
- Highly configurable
- Usable in older versions of Spring Framework
Cons:
- Having multiple overloads of a method makes this library hard to use
- The classic Spring template pattern is old-fashioned
- Not suitable for non-blocking environments (for example, WebFlux)
What did WebClient bring us new?
WebClient was introduced and designed specifically for the WebFlux stack. Unlike RestTemplate, it was not based on an old-fashioned template-based API and followed the modern functional and fluent style API.
Calling the echo service using WebClient
First, we need to create a bean using the WebClient.Builder class:
@Configuration
public class WebClientConfig {
@Bean
public WebClient webClient(WebClient.Builder builder) {
return builder
.baseUrl("http://localhost:8080")
.build();
}
}
Then inject the WebClient bean into the controller:
@GetMapping("/echo/{message}")
public Mono<Echo> echo(@PathVariable String message) {
return webClient
.get()
.uri("/echo/" + message)
.retrieve()
.bodyToMono(Echo.class);
}
WebClient was designed for WebFlux, and the API and threading model differs from the RestTemplate. WebClient was introduced in Spring Framework 5, although it was designed for Spring WebFlux but is heavily used in the blocking stack (Web MVC) by developers by calling the block() operation from WebClient:
@GetMapping("/echo/{message}")
public Echo echo(@PathVariable String message) {
return webClient
.get()
.uri("/echo/" + message)
.retrieve()
.bodyToMono(Echo.class)
.block();
}
Defining declarative HTTP interface using WebClient
Like the RestTemplate, WebClient also supports defining an HTTP service as a Java interface using the @HttpExchange annotation:
@Bean("wc")
public EchoService echoService() {
WebClient webClient = WebClient.builder().baseUrl("http://localhost:8080").build();
WebClientAdapter adapter = WebClientAdapter.create(webClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
return factory.createClient(EchoService.class);
}
Yet another HTTP client library for Spring Framework. Why?
RestClient was introduced in Spring Framework 6.1 and has the same infrastructure and abstraction as RestTemplate, which means it is blocking, but it has a fluent API similar to WebClient.
Calling the echo service using RestClient
@Bean
public RestClient restClient() {
return RestClient.builder()
.baseUrl("http://localhost:8080")
.build();
}
Then inject the RestClient bean into the controller:
@GetMapping("/echo/{message}")
public Echo echo(@PathVariable String message) {
return restClient
.get()
.uri("/echo/" + message)
.retrieve()
.body(Echo.class);
}
Migrate from RestTemplate to RestClient
The Spring Framework team recommends using RestClient for new Spring MVC projects and provides guidelines to migrate from RestTemplate to RestClient.
Defining declarative HTTP interface using RestClient
RestClient can also be used for declarative HTTP interfaces similar to RestTemplate and WebClient.
@Bean("rc")
public EchoService echoService() {
RestClient restClient = RestClient.builder().baseUrl("http://localhost:8080/").build();
RestClientAdapter adapter = RestClientAdapter.create(restClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
return factory.createClient(EchoService.class);
}
HTTP Client Observability
Observability is an important aspect of every library and framework. If at some point in time, worrying about visibility and observability was the purview of SREs and DevOps teams, today, every developer must ensure the code can be tracked and analyzed.
Three main reasons to care about this as developers are:
- Clarity about code execution paths and flows makes us more productive.
- Proper analysis helps detect issues such as timeouts and performance problems.
- Observability is crucial for microservices communication.
Final comparison and advice
RestClient, WebClient, and RestTemplate are all wrappers for a networking library that allows you to perform HTTP requests. The important differences are in the programming paradigms and API design approaches.
Summary of Recommendations
- For new Spring MVC projects, it is best to use RestClient.
- Existing projects using RestTemplate should consider migrating to RestClient since RestTemplate is in maintenance mode.
- WebClient remains the recommendation for Spring WebFlux projects.