Spring WebClient

Spring WebClient is a non-blocking and reactive web client to perform HTTP requests. WebClient has been added in Spring 5 (spring-webflux module) and provides fluent functional style API.

Prior to Spring 5, RestTemplate has been main technique for client-side HTTP accesses, which is part of the Spring MVC project.

Since Spring 5 release, WebClient is the recommended.

Table of Contents

1. How to use WebClient
    1.1. Create and configure WebClient instance
    1.2. Sending requests
    1.3. Handling responses
2. WebClient - GET API Example
3. WebClient - POST API Example
4. WebClient - PUT API Example
5. WebClient - DELETE API Example
6. Useful configurations
    6.1. Memory limit
    6.2. Connection Timeout

1. How to use WebClient

To use WebClient api, we must have spring-boot-starter-webflux module imported in the project.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

1.1. Create and configure WebClient instance

To create WebClient, we can follow any one of given approaches.

1.1.1. WebClient.create() API

The create() method is an overloaded method and can optionally accept a base URL for requests.

WebClient webClient1 = WebClient.create();

WebClient webClient2 = WebClient.create("https://client-domain.com");
1.1.2. WebClient.Builder API
WebClient webClient2 = WebClient.builder()
        .baseUrl("http://localhost:3000")
        .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
        .build();

1.2. Sending requests

To send a request, we can use its fluent API and execute the necessary steps as per requirements. For example, sending a HTTP POST request involves following steps.

  • Create WebClient.UriSpec reference using method(HttpMethod) or prebuilt methods such as get(), put(), post() or delete().
  • Set the request URI if not set already.
  • Set the request headers and authentication details, if any.
  • Set the request body, if any.
  • Call the retrieve() or exchange() method. The retrieve() method directly performs the HTTP request and retrieve the response body. The exchange() method returns ClientResponse having the response status and headers. We can get the response body from ClientResponse instance.
  • Handle the response returned from the server.
WebClient webClient = WebClient.create("http://localhost:3000");

Employee createdEmployee = webClient.post()
		.uri("/employees")
		.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
		.body(Mono.just(empl), Employee.class)
		.retrieve()
		.bodyToMono(Employee.class);

1.3. Handling responses

If we are only interested in response body entity the using methods retrieve() and then bodyToFlux() and bodyToMono() will serve the purpose.

Else, use method exchange() which will return the ClientResponse which has all the response elements such as status, headers and response body as well.

Please note that bodyToMono() and bodyToFlux() methods always expect a response body of given class type. If response status code is 4xx (client error) or 5xx (Server error) i.e. there is no response body then these methods throw WebClientException.

When using exchange(), we must always use any of the body or toEntity methods of ClientResponse to ensure resources are released and to avoid potential issues with HTTP connection pooling. Use bodyToMono(Void.class) if no response content is expected.

2. WebClient – GET API Example

Generally, we will use GET API to fetch either collection of resources or a singular resource. Let’s see the example of both use cases using get() method call.

  • HTTP GET /employees : collection of employees as Flux
  • HTTP GET /employees/{id} : single employee by id as Mono
@Autowired
WebClient webClient;

public Flux<Employee> findAll() 
{
	return webClient.get()
		.uri("/employees")
		.retrieve()
		.bodyToFlux(Employee.class);
}

public Mono<Employee> findById(Integer id) 
{
	return webClient.get()
		.uri("/employees/" + id)
		.retrieve()
		/*.onStatus(httpStatus -> HttpStatus.NOT_FOUND.equals(httpStatus),
                clientResponse -> Mono.empty())*/
		.bodyToMono(Employee.class);
}

3. WebClient – POST API Example

POST API is used commonly for creating a resource. Let’s see an example of post() method to create an employee.

  • HTTP POST /employees : creates a new employee from request body and returns the created employee in response.
@Autowired
WebClient webClient;

public Mono<Employee> create(Employee empl)
{
	return webClient.post()
		.uri("/employees")
		.body(Mono.just(empl), Employee.class)
		.retrieve()
		.bodyToMono(Employee.class);
}

4. WebClient – PUT API Example

PUT API is used commonly for updating a resource. Let’s see an example of put() method to update an employee.

  • HTTP PUT /employees/{id} : updates an existing employee data from request body and returns the updated employee in response.
@Autowired
WebClient webClient;

public Mono<Employee> update(Employee e) 
{
	return webClient.put()
		.uri("/employees/" + e.getId())
		.body(Mono.just(e), Employee.class)
		.retrieve()
		.bodyToMono(Employee.class);
}

5. WebClient – DELETE API Example

DELETE API is used commonly for deleting a resource. Let’s see an example of delete() method to delete an employee from records.

  • HTTP DELETE /employees/{id} : deletes an existing employee by its id. It does not accept any request body as well as does not return any response body as well.
@Autowired
WebClient webClient;

public Mono<Void> delete(Integer id) 
{
	return webClient.delete()
		.uri("/employees/" +id)
		.retrieve()
		.bodyToMono(Void.class);
}

6. Useful Spring WebClient related Configurations

6.1. Memory limit

Spring WebFlux configures the default memory limit for buffering data in-memory to 256KB. If this limit is exceeded in any case then we will encounter DataBufferLimitException error.

To reset the memory limit, configure below property in application.properties file.

spring.codec.max-in-memory-size=1MB

6.2. Connection Timeout

We can use HttpClient class to set timeout periods for connection timeout, read timeout and write timeouts.

@Bean
public WebClient getWebClient()
{
	HttpClient httpClient = HttpClient.create()
	        .tcpConfiguration(client ->
	                client.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)
	                .doOnConnected(conn -> conn
	                        .addHandlerLast(new ReadTimeoutHandler(10))
	                        .addHandlerLast(new WriteTimeoutHandler(10))));
	
	ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);	    

	return WebClient.builder()
	        .baseUrl("http://localhost:3000")
	        .clientConnector(connector)
	        .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
	        .build();
}

Drop me your questions related to Spring WebClient.

Happy Learning !!

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

4 thoughts on “Spring WebClient”

  1. Hi, can you add a complete example using connection timeout for an Api request and a handled response? Thanks so much

    Reply
  2. I am using the spring webclient 5.1.2.Release and .addHandlerLast( is giving the following error
    class file for reactor.core.Disposable not found
    1 error

    Please help me to fix

      compile "org.springframework:spring-webflux:5.1..2.RELEASE"
      compile "org.springframework.boot:spring-boot-starter-reactor-netty:2.1.0.RELEASE"
    Reply
  3. Hi Lokesh

    How do i use this webclient to get OAuth Token from a end point and then use that token to get a resource from another end point pls.

    Reply

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.