Table of contents
1.
Introduction
2.
Why WebClient?
3.
When To Use WebClient?
4.
About WebClient in Spring Boot
4.1.
Creating a WebClient Instance
5.
How to Add WebClient in Spring Boot?  
6.
How to Use WebClient in Spring Boot Project?
7.
Example Spring Boot Project
7.1.
Developing Employee Service Step by Step
7.1.1.
Step 1: Create a Spring Boot Project
7.1.2.
Step 2: Define Employee Entity
7.1.3.
Step 3: Create Employee Controller
7.2.
Developing Address Service Step by Step
7.2.1.
Step 1: Create a Spring Boot Project
7.2.2.
Step 2: Define Address Entity
7.2.3.
Step 3: Create Address Controller
8.
Run Your Both Address and Employee Microservices
9.
Test Your Endpoint in Postman
10.
Why WebFlux?  
11.
How to Create a WebClient Instance?  
12.
How to Send a Request Using WebClient?  
13.
retrieve() vs exchange() in WebClient
14.
Frequently Asked Questions
14.1.
What is the difference between RestTemplate and WebClient?
14.2.
Can WebClient handle error responses?
14.3.
Do I need to use WebFlux to work with WebClient?
15.
Conclusion
Last Updated: Feb 16, 2025
Easy

WebClient in Spring Boot

Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

In Spring Boot, WebClient is a modern, non-blocking, and reactive HTTP client used to make API calls. It replaces the older RestTemplate and supports asynchronous communication, making it ideal for handling web requests efficiently. With WebClient, you can perform GET, POST, PUT, DELETE requests and process responses easily.

In this article, you will learn the features, usage, and examples of WebClient in Spring Boot to build scalable and efficient web applications.

Why WebClient?

WebClient is a reactive and non-blocking HTTP client introduced in Spring WebFlux. It replaces the older RestTemplate and provides better efficiency and scalability. Here’s why WebClient is preferred:

  • Supports asynchronous requests.
     
  • Works seamlessly with reactive programming.
     
  • Handles large data streams efficiently.
     
  • Provides better error handling and customization.

When To Use WebClient?

WebClient is useful in scenarios where you need to make HTTP calls to external services, such as:

  • Calling REST APIs from a Spring Boot application.
     
  • Fetching data from remote microservices.
     
  • Handling real-time streaming data.
     
  • Making non-blocking HTTP requests in reactive applications.

About WebClient in Spring Boot

WebClient is part of the Spring WebFlux module. It is fully reactive and provides a fluent API for making HTTP requests. You can use WebClient to send GET, POST, PUT, DELETE, and other HTTP requests.

Creating a WebClient Instance

To use WebClient in a Spring Boot project, first add the WebFlux dependency:

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

Then, create a WebClient bean:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;

@Configuration
public class WebClientConfig {
    @Bean
    public WebClient webClient() {
        return WebClient.builder().baseUrl("http://localhost:8080").build();
    }
}

How to Add WebClient in Spring Boot?  

To use WebClient in a Spring Boot application, you need to add the necessary dependencies to your project. WebClient is part of the Spring WebFlux module, so you’ll need to include it in your `pom.xml` file if you’re using Maven. If you’re using Gradle, you’ll add it to your `build.gradle` file.  

Let’s see how you can add WebClient to your Spring Boot project:  

For Maven:  

Open your `pom.xml` file & add the following dependency:  

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

 

This dependency includes WebClient & other reactive programming tools provided by Spring WebFlux.  


For Gradle:  

Open your `build.gradle` file & add the following dependency:  

implementation 'org.springframework.boot:spring-boot-starter-webflux'  

 

Once you’ve added the dependency, you’re ready to use WebClient in your Spring Boot application.  

How to Use WebClient in Spring Boot Project?

WebClient allows you to make HTTP requests with a simple and intuitive API. Here’s an example of making a GET request:

import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

@Service
public class EmployeeService {
    private final WebClient webClient;

    public EmployeeService(WebClient webClient) {
        this.webClient = webClient;
    }

    public Mono<String> getEmployeeData() {
        return webClient.get()
                .uri("/employees")
                .retrieve()
                .bodyToMono(String.class);
    }
}

Example Spring Boot Project

To demonstrate WebClient, we will build two microservices:

  1. Employee Service - Calls the Address Service using WebClient.
     
  2. Address Service - Returns address data.

Developing Employee Service Step by Step

Step 1: Create a Spring Boot Project

Use Spring Initializr and include Spring WebFlux and Spring Boot Starter Web dependencies.

Step 2: Define Employee Entity

public class Employee {
    private String id;
    private String name;
    private String addressId;

    // Constructors, Getters, and Setters
}

Step 3: Create Employee Controller

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

@RestController
public class EmployeeController {
    private final EmployeeService employeeService;

    public EmployeeController(EmployeeService employeeService) {
        this.employeeService = employeeService;
    }

    @GetMapping("/employee")
    public Mono<String> getEmployee(@RequestParam String id) {
        return employeeService.getEmployeeData();
    }
}

