RestClient vs. WebClient vs RestTemplate
Using the suitable library to call REST API in Spring Boot
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 these three 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 (you can find more description and the GitHub repository link at the last section).
Calling the echo service using RestTemplate
Using the RestTemplate
in Spring Boot is very straightforward. We can create it from the RestTemplateBuilder
either inside of 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, in our example, we use it directly in a RestController
(for the sake of simplicity, we keep the example simple, it is not a good idea to use any of these three libraries directly in the controller, it is better to define an EchoClient
and use them there):
@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!
Incredibly, 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 cool feature in Spring Framework allows us to define an HTTP service as an interface. For example, the echo-service
interface will be similar to this:
@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 and create a bean from the EchoService interface:
@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. Knowing about them will help us to make the best of it and also allow us to compare it with two other libraries in the following:
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?
As we discussed in the previous sections, RestTemplate
is a simple and flexible library to call HTTP services, but it was synchronous and blocking, and it was the main reason that The Spring non-blocking stack (WebFlux) introduced a new and modern and fully non-block and Asynchronous HTTP client library with functional and fluent API called WebClient
.
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.
The WebClient
API is much clearer than the RestTemplate
, and they are equivalent to HTTP methods.
Calling the echo service using WebClient
Very similar to RestTemplate
, 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 and use it:
@GetMapping("/echo/{message}")
public Mono<Echo> echo(@PathVariable String message) {
return webClient
.get()
.uri("/echo/" + message)
.retrieve()
.bodyToMono(Echo.class);
}
As I said before, 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 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();
}
In this article, I describe in detail that, technically, there is not any problem with using WebClient in the Web MVC stack and calling the block() operation:
When we call the
block()
method on theWebClient
return type, it will block the calling thread from the WebMVC thread pool, and as a result, the WebClient can continue to call external services or APIs asynchronous and non-blocking.
In this way, you can have all the benefits of the WebClient
API and its infrastructure (like non-blocking, performance and streaming support, and more), but the cost is to add extra library dependency to your Web MVC project (WebFlux and Project Reactor).
Defining declarative HTTP interface using WebClient
Like the RestTemplate
, WebClient
also supports defining an HTTP service as a Java interface using the @HttpExchange
annotation. Implementing the interface and its methods are similar to the RestTemplate
, the only difference is when we want to create a proxy to perform requests and attach it to the WebClient
instance and create a bean from the EchoService interface:
@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?
Why do we need another HTTP client in Spring Framework when we have RestTemplate
and WebClient
?
Now, by knowing the story behind the RestTemplate
and WebClient
, you can understand why we need another HTTP client library in Spring Framework.
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
Again, very similar to RestTemplate
and WebClient
, we can create a bean using the RestClient.builder()
method:
@Bean
public RestClient restClient() {
return RestClient.builder()
.baseUrl("http://localhost:8080")
.build();
}
Then inject the RestClient
bean into the controller and use it:
@GetMapping("/echo/{message}")
public Echo echo(@PathVariable String message) {
return restClient
.get()
.uri("/echo/" + message)
.retrieve()
.body(Echo.class);
}
As you can see in this example, the RestClient
API is almost identical to the WebClient
API, except we don't need to have the WebFlux library in our dependency and also call the block()
method!
If you don't want to have the Spring WebFlux dependency in your Spring MVC project, RestClient
is a good choice, and keep the codes in your project unmixed.
Migrate from RestTemplate to RestClient
The Spring Framework team recommends using RestClient
for the new Spring MVC project and also provides guidelines to migrate from RestTemlate
to RestClient
.
Read this part of Spring Framework reference documentation to learn more about migrating from RestTemplate to RestClient.
Defining declarative HTTP interface using RestClient
RestClient
can be used for declarative HTTP interfaces similar to RestTemplate
and WebClient
. It can be used with @GetExchange
and @HttpExchange
annotations to define our HTTP client in a declarative approach.
Implementing the interface and its methods are similar to the RestTemplate
and WebClient
, the only difference is when we want to create a proxy to perform requests and attach it to the RestClient
instance and create a bean from the EchoService
interface:
@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);
}
Final comparison and advice
RestClient
, WebClient
, and RestTemplate
are all wrappers for a networking library that allows you to perform HTTP requests. The most important differences are in the programming paradigms and the API design approaches. In the following table, you can see the comparison between the three libraries:
As you can see in the table above, RestClient
is a game changer. If you are looking for an HTTP client in a Spring MVC stack, we no longer need to use WebClient
to have a modern and functional API. So, RestClient
is the best choice for us if we are starting a greenfield project based on the Spring MVC stack. For existing projects based on the Spring MVC stack that have used RestTemplate
, It can be a good option to replace it with RestClient
because the RestTemplate
is now in maintenance mode, and it will not be updated anymore. For blocking Spring projects that use WebClient
, because of its functional and modern API, it is time to consider using RestClient
because migrating from WebClient
to RestClient
for the Web MVC stack will not take long, and it will be worth the effort.
Of course, WebClient is still the best and the only official option for the Spring WebFlux projects.
Observe HTTP client calls using Digma
One of the advantages of using Digma is the ability to observe HTTP client calls between our services or even external services during the development time. Digma provides us with all activities, metrics, and traces inside the IDE when we test services on our local machine.
Sample application services
For this article, I will provide three services. The echo-service
service provides a simple echo REST API for two other caller services. The first caller service is called reactive-caller
, which uses WebFlux stack and WebClient
to call echo REST API, and the second caller service is called blocking-caller
, which uses Web MVC stack and all 3 HTTP client libraries (RestClient, WebClient, and RestTemplate) to call echo REST API.
The code for these services can be found in this GitHub repository.
Observe HTTP Client's Activities and Traces locally using Digma
After setting up the Digma plugin for IntelliJ IDEA, You can clone the repository and run the services locally. For example, you can call the echo REST API using the RestTemplate library in the blocking-caller service as follows (using HTTPie):
http :8081/rt/echo/hello
Now, in the Digma view, in the assets list, you can see that Digma detects one HTTP client:
If you click on the HTTP client section, you can see more details about this client call, like performance or to which service it belongs, and more:
To observe recent calls, traces, and also metrics, you need to open the Observability view:
To see the trace and metrics, click on the trace icon in the Actions column:
As you saw, Digma allows us to observe the HTTP client’s activities and traces locally inside the IntelliJ IDEA.
Final Thoughts
By introducing the RestClient
, Spring developers now have a modern alternative to RestTemplate
with functional and fluent API similar to WebClient
but suitable for synchronous programming models in the Spring WebMVC stack. Although RestTemplate
is being deprecated, it is still in maintenance mode and will receive updates as needed. However, it is highly recommended to use RestClient
instead of RestTemplate
for new projects or even migrate to RestClient
for existing projects.
You can follow me for upcoming stories:
Read my short technical posts on Twitter.