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 a WebClient instance.
  • get() method denote, you are making an HTTP.GET request. You can change it accordingly like post(), 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

Post.java
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.

MyController.java
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.

SpringBootWebClientApp.java
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

  1. Spring Boot – Calling REST Services with RestTemplate
  2. Spring Boot – WebClient
  3. JSONPlaceholder
  4. Reactive programming – Wikipedia

Similar Posts

About the Author

Atul Rai
I love sharing my experiments and ideas with everyone by writing articles on the latest technological trends. Read all published posts by Atul Rai.