Get ahead
VMware offers training and certification to turbo-charge your progress.
Learn moreSpring Framework 6.1 M2 introduces the RestClient
, a new synchronous HTTP client.
As the name suggests, RestClient
offers the fluent API of WebClient
with the infrastructure of RestTemplate
.
Fourteen years ago, when RestTemplate
was introduced in Spring Framework 3.0, we quickly discovered that exposing every capability of HTTP in a template-like class resulted in too many overloaded methods.
In Spring Framework 5, we therefore used a fluent API for the reactive WebClient
.
With RestClient
we are introducing a HTTP client that offers an API similar to WebClient
, and that uses the message converters, request factories, interceptors, and other underlying components of RestTemplate
.
RestClient
You can create a RestClient
using one of the static create
methods.
You can also use RestClient::builder
to get a builder with further options, such as specifying the HTTP client to use, setting a default URL, path variables, and headers, or registering interceptors and initializers.
Using RestClient::create(RestTemplate)
, you can initialize a RestClient
with the configuration of an existing RestTemplate
.
Let's create a RestClient
, use it to set up a basic GET
request, and retrieve the contents of a site as string using retrieve
:
RestClient restClient = RestClient.create();
String result = restClient.get()
.uri("https://example.com")
.retrieve()
.body(String.class);
System.out.println(result);
If you're interested in the response status code and headers, and not just the contents, you can use toEntity
to get a ResponseEntity
:
ResponseEntity<String> result = restClient.get()
.uri("https://example.com")
.retrieve()
.toEntity(String.class);
System.out.println("Response status: " + result.getStatusCode());
System.out.println("Response headers: " + result.getHeaders());
System.out.println("Contents: " + result.getBody());
RestClient
can also convert JSON to objects, using Jackson under the hood.
In fact, it can convert all types that RestTemplate
supports, as it uses the same message converters.
Note the usage of uri variables, and that the Accept
header is set to JSON.
int id = ...
Pet pet = restClient.get()
.uri("https://petclinic.example.com/pets/{id}", id)
.accept(APPLICATION_JSON)
.retrieve()
.body(Pet.class);
Doing a POST
request is just as simple, like so:
Pet pet = ...
ResponseEntity<Void> response = restClient.post()
.uri("https://petclinic.example.com/pets/new")
.contentType(APPLICATION_JSON)
.body(pet)
.retrieve()
.toBodilessEntity();
By default, RestClient
throws a subclass of RestClientException
when receiving a 4xx or 5xx status code.
This behavior can be overriden using status handlers, like so:
String result = restClient.get()
.uri("https://example.com/this-url-does-not-exist")
.retrieve()
.onStatus(HttpStatusCode::is4xxClientError, (request, response) -> {
throw new MyCustomRuntimeException(response.getStatusCode(), response.getHeaders())
})
.body(String.class);
The RestClient
offers the exchange
method for more advanced scenarios, as it provides access to the underlying HTTP request and response.
The previously mentioned status handlers are not applied when you use exchange
, because the exchange function already provides access to the full response, allowing you to perform any error handling necessary:
Pet result = restClient.get()
.uri("https://petclinic.example.com/pets/{id}", id)
.accept(APPLICATION_JSON)
.exchange((request, response) -> {
if (response.getStatusCode().is4xxClientError()) {
throw new MyCustomRuntimeException(response.getStatusCode(), response.getHeaders());
}
else {
Pet pet = convertResponse(response);
return pet;
}
});
RestClient
The RestClient
is just one of the many features that Spring Framework 6.1 offers.
Various components already support RestClient
: you can test its usage through the MockRestServiceServer
, or use it as the backend for @HttpExchange
interfaces.
Additionally, Spring Boot 3.2 M1 will include support for the RestClient
.