Modern IT business needs have changed significantly compared to a few years ago. The amount of data that is being generated from various sources like social media sites, IoT devices, sensors, and the like is humongous. The traditional data processing models may not be suitable to process such a huge volume of data. Even though we have better hardware support these days, many of the existing APIs are synchronous and blocking APIs, which become bottlenecks to better throughput.

Reactive programming is a programming paradigm that promotes an asynchronous, non-blocking, event-driven approach to data processing. Reactive programming is gaining momentum and many of the programming languages provide reactive frameworks and libraries.

In Java, there are reactive libraries like RxJava and Reactor, which supports reactive programming. As interest in reactive programming grows in the Java community, a new initiative called reactive streams is starting to provide a standard for asynchronous stream processing with non-blocking back pressure. Reactive streams support will be part of the Java 9 release.

The Spring framework 5 introduced support for reactive programming with the new WebFlux module. Spring Boot 2, which uses Spring 5, also provides a starter to quickly create reactive applications using WebFlux.

Introduction to Reactive Programming

Reactive programming involves modeling data and events as observable data streams and implementing data processing routines to react to the changes in those streams. A group of people put together a Reactive Manifesto at http://www.reactivemanifesto.org/ to describe the characteristics of a reactive system.

Reactive programming is becoming popular and there are already reactive frameworks or libraries for many of the popular programming languages.

Reactive Streams

Reactive streams (http://www.reactive-streams.org/) is an initiative to provide a standard for asynchronous stream processing with non-blocking back pressure. The key components of reactive streams are the Publisher and Subscriber.

A Publisher is a provider of an unbounded number of sequence elements, which are published according to the demand received from the subscriber(s).

public interface Publisher<T> {
    public void subscribe(Subscriber<? super T> s);
}

A Subscriber subscribes to the publisher for callbacks. Publishers don’t automatically push data to subscribers unless subscribers request the data.

public interface Subscriber<T> {
	public void onSubscribe(Subscription s);
	public void onNext(T t);
	public void onError(Throwable t);
	public void onComplete();
}

Two popular implementations of reactive streams are RxJava (https://github.com/ReactiveX/RxJava) and Project Reactor (https://projectreactor.io/).

Project Reactor

Project Reactor is an implementation of the reactive streams specification with non-blocking and back pressure support. Reactor provides two composable reactive types—Flux and Mono—that implement the publisher but also provide a rich set of operators. A Flux represents a reactive sequence of 0..N items, whereas a Mono represents a single value or an empty result.

A Flux is a standard Publisher representing an asynchronous sequence of 0 to N emitted items, optionally terminated by either a success signal or an error.

A Mono is a specialized Publisher that emits at most one item and then optionally terminates with an onComplete signal or an onError. A Mono can be used to represent no-value asynchronous processes returning Mono.

Now you’ll see how to create Mono and Flux types and how to consume data from them.

Mono<String> mono = Mono.just("Spring");
Mono<String> mono = Mono.empty();

Flux<String> flux = Flux.just("Spring", "SpringBoot", "Reactor");
Flux<String> flux = Flux.fromArray(new String[]{"Spring", "SpringBoot", "Reactor"});
Flux<String> flux = Flux.fromIterable(Arrays.asList("Spring", "SpringBoot", "Reactor"));

Until you subscribe to the publisher, no data flow will happen. You must enable logging and subscribe to the flux.

Flux<String> flux = Flux.just("Spring", "SpringBoot", "Reactor");
flux.log().subscribe();

When you run this code it will log the underlying callback method invocations as follows:

[main] INFO reactor.Flux.Array.1 - | onSubscribe([Synchronous Fuseable] FluxArray.
ArraySubscription)
[main] INFO reactor.Flux.Array.1 - | request(unbounded)
[main] INFO reactor.Flux.Array.1 - | onNext(Spring)
[main] INFO reactor.Flux.Array.1 - | onNext(SpringBoot)
[main] INFO reactor.Flux.Array.1 - | onNext(Reactor)
[main] INFO reactor.Flux.Array.1 - | onComplete()

Looking at the log statements, you can see that when you subscribe to Publisher:

  • The onSubscribe() method is called when you subscribe to Publisher(Flux).
  • When you call subscribe() on Publisher, a subscription is created. This subscription requests data from the publisher. In this example, it defaults to unbounded and hence it requests every element available.
  • The onNext() callback method is called for every element.
  • The onComplete() callback method is called last after receiving the last element.
  • If an error occurs while consuming the next element, then onError() callback would have been called.

This blog is the introduction to reactor project which gives us the Mono and Flux to work with Asynchronous and non-blocking paradigm. It serves as the foundation of spring 5 support for reactive programming.