Spring WebClient (with Examples)

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 the main technique for client-side HTTP accesses, which is part of the Spring MVC project. Since Spring 5 release, WebClient is the recommended approach.

1. WebClient

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

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

1.1. Create and configure WebClient

To create WebClient, we can follow any one of the 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 the 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 the 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 a given class type. If the 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&lt;Employee&gt; findAll()
{
	return webClient.get()
		.uri("/employees")
		.retrieve()
		.bodyToFlux(Employee.class);
}

public Mono&lt;Employee&gt; findById(Integer id)
{
	return webClient.get()
		.uri("/employees/" + id)
		.retrieve()
		/*.onStatus(httpStatus -&gt; HttpStatus.NOT_FOUND.equals(httpStatus),
                clientResponse -&gt; 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&lt;Employee&gt; 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&lt;Employee&gt; 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&lt;Void&gt; delete(Integer id)
{
	return webClient.delete()
		.uri("/employees/" +id)
		.retrieve()
		.bodyToMono(Void.class);
}

6. Useful 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 the 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 -&gt;
	                client.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)
	                .doOnConnected(conn -&gt; 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 !!

Leave a Reply

6 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions, and frequently asked interview questions.

Our Blogs

REST API Tutorial