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 (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 th

 @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 the WebClient 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);
   }

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.  HTTP clients are especially important because they propagate the observability context between microservices.

Why should we care about this as developers? Three main reasons (in no particular order):

  1. Having clarity about code execution paths and flows within the application makes us more productive
  2. With proper analysis, it is possible to detect issues such as timeouts, bad performance, or even more.

I have been using a free IDE plugin called Digma, which provides a quick way to observe your code even in dev and test. One of its unique properties is that it is integrated right into the IDE. I’ll take advantage of this capability to demonstrate how we can use observability data for our HTTP libraries in dev.

Sample application services

I created a quick example using three microservices. 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.

How to observe in dev?

To get up and running quickly with an observability stack,  you can install 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 and our two endpoints:

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:

We can drill down to see which services are using this client and in which flows, as well as get a detailed performance view:

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 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.

Final Thoughts: RestClient vs. WebClient vs RestTemplate

By introducing the RestClient, Spring developers now have a modern alternative to RestTemplate with functional and fluent API similar to WebClient but suitable for synchro

Spread the news:

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *