How to Avoid Blocking Calls in Reactive Programming

Bhavin Shah
3 min readJul 20, 2023

--

Reactive programming is a programming paradigm that focuses on data streams and the propagation of change. It’s designed to be non-blocking, meaning it should handle events and execute operations without stopping the flow of the program. However, one of the challenges that developers often face in reactive programming is dealing with blocking calls. In this blog post, we will explore how to avoid blocking calls in reactive programming, illustrated with examples.

What are Blocking Calls?

stop sign
Photo by Markus Winkler on Unsplash

In simple terms, a blocking call is any function that halts the execution of a program until a specific operation completes. This means that the program’s flow is ‘blocked’ until the operation is finished, which can lead to inefficiencies and delays in the overall execution of the program.

Blocking calls are particularly problematic in reactive programming because they go against the paradigm’s core principles. Reactive programming is designed to be non-blocking, meaning it should handle events and execute operations without stopping the flow of the program.

Avoiding Blocking Calls in Reactive Programming

The key to avoiding blocking calls in reactive programming is to use non-blocking methods. These methods allow the program to continue executing other operations while waiting for the operation to complete.

flatMap() is a powerful operator that allows you to perform asynchronous operations and handle the results without blocking.

Let’s consider an example where we need to call an external API to get user details and then another API to get the user’s order details. We’ll use Spring WebFlux’s WebClient to make the API calls.

First, let’s define our data models:

public class User {
private String id;
private String name;
private String email;
// Getters and setters omitted for brevity
}
public class Order {
private String id;
private String userId;
private String product;
// Getters and setters omitted for brevity
}

Now, let’s use flatMap() to make the API calls:

WebClient webClient = WebClient.create();
Mono<User> userMono = webClient.get()
.uri("http://example.com/api/users/{id}", userId)
.retrieve()
.bodyToMono(User.class);

userMono.flatMap(user ->
webClient.get()
.uri("http://example.com/api/orders?userId={id}", user.getId())
.retrieve()
.bodyToMono(Order.class)
).subscribe(order -> System.out.println(order.getProduct()));

In this example, we first create a Mono<User> by making a GET request to the user API. We then use flatMap() to make a second API call to get the user’s order. This second API call is dependent on the result of the first API call, but because we’re using flatMap(), it doesn’t block the execution of our program.

The subscribe() method then sets up a callback that will be invoked when the user’s order is emitted. This doesn’t block the execution of the program, allowing it to continue with other operations.

Non-blocking methods like flatMap() & subscribe() are essential in reactive programming because they allow you to handle complex operations asynchronously and keep your program’s flow uninterrupted. Remember, the essence of reactive programming lies in its non-blocking nature, and adhering to this principle will help you create more efficient and responsive applications.

--

--