Spring 5 WebClient

Spring 5 WebClient

0 Comments

Spring Framework 5 introduces WebClient, a component in the new Web Reactive framework to build Web applications that are reactive and non-blocking.

In web applications, a common requirement is to make HTTP calls to other services.

Prior to Spring 5, there was RestTemplate for client-side HTTP access. RestTemplate, which is part of the Spring MVC project, enables communication with HTTP servers and enforces RESTful principles.

Other options to perform HTTP operations from Spring Boot applications include the Apache HttpClient library. These options are based upon the Java Servlet API, which is blocking (aka not reactive).

With Spring Framework 5, you now have a new reactive WebClient that provides a higher level, common API over HTTP client libraries.

This post assumes you have basic knowledge of Spring 5 Reactive Programming.

If you are new to reactive programming, checkout my course, Spring Framework 5: Beginner to Guru which covers reactive programming with Spring Framework 5.

In this post I will explain how to use WebClient along with WebClientTest.

Overview of WebClient

WebClient is a non-blocking, reactive client for performing HTTP requests with Reactive Streams back pressure. WebClient provides a functional API that takes advantage of Java 8 lambdas.

By default, WebClient uses Reactor Netty as the HTTP client library but others can be plugged in through a custom ClientHttpConnector.

To start using WebClient with remote Rest APIs, you need Spring WebFlux as your project dependency.

You can create a WebClient using one of the static factory methods create() or the overloaded create(String). Another approach is to obtain a builder() to create and configure an instance.

In this post, we’ll look at both the approaches.

The Application

For this post, I have a Spring 5 reactive RESTful service that acts as a Producer. It continuously emits streams of data wrapped in a Flux. We will access the producer from a second service using WebClient.

We will also use WebClient to access the OMDB API, a free REST API to query movie information.

The existing Spring 5 Reactive RESTful service (Producer) is comprised of a controller and a MovieEvent domain object that models an event. The service layer produces a stream of MovieEvent with a delay of 1 second continuously.

As this post is on WebClient, I won’t go into the Producer side. The Producer is a Maven project that you can download from the link provided at the end of this post. You need to clone it, import it to your IDE, and run.

I have imported the producer as a Maven Project to IntelliJ and got it running on an embedded Netty server, as shown in this Figure.

Spring WebFlux Producer Output from Netty

WebClient in the API Consumer

The API consumer is a Spring Boot project that uses WebFlux. The consumer communicates with two services:

  1. OMDB API to retrieve movie information by name, and ID.
  2. Our local Producer to consume event streams.

To access the OMDB API, get your free API access key here.

The Maven POM of the consumer is this.

pom.xml

The Domain Models

Our domain model is a Movie POJO with fields to hold movie information returned by the OMDB API.

The Movie POJO is this.

Movie.java

Our second domain model is MovieEvent that models an event to be received from the Producer.

The MovieEvent POJO is this.

MovieEvent.java

The Service Interfaces

The service layer is composed of two service interfaces – MovieClientService and MovieClientEventService.

The service interfaces are as follows.

MovieClientService.java

MovieClientEventService.java

The Service Implementations

The MovieClientServiceImplementation class implements the MovieClientService interface. In this class, we will use WebClient to send requests to the OMDB API to search a movie by ID and title.

For this example, I have specified the OMDB API access key in the application.properties file, like this.

The code of the MovieClientServiceImplementation class is this.

MovieClientServiceImplementation.java

In the preceding code:

  • The constructor of the MovieClientServiceImplementation creates a WebClient using a WebClient.Builder obtained from a call to the builder() method.
  • Line 24 – Line 27 configures the WebClient through method chaining with the base URL and the CONTENT_TYPE and USER_AGENT headers.
  • Line 30 – Line 35 implements the searchMovieByTitle() method to perform a request with the API key and movie title. The retrieve() method returns a WebClient.ResponseSpec whose bodyToMono() extracts the response body to a Mono.
  • Line 38 -Line 43 implements the searchMovieById() method in the same way, but by passing the movie ID instead of the title in the URL.

The MovieClientEventServiceImpl class implements the MovieClientEventService interface to communicate with our producer of MovieEvent stream.

The MovieClientEventServiceImpl service implementation is this.

MovieClientEventServiceImpl.java

Note that Line 32 calls the exchange() method instead of retrieve() this time to receive the response. The exchange() method returns a Mono that represents the response body along with other information, such as status and headers. On the other hand, the retrieve() method we used earlier is a lightweight way to access the response body directly.

Learn more about WebClient in my Spring Framework 5 Online Course
Online Course – Spring Framework 5: Beginner to Guru

The Controller

The REST controller of the Consumer application define endpoints for clients to query for movies and subscribe to events.

The MovieController class is this.

MovieController.java

Testing Endpoints with WebTestClient

To test endpoints, Spring 5 WebFlux framework comes with a WebTestClient class. WebTestClient is a thin shell around WebClient. You can use it to perform requests and verify responses.

WebTestClient bind to a WebFlux application using a mock request and response, or it can test any web server over an HTTP connection.

Our first test uses WebTestClient to test the movie search endpoints exposed by out Producer RESTful service.

The code of the MovieClientServiceImplTest is this.

MovieClientServiceImplTest.java

In the preceding code:

  • Line 27 autowires in WebTestClient to the test class.
  • Line 31 – Line 36 mutates the response timeout property of WebTestClient and builds it.
  • Line 38 – Line 42 of the first test case sets up a GET request and performs the request through exchange()
  • Line 43- Line 46 after exchange() is a chained API workflow to verify responses.
  • Line 49 – Line 58 similarly tests the endpoint that accepts search requests of movies by title.

Our second test uses WebTestClient to test the event source endpoint exposed by out Producer RESTful service.

The code of the MovieClientServiceImplTest is this.

MovieClientEventServiceImplTest.java

Summary

One common question is whether WebClient is replacing the traditional RestTemplate. Not at this time. RestTemplate will continue to exist within the Spring Framework for the foreseeable future.

The primary differentiating factor is that RestTemplate continues to use the Java Servlet API and is synchronous blocking. This means, a call done using RestTemplate needs to wait till the response comes back to proceed further.

On the other hand, as WebClient is asynchronous, the rest call need not wait till response comes back. Instead when there is a response, a notification will be provided.

Get The Source!

Like all of my tutorials, the source code for this post is available on GitHub here.

Testing Spring Boot Online Course
Online Course – Testing Spring Boot: Beginner to Guru
1

About jt

    You May Also Like

    Leave a Reply