Spring Boot WebClient Example (2024)
Overview
In this tutorial we will be looking at example using Spring Boot WebFlux WebClient.
Spring WebFlux Tutorial :
In this tutorial, we'll create spring boot application with WebClient for communication between two services.
We will utilize our previous example Spring Boot WebFlux + MongoDB Crud Example to call the crud services using WebClient.
What is WebClient?
Spring Framework 5 has introduces WebClient (spring-webflux module
), a part of
the new Web Reactive framework that helps
construct reactive and non-blocking web applications, is part of the Spring MVC project and
allows
communication with HTTP servers while adhering to RESTful standards.
Prior to Spring 5, RestTemplate was the main approach for client-side HTTP communications, which was part of the Spring MVC project.
Since the release of Spring Framework 5, WebClient has been the recommended for client-side HTTP communications.
Let's create Spring Boot Project from Spring Initializer site https://start.spring.io/
Project Structure
Maven Dependency
The spring-boot-starter-webflux
module must be added in the pom.xml
to use
the WebClient API.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.techgeeknext</groupId>
<artifactId>spring-boot-webclient-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-boot-webclient-example</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.projectreactor</groupId>
<artifactId>reactor-spring</artifactId>
<version>1.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Take a look at our suggested posts:
Application Properties
The default memory limit for buffering data in memory in Spring WebFlux is configured to
256KB. If
this limit is exceeded in any way, the DataBufferLimitException
error will occur.
org.springframework.core.io.buffer.DataBufferLimitException: Exceeded limit on max bytes to buffer
Configure the spring.codec.max-in-memory-size
property in the application.properties to
reset the memory limit.
server.port=8081
logging.level.org.springframework=DEBUG
server.servlet.context-path=/employee-management
spring.codec.max-in-memory-size=3MB
logging.level.reactor.netty.http.client.HttpClient=DEBUG
logging.level.org.springframework.boot.autoconfigure=ERROR
WebFlux Configuration
Create WebFlux Configuration Class.
- The HttpClient can be used to define connection timeout periods, read, and write timeouts.
Create and configure WebClient instance
We can use any one of the ways listed below to create WebClient.WebClient.create() API
create()
is a factory method to create instance of WebClient and then further we can provide url to it.WebClient webClientObj = WebClient.create();
WebClient.create(url) API
The create() method is an overloaded method that accepts a base URL (calling service url) for requests as an optional parameter.WebClient webClientObj = WebClient.create("http://localhost:8080");
WebClient.Builder API
WebClient.Builder()
is the builder method to create WebClient instance. This is reusable, as we can create the instance at one place can be used to instantiate multiple WebClient instance where ever required.@Bean public WebClient getWebClient() { return WebClient.builder() .baseUrl("http://localhost:8080") .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .build(); }
WebClient.Builder() + Filter for basic authentication
If authentication is required while calling an upstream service, it can be accomplished by usingWebClient.Builder()
with afilter
.import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication; WebClient client = WebClient.builder() .filter(basicAuthentication("user", "password")) .build();
package com.techgeeknext.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springframework.web.reactive.function.client.WebClient;
@Configuration
@EnableWebFlux
public class WebFluxConfig implements WebFluxConfigurer
{
Logger logger = LoggerFactory.getLogger(WebFluxConfig.class);
@Bean
public WebClient getWebClient()
{
return WebClient.builder()
.baseUrl("http://localhost:8080")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.build();
}
}
Retrieve or Exchange data
Sending request and receiving a response, can be achieved by using retrieve()
or exchange()
are two
methods that can be used to retrieve or exchange data. The retrieve()
method
makes an HTTP request
and retrieves the response body directly. ClientResponse
with the response status and
headers is
returned by the exchange()
method. The response body can be obtained from the ClientResponse
instance.
package com.techgeeknext.service;
import com.techgeeknext.model.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.time.Duration;
@Service
public class EmployeeService implements IEmployeeService
{
@Autowired
WebClient webClient;
public Flux<Employee> findAll()
{
return webClient.get()
.uri("/get/all")
.retrieve()
.bodyToFlux(Employee.class)
.timeout(Duration.ofMillis(10_000));
}
public Mono<Employee> create(Employee empl)
{
return webClient.post()
.uri("/create/emp")
.body(Mono.just(empl), Employee.class)
.retrieve()
.bodyToMono(Employee.class)
.timeout(Duration.ofMillis(10_000));
}
public Mono<Employee> findById(Integer id)
{
return webClient.get()
.uri("/get/" + id)
.retrieve()
.bodyToMono(Employee.class);
}
public Mono<Employee> update(Employee e)
{
return webClient.put()
.uri("/update/emp/" + e.getId())
.body(Mono.just(e), Employee.class)
.retrieve()
.bodyToMono(Employee.class);
}
public Mono<Void> delete(Integer id)
{
return webClient.delete()
.uri("/delete/" +id)
.retrieve()
.bodyToMono(Void.class);
}
}
- If we simply care about the response body entity, the
retrieve()
method and thenbodyToFlux()
andbodyToMono()
methods will suffice. - Otherwise, use the method
exchange()
, which returns aClientResponse
with all of the response elements, including status, headers, and the response body. - Please keep in mind that the
bodyToMono()
andbodyToFlux()
methods require a response body of the specified class type. These methods throwWebClientException
if the response status code is 4xx (client error) or 5xx (server error), i.e. there is no response body. - While using
exchange()
, ensure that resources are freed and to avoid potential issues with HTTP connection pooling, we must always use any of the body or toEntity methods ofClientResponse
. If no response content is expected, usebodyToMono(Void.class)
.
Rest Controller
Create Rest Controller, which will in turn call the rest end points of other microservice ( Spring Boot WebFlux + MongoDB Crud Example) using WebClient.
package com.techgeeknext.controller;
import com.techgeeknext.model.Employee;
import com.techgeeknext.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/employees")
public class EmployeeController
{
@Autowired
private EmployeeService employeeService;
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE)
@ResponseStatus(HttpStatus.OK)
//using Flux for collection of employees
public Flux<Employee> findAll() {
return employeeService.findAll();
}
@GetMapping(value = "/{id}")
//using Mono for single employee
public Mono<Employee> findById(@PathVariable("id") Integer id) {
return employeeService.findById(id);
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
//using Mono for single employee
public Mono<Employee> create(@RequestBody Employee e) {
return employeeService.create(e);
}
@PutMapping(value = "/{id}")
@ResponseStatus(HttpStatus.OK)
//using Mono for single employee
public Mono<Employee> update(@RequestBody Employee e, @PathVariable("id") Integer id) {
e.setId(id);
return employeeService.update(e);
}
@DeleteMapping(value = "/{id}")
@ResponseStatus(HttpStatus.OK)
// using Mono<Void> when no response content is expected
public Mono<Void> delete(@PathVariable("id") Integer id) {
return employeeService.delete(id);
}
}
Test WebClient
To test WebClient communication with asynchronous (WebFlux) rest api example, perform below steps:
- Download and Run Spring Boot WebFlux + MongoDB Crud Example. It will provide WebFlux rest api's for tesing WebClient Communication.
-
Run Spring Boot + WebClient Example (can Download Source given below) by using
mvn spring-boot run
command. - Open Postman or any Browser and use employees rest endpoint http://localhost:8081/employees to get all the employees.
- You can also verify other rest endpoints such as get employee by id http://localhost:8081/employees/1.
Download Source Code
The full source code for this article can be found on below.Download it here - Spring Boot WebClient Example