Spring Framework 6.1 RestClient

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.

The modern way to make HTTP calls in Spring is WebClient. This tool provides a fluent API for setting up HTTP calls and allows for asynchronous operations. However, it's important to have the Spring Reactive Web dependency in your project, as the Spring Web dependency alone isn't sufficient.

Spring's new RestClient offers a solution for making synchronous calls, similar to RestTemplate, but with a fluent API akin to WebClient for configuring HTTP calls. Unlike the WebClient, RestClient only requires the Spring Web dependency. This new RestClient presents a straightforward approach to making HTTP requests without needing the sometimes extraneous Spring Reactive Web module. Essentially, it's the kind of client that RestTemplate was initially intended to be.

RestClient 

The RestClient is a synchronous HTTP client that offers a modern, fluent API. It offers an abstraction over HTTP libraries that allows for convenient conversion from Java object to HTTP request, and creation of objects from the HTTP response. 

Creating a RestClient 

The RestClient is created using one of the static create methods. 

The following sample shows how to create a default RestClient:

RestClient defaultClient = RestClient.create();

You can also use builder to get a builder with further options, such as specifying which HTTP library to use (see Client Request Factories) and which message converters to use (see HTTP Message Conversion), setting a default URI, default path variables, a default request headers, or uriBuilderFactory, or registering interceptors and initializers. Once created (or built), the RestClient can be used safely by multiple threads. 

The following sample shows how to build a custom RestClient object using builder:

RestClient customClient = RestClient.builder()
  .requestFactory(new HttpComponentsClientHttpRequestFactory())
  .messageConverters(converters -> converters.add(new MyCustomMessageConverter()))
  .baseUrl("https://example.com")
  .defaultUriVariables(Map.of("variable", "foo"))
  .defaultHeader("My-Header", "Foo")
  .requestInterceptor(myCustomInterceptor)
  .requestInitializer(myCustomInitializer)
  .build();

RestClient Class Methods/APIs

Here are some of the commonly used RestClient class methods:

create() - This method is used to create a new RestClient instance.

create(String baseUrl) - This method is a variant of create() that accepts a default base URL.

post() - This method is used to start building an HTTP POST request.

get() - This method is used to start building an HTTP GET request.

put() - This method is used to start building an HTTP PUT request.

delete() - This method is used to start building an HTTP DELETE request.

head() - This method is used to start building an HTTP HEAD request.

options() - This method is used to start building an HTTP OPTIONS request.

patch() - This method is used to start building an HTTP PATCH request.

Spring RestClient GET, POST, PUT, and DELETE Examples

1. Creating a RestClient

To create a RestClient, you can use the RestClientBuilder class. The RestClientBuilder class allows you to configure the RestClient, such as setting the base URI, adding interceptors, and configuring timeouts.
public class RestClientTest {
    private final RestClient restClient;

    public RestClientTest() {
        restClient = RestClient.builder()
                .baseUrl("http://localhost:8080")
                .build();
    }
}
Similarly to RestTemplate or any other rest client, RestClient allows us to make HTTP calls with request methods. Let’s walk through different HTTP methods to create, retrieve, modify, and delete resources.

2. Use POST to Create a Resource 

Let's use RestClient.post() method to send HTTP POST request to create an Employee resource:
    @Test
    public void createEmployee() {
        EmployeeDto newEmployee = new EmployeeDto(null, "admin", "admin", "admin123@gmail.com");

        EmployeeDto savedEmployee = restClient.post()
                .uri("/api/employees")
                .contentType(MediaType.APPLICATION_JSON)
                .body(newEmployee)
                .retrieve()
                .body(EmployeeDto.class);

        System.out.println(savedEmployee.toString());
    }

2. Use GET to Retrieve a Resource 

Let's use RestClient.get() method to make an HTTP GET request to retrieve a specific Employee:
    @Test
    public void getEmployeeById() {

        Long employeeId = 1L;

        EmployeeDto employeeDto = restClient.get()
                .uri("/api/employees/{id}", employeeId)
                .retrieve()
                .body(EmployeeDto.class);

        System.out.println(employeeDto);
    }

3. Use UPDATE to Update an Existing Resource 

Let's use RestClient.put() method to make an HTTP PUT request to update the existing Employee entity:
    @Test
    public void updateEmployee() {

        Long employeeId = 1L;

        EmployeeDto updatedEmployee = new EmployeeDto();
        updatedEmployee.setFirstName("Ramesh");
        updatedEmployee.setLastName("Fadatare");
        updatedEmployee.setEmail("ramesh@gmail.com");

        EmployeeDto result = restClient.put()
                .uri("/api/employees/{id}", employeeId)
                .contentType(MediaType.APPLICATION_JSON)
                .body(updatedEmployee)
                .retrieve()
                .body(EmployeeDto.class);

        System.out.println(result.toString());
    }

5. Use GET to Retrieve all the Resources

Let's use RestClient.get() method to make an HTTP GET request to retrieve all the Employees:
    @Test
    public void findAll() {
        List<EmployeeDto> listOfEmployees = restClient.get()
                .uri("/api/employees")
                .retrieve()
                .body(new ParameterizedTypeReference<List<EmployeeDto>>() {});

        listOfEmployees.forEach(employeeDto -> {
            System.out.println(employeeDto.toString());
        });
    }

 

6. Use DELETE to Delete an Existing Resource

Let's use RestClient.delete() method to make an HTTP DELETE request to delete a specific Employee:
    @Test
    public void deleteEmployee() {
        Long employeeId = 1L;

        String response = restClient.delete()
                .uri("/api/employees/{id}", employeeId)
                .retrieve()
                .body(String.class);

        System.out.println(response);
    }

7. Exception Handling

The RestClient throws two types of exceptions for a failed request: 
  1. HttpClientErrorException: with 4xx response code 
  2. HttpServerErrorException: with 5xx response code

Handling HttpClientErrorException Example

    @Test
    public void exceptionHandlingClientErrorDemo(){
        HttpClientErrorException thrown = Assertions.assertThrows(HttpClientErrorException.class,
                () -> {

                    EmployeeDto employee = restClient.get()
                            .uri("/employees/404")
                            .accept(MediaType.APPLICATION_JSON)
                            .retrieve()
                            .body(EmployeeDto.class);
                });

        Assertions.assertEquals(404, thrown.getStatusCode().value());
    }

Handling HttpServerErrorException Example

    @Test
    public void exceptionHandlingServerErrorDemo(){
        HttpServerErrorException thrown = Assertions.assertThrows(HttpServerErrorException.class,
                () -> {

                    EmployeeDto employee = restClient.get()
                            .uri("/api/employees/500")
                            .accept(MediaType.APPLICATION_JSON)
                            .retrieve()
                            .body(EmployeeDto.class);
                });

        Assertions.assertEquals(500, thrown.getStatusCode().value());
    }

Complete Tutorial

You can find a complete tutorial to create and consume CRUD REST APIs here: Spring Boot 3.2 RestClient Tutorial - GET, POST, PUT, and Delete Example

GitHub Repository

The source code of this tutorial is available on the GitHub repository: spring-boot-3.2-restclient-demo

Comments