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
public class RestClientTest {
private final RestClient restClient;
public RestClientTest() {
restClient = RestClient.builder()
.baseUrl("http://localhost:8080")
.build();
}
}
2. Use POST to Create a 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
@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
@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
@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
@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
- HttpClientErrorException: with 4xx response code
- 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());
}
Comments
Post a Comment
Leave Comment