Developing Address Service Step by Step

Step 1: Create a Spring Boot Project

Include Spring Web in dependencies.

Step 2: Define Address Entity

public class Address {
    private String id;
    private String city;
    private String state;
    
    // Constructors, Getters, and Setters
}

Step 3: Create Address Controller

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AddressController {
    @GetMapping("/address")
    public Address getAddress(@RequestParam String id) {
        return new Address(id, "New York", "NY");
    }
}

Run Your Both Address and Employee Microservices

  1. Run Address Service:

  2. Run Employee Service:

Test Your Endpoint in Postman

  1. Start both microservices.
     
  2. Open Postman and send a GET request to http://localhost:8080/employee?id=1.
     
  3. The response should include employee details along with address information fetched using WebClient.

Why WebFlux?  

WebClient is part of the Spring WebFlux module because it supports reactive programming. Reactive programming is a programming paradigm that focuses on asynchronous data streams & non-blocking operations. This makes WebClient ideal for applications that need to handle a large number of concurrent requests efficiently.  

How to Create a WebClient Instance?  

Once you’ve added the WebClient dependency to your Spring Boot project, the next step is to create a WebClient instance. WebClient provides multiple ways to create an instance, depending on your needs. Let’s discuss the most common methods.  

1. Using the `WebClient.create()` Method  

The simplest way to create a WebClient instance is by using the static `create()` method. This method is useful for quick setups where you don’t need to configure the client extensively.  

Let’s see how you can do it:  

import org.springframework.web.reactive.function.client.WebClient;  

public class MyService {  
    private final WebClient webClient;  

    public MyService() {  
        this.webClient = WebClient.create();  
    }  

    public void fetchData() {  
        // Use the webClient instance to make requests  
    }  
}  

 

In this example, `WebClient.create()` creates a default WebClient instance with no base URL. You can use this instance to send requests to any URL.  

 

2. Using the `WebClient.builder()` Method  

For more advanced configurations, you can use the `WebClient.builder()` method. This allows you to customize the WebClient instance with options like a base URL, default headers, or filters.  

For example:  

import org.springframework.web.reactive.function.client.WebClient;  

public class MyService {  
    private final WebClient webClient;  

    public MyService() {  
        this.webClient = WebClient.builder()  
                .baseUrl("https://api.example.com") // Set a base URL  
                .defaultHeader("Authorization", "Bearer my-token") // Set default headers  
                .build();  
    }  

    public void fetchData() {  
        // Use the webClient instance to make requests  
    }  
}  

 

In this example, the WebClient instance is configured with a base URL (`https://api.example.com`) & a default header for authorization.  

 

3. Injecting WebClient as a Bean  

In a Spring Boot application, you can also define WebClient as a bean & inject it wherever needed. This is a clean & reusable approach, especially in larger applications.  

Let’s see how you can define a WebClient bean:  

import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  
import org.springframework.web.reactive.function.client.WebClient;  

@Configuration  
public class WebClientConfig {  

    @Bean  
    public WebClient webClient() {  
        return WebClient.builder()  
                .baseUrl("https://api.example.com")  
                .defaultHeader("Authorization", "Bearer my-token")  
                .build();  
    }  
}  

 

You can then inject this bean into your service class:  

import org.springframework.stereotype.Service;  
import org.springframework.web.reactive.function.client.WebClient;  

@Service  
public class MyService {  

    private final WebClient webClient;  

    public MyService(WebClient webClient) {  
        this.webClient = webClient;  
    }  

    public void fetchData() {  
        // Use the webClient instance to make requests  
    }  
}  

 

This approach ensures that your WebClient instance is reusable & centrally configured.  

How to Send a Request Using WebClient?  

Now, let’s discuss how to send requests using WebClient. WebClient supports all HTTP methods like GET, POST, PUT, DELETE, etc. We’ll give examples for GET & POST requests, as they are the most commonly used.  

1. Sending a GET Request  

A GET request is used to fetch data from a server. Here’s how you can send a GET request using WebClient:  

import org.springframework.web.reactive.function.client.WebClient;  
import reactor.core.publisher.Mono;  
public class MyService {  

    private final WebClient webClient;  

    public MyService(WebClient webClient) {  
        this.webClient = webClient;  
    }  
    public Mono<String> fetchData() {  
        return webClient.get()  
                .uri("/data") // Specify the endpoint  
                .retrieve() // Fetch the response  
                .bodyToMono(String.class); // Convert the response to a Mono<String>  
    }  
}  

 

Explanation:  

  • `webClient.get()` specifies that this is a GET request.  
     
  • `.uri("/data")` sets the endpoint to fetch data from.  
     
  • `.retrieve()` fetches the response.  
     
  • `.bodyToMono(String.class)` converts the response body into a `Mono<String>`.  

 

Example Usage:  

If the server returns JSON data like `{"message": "Hello, World!"}`, the `fetchData()` method will return a `Mono<String>` containing the JSON string.  
 

