New in Spring 6.1: RestClient

Engineering | Arjen Poutsma | July 13, 2023 | ...

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

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

Retrieve

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);

POST

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();

Error handling

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);

Exchange

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;
    }
  });

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

Get the Spring newsletter

Stay connected with the Spring newsletter

Subscribe

Get ahead

VMware offers training and certification to turbo-charge your progress.

Learn more

Get support

Tanzu Spring offers support and binaries for OpenJDK™, Spring, and Apache Tomcat® in one simple subscription.

Learn more

Upcoming events

Check out all the upcoming events in the Spring community.

View all