Introducing the new Spring Rest Client

Introducing the new Spring Rest Client

Since the release of 6.1 we get the RestClient in Spring, a brand new synchronous HTTP client. This client is based on the RestTemplate and combines the fluentApi of WebClient with the infrastructure of RestTemplate. There already exist 2 viable options in the spring framework for making http calls. The RestTemplate that was introduced fourteen (!) years ago, and the WebClient introduced in Spring Framework 5. Both come with certain drawbacks however. Let’s look at them.


Since the release of 6.1 we get the RestClient in Spring, a brand new synchronous HTTP client. This client is based on the RestTemplate and combines the fluentApi of WebClient with the infrastructure of RestTemplate.

Why is a new RestClient needed?

There already exist 2 viable options in the spring framework for making http calls. The RestTemplate that was introduced fourteen (!) years ago, and the WebClient introduced in Spring Framework 5. Both come with certain drawbacks however. Let’s look at them.

RestTemplate

The template was the go to for many years, it’s usage can be a bit clunky however. Exposing every capability of HTTP in a template results in a lot of overloaded methods:

Also, it lacks a nice and easy to use builder for your requests, so a simple get request looks like this.

private void getCallWithRestTemplate() {  
    String apiUrl = "https://fabiangotzen.com/data";  
    ResponseEntity<String> response = restTemplate.getForEntity(apiUrl, String.class);  
    System.out.println("Response: " + response.getBody());  
}

An additional drawback is that it has been marked for deprecation since Spring 5, in order to be replaced by the webClient, which we will look at now.

WebClient

At first glance, there is nothing wrong in using webClient in your application, even if it’s a synchronous API. You can create an equivalent get request like this:

private void getCallWithWebClient() {  
    String response = webClient.get()  
        .uri("/data")  
        .retrieve()  
        .bodyToMono(String.class)  
        .block();  

    System.out.println("Response: " + response);  
}

however, if we look a bit closer we see 2 methods that don’t necessarily need to be there in a synchronous API, “bodyToMono” and “block”. “bodyToMono” converts the response to a String and since WebClient is non-blocking by nature, “block” needs to be added to make the example synchronous. An additional pain point if you don’t need async APIs in your application is that you have to add the spring-boot-starter-webflux dependency to your application only to get the webClient. So now let’s have a look at the solution, the new RestClient.

RestClient

Note: At the time of writing the current GA of Spring Boot is 3.1.3 and the RestClient is not yet included there. If you want to try it out you need to use the 3.2.0-SNAPSHOT version and configure your pom.xml to use the spring-milestone repositories. (Easiest way to do this is to head to Spring Start and select the 3.2.0 Snapshot or M2 version.) After you have everything set up, a RestClient bean can be simply configured like this:

@Bean
RestClient restClient() {
return RestClient.create();
}

If we now want to make the same rest call as in the examples above, we can use the RestClient like this:

private void getCallWithRestClient(){
    String response = restClient.get()  
        .uri("/data")  
        .retrieve()  
        .body(String.class);  

    System.out.println("Response: " + response);
}

If we want to retrieve the response status and headers we can use the new toEntity method to extract the information as follows

ResponseEntity result = restClient.get()
    .uri("/data")
    .retrieve()
    .toEntity(String.class);

System.out.println("Response status: " + result.getStatusCode());
System.out.println("Response headers: " + result.getHeaders());
System.out.println("Contents: " + result.getBody());
}

So the benefit is essentially that we get the best of both worlds, we stay in synchronous world and can use the Rest Client with our standard web-starter dependency and can avoid the method calls to make the asynchronous Web Client synchronous via blocking and converting the Body to a Mono. At the same time, we have a nice fluent API which is easier to read and maintain than the Rest Template.

Hope you enjoy your new Rest Client

Further Reading / Watching:

Spring Blog