2. Sending a POST Request  

A POST request is used to send data to a server. Here’s how you can send a POST request using WebClient:  

import org.springframework.web.reactive.function.client.WebClient;  
import reactor.core.publisher.Mono;  

public class MyService {  

    private final WebClient webClient;  

    public MyService(WebClient webClient) {  
        this.webClient = webClient;  
    }  

    public Mono<String> sendData(String requestBody) {  
        return webClient.post()  
                .uri("/data") // Specify the endpoint  
                .bodyValue(requestBody) // Attach the request body  
                .retrieve() // Fetch the response  
                .bodyToMono(String.class); // Convert the response to a Mono<String>  
    }  
}  

 

Explanation:  

  • `webClient.post()` specifies that this is a POST request.  
     
  • `.uri("/data")` sets the endpoint to send data to.  
     
  • `.bodyValue(requestBody)` attaches the request body (e.g., a JSON string).  
     
  • `.retrieve()` fetches the response.  
     
  • `.bodyToMono(String.class)` converts the response body into a `Mono<String>`.  
     

Example Usage:  

If you want to send JSON data like `{"name": "John", "age": 30}`, you can call the `sendData()` method like this:  

String requestBody = "{\"name\": \"John\", \"age\": 30}";  
myService.sendData(requestBody).subscribe(response -> {  
    System.out.println("Response: " + response);  
});  

 

3. Adding Headers to Requests  

You can also add custom headers to your requests. Here’s an example of sending a GET request with headers:  

import org.springframework.web.reactive.function.client.WebClient;  
import reactor.core.publisher.Mono;  

public class MyService {  

    private final WebClient webClient;  

    public MyService(WebClient webClient) {  
        this.webClient = webClient;  
    }  

    public Mono<String> fetchDataWithHeaders() {  
        return webClient.get()  
                .uri("/data") // Specify the endpoint  
                .header("Authorization", "Bearer my-token") // Add a custom header  
                .header("Accept", "application/json") // Add another header  
                .retrieve() // Fetch the response  
                .bodyToMono(String.class); // Convert the response to a Mono<String>  
    }  
}  

 

Explanation:  

  • `.header("Authorization", "Bearer my-token")` adds an authorization header.  
     
  • `.header("Accept", "application/json")` specifies that the client expects a JSON response.  

 

4. Handling Errors  

WebClient provides built-in support for handling errors. For example, if the server returns a 404 error, you can handle it like this:  

import org.springframework.http.HttpStatus;  
import org.springframework.web.reactive.function.client.WebClient;  
import reactor.core.publisher.Mono;  

public class MyService {  

    private final WebClient webClient;  

    public MyService(WebClient webClient) {  
        this.webClient = webClient;  
    }  

    public Mono<String> fetchDataWithErrorHandling() {  
        return webClient.get()  
                .uri("/data") // Specify the endpoint  
                .retrieve()  
                .onStatus(HttpStatus::is4xxClientError, response -> {  
                    return Mono.error(new RuntimeException("Client error: " + response.statusCode()));  
                })  
                .onStatus(HttpStatus::is5xxServerError, response -> {  
                    return Mono.error(new RuntimeException("Server error: " + response.statusCode()));  
                })  
                .bodyToMono(String.class);  
    }  
}  

 

Explanation:  

  • `.onStatus(HttpStatus::is4xxClientError, ...)` handles client errors (e.g., 404).  
     
  • `.onStatus(HttpStatus::is5xxServerError, ...)` handles server errors (e.g., 500).  

retrieve() vs exchange() in WebClient

Parametersretrieve()exchange()
Response AccessGives direct access to the response body only. Cannot access headers or status codes.Provides access to the complete ClientResponse object, including headers, cookies, status codes, and body.
Memory UsageUses less memory as it processes only the response body.Uses more memory as it stores the complete response information.
Use CaseIdeal for simple API calls where only the response body is needed.Best for scenarios where you need to inspect headers, status codes, or cookies.
Error HandlingAutomatically throws WebClientResponseException for error status codes.Requires manual error handling through the complete response object.
Code ComplexitySimpler to use with less code.Requires more code but provides greater control over the response.

Frequently Asked Questions

What is the difference between RestTemplate and WebClient?

WebClient is non-blocking and reactive, while RestTemplate is blocking and synchronous. WebClient is recommended for modern Spring applications.

Can WebClient handle error responses?

Yes, WebClient provides error handling using .onStatus() to manage HTTP errors like 404 or 500.

Do I need to use WebFlux to work with WebClient?

No, WebClient works in both Spring WebFlux (reactive) and Spring MVC (non-reactive) projects.

Conclusion

WebClient in Spring Boot is a powerful tool for making HTTP requests in a reactive and efficient way. It is ideal for microservices communication, API calls, and handling large data streams. In this article, we built a Spring Boot project using WebClient to fetch data from an Address Service. We also tested the endpoints using Postman. By using WebClient, developers can build scalable, non-blocking, and high-performance applications efficiently.

Live masterclass