Spring Boot– Consuming a REST Services with WebClient
In this guide, we’ll show how to consume REST services with WebClient
. Spring WebFlux includes a reactive, non-blocking (asynchronous) WebClient
for HTTP requests. It is an alternative of RestTemplate to call the remote REST services. Spring WebFlux framework is part of Spring 5 and provides reactive programming support for web applications.
What is Reactive Programming?
In plain terms, reactive programming is about non-blocking applications that are asynchronous and event-driven and require a small number of threads to scale vertically (i.e. within the JVM) rather than horizontally (i.e. through clustering). Source: docs.spring.io
What we’ll build
In this tutorial, we’ll create a Spring Boot application that makes a REST call to remote service using WebClient
.
Mock API: https://jsonplaceholder.typicode.com/posts/9 and the response of the API is:
{
"userId": 1,
"id": 9,
"title": "nesciunt iure omnis dolorem tempora et accusantium",
"body": "consectetur animi nesciunt iure dolore\nenim quia ad\nveniam autem ut quam aut nobis\net est aut quod aut provident voluptas autem voluptas"
}
Dependencies Required
WebClient
is bundled in Spring WebFlux dependency, make sure these following dependencies are available in the classpath. Add the following to your pom.xml.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Similar Post: Spring Boot – Calling REST Services with RestTemplate
How we’ll build
To consume the REST services of another application or microservices using WebClient
, follow the below steps:
Step 1: Create the POJO classes which have exactly the same field name as shown in API response.
Step 2: Instantiate WebClient.Builder
using @Bean annotation.
@Bean
public WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
Step 3: Create an object of WebClient.Builder
using @Autowired annotation where you want to make a REST call to external services.
@Autowired
private WebClient.Builder webClientBuilder;
Step 4: Call an external API as shown below:
return webClientBuilder.build()
.get()
.uri(POST_BY_ID_AP)
.retrieve()
.bodyToMono(Post.class)
.block();
The description of the method:
build()
method build aWebClient
instance.get()
method denote, you are making an HTTP.GET request. You can change it accordingly likepost()
,put()
,delete()
etc.uri()
method specifies the URI (API) that we wish to consume.retrieve()
method perform the HTTP request and retrieve the response body.bodyToMono(YourPOJOClass.class)
method map the response of the API to the POJO class.block()
method return the value.
Let’s jump to the actual piece of coding and create the POJO class.
1. POJO Class
package org.websparrow.dto;
public class Post {
private Integer id;
private Integer userId;
private String title;
private String body;
// Generate Getters and Setters...
}
Controller Class
In the controller class, we’ll instantiate the WebClient.Builder
object and define the final variable which holds the external REST service URI.
package org.websparrow.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
import org.websparrow.dto.Post;
@RestController
public class MyController {
private final String POST_OF_API = "http://jsonplaceholder.typicode.com/posts/9";
private final String POST_BY_ID_API = "http://jsonplaceholder.typicode.com/posts/{id}";
private final String POST_API = "http://jsonplaceholder.typicode.com/posts";
@Autowired
private WebClient.Builder webClientBuilder;
/**
* getPost() method call the defined API (static post)
*/
@GetMapping("/comsume")
public Post getPost() {
return webClientBuilder.build()
.get()
.uri(POST_OF_API)
.retrieve()
.bodyToMono(Post.class)
.block();
}
/**
* getPostById() method call the API with the post id send by the user (dynamic post)
*/
@GetMapping("/comsume/{id}")
public Post getPostById(@PathVariable("id") Integer postId) {
return webClientBuilder.build()
.get()
.uri(POST_BY_ID_API, postId)
.retrieve()
.bodyToMono(Post.class)
.block();
}
/**
* getAllPost() method call the API which returns the array or list of post
*/
@GetMapping("/comsume/all")
public Post[] getAllPost() {
return webClientBuilder.build()
.get()
.uri(POST_API)
.retrieve()
.bodyToMono(Post[].class)
.block();
}
}
Run it
The SpringBootWebClientApp
class is used to run the application and it also returns the bean of WebClient.Builder
.
package org.websparrow;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.reactive.function.client.WebClient;
@SpringBootApplication
public class SpringBootWebClientApp {
@Bean
public WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
public static void main(String[] args) {
SpringApplication.run(SpringBootWebClientApp.class, args);
}
}
Test it
To test the application open the Postman and hit the blow endpoints with an appropriate HTTP method:
Testcase 1:
Endpoint: http://localhost:8080/comsume
HTTP method: GET
Result: It will make a REST call to an external API and map all the data to the DTO.
{
"id": 9,
"userId": 1,
"title": "nesciunt iure omnis dolorem tempora et accusantium",
"body": "consectetur animi nesciunt iure dolore\nenim quia ad\nveniam autem ut quam aut nobis\net est aut quod aut provident voluptas autem voluptas"
}
Testcase 2:
Endpoint: http://localhost:8080/comsume/44
HTTP method: GET
Result: It will make a REST call to an external API with post id (i.e. 44)and map all the data to the DTO.
{
"id": 44,
"userId": 5,
"title": "optio dolor molestias sit",
"body": "temporibus est consectetur dolore\net libero debitis vel velit laboriosam quia\nipsum quibusdam qui itaque fuga rem aut\nea et iure quam sed maxime ut distinctio quae"
}
Similarly, you can also try http://localhost:8080/comsume/all endpoint which returns the array of objects.
References
- Spring Boot – Calling REST Services with RestTemplate
- Spring Boot – WebClient
- JSONPlaceholder
- Reactive programming – Wikipedia