In this tutorial, you will learn about Project Reactor used to create efficient Reactive systems. The project reactor is often simply referred to as Reactor. It is based on the Reactive Stream Specification which is implemented by Project reactor and RxJava.
1. What is Project Reactor?
Technically, the Reactor is a fourth-generation reactive library, based on the Reactive Streams
specification, for building non-blocking applications on the JVM. The reactor also supports non-blocking inter-process communication with the reactor-netty project.
- It is fully non-blocking and it directly interacts with Java’s Functional API,
CompletableFuture
,Stream
, andDuration
. - Reactor offers two reactive and composable APIs, Flux [N] and Mono [0|1].
- It fits well in microservices architecture, Reactor offers backpressure-ready network engines for HTTP (including Websockets), TCP, and UDP.
- It has three main components, Reactor Core, Reactor Test, and Reactor Netty. Reactor Netty is suited for microservices architecture.
1.1. Who uses the Reactor?
The Project reactor is used in popular tools:
- In frameworks such as Spring Boot and WebFlux
- Drivers and clients such as the CloudFoundry Java Client
- In contracts or protocols such as RSocket and R2DBC
2. What is Reactive Programming?
Reactive programming is a different way of handling data and events. Here the code reacts to every event/change that happens. Code becomes cleaner and more maintainable when you use reactive programming.
In reactive programming, you consider everything as asynchronous data streams (or async event streams). These streams could be UI-events, tweets, video streams, data coming from sockets, and so on. Imagine, you have Observers assigned to these streams which can react to every event. Then there are magic functions to Filter, Combine, or even to report an error when it happens.
As you know, data can be of any forms, a stream of data, a stream of events, data from REST API, data from WebSockets, the user events such as mouse clicks, key inputs and so on. In Reactive Programming, this is what is known as Observable sequences. A function can subscribe to these Observables to receive asynchronous data whenever one arrives and they are Subscribers. Reactive programming is the Observer Design Pattern used in a slightly different way.
A Publisher
can push new values to its Subscriber
(by calling onNext
). It can also signal an error (by calling onError
) or completion (by calling onComplete
). Both errors and completion terminate the sequence.
Many says, Reactive concepts for programming is what Henry Ford’s assembly line was to cars.
2.1. What is a Stream?
A stream is considered as a sequence of data or events ordered in time, example – tweets, mouse events, socket data. These streams can emit 3 things, a value, an error (whenever anything goes wrong), or a completed signal. The completed signal indicates that the stream is closed.
In reactive concept, we will call a stream as Observable.
3. Overview of Reactive Streams Specification
I mentioned earlier, Project Reactor implements the Reactive streams specifications for JVM. Handling streams of data, especially live
data whose volume is not predetermined requires special care in an asynchronous system.
There are 4 main components of Reactive stream implementations, Publisher, Subscriber, Subscription, and Processor.
3.1. Publisher
A Publisher is a provider of a potentially unbounded number of sequenced elements, publishing them according to the demand received from its Subscriber(s).
public interface Publisher<T> {
public void subscribe(Subscriber<? super T> s);
}
3.2. Subscriber
The responsibility of the Subscriber to decide when and how many elements it is able and willing to receive. It is recommended that Subscribers request the upper limit of what they are able to process, as requesting only one element at a time results in an inherently inefficient “stop-and-wait” protocol.
public interface Subscriber<T> {
public void onSubscribe(Subscription s);
public void onNext(T t);
public void onError(Throwable t);
public void onComplete();
}
3.3. Subscription
A Subscription represents the unique relationship between a Subscriber and a Publisher. The Subscriber is in control over when elements are requested and when more elements are no longer needed. The Subscription must allow the Subscriber to call Subscription.request
synchronously from within onNext
or onSubscribe
.
public interface Subscription {
public void request(long n);
public void cancel();
}
3.4. Processor
A Processor represents a processing stage, which is both a Subscriber
and a Publisher
and must obey the contracts of both.
public interface Processor<T, R>
extends Subscriber<T>, Publisher<R> {
}
As this article focuses on the Project reactor, I will not go in-depth about each of these components, but I encourage you to try out the examples from the GitHub repo.
4. Components of Reactor core
There are several artifacts in reactor-core, reactor-test, reactor-tools, and reactor-netty. We will discuss all of them a little later, but will just focus on reactor-core at this moment.
Project reactors introduces two important reactive types that implements Publisher
are Flux and Mono.
- Mono – A Mono object represents a single value or empty value (
0 to 1
) item, e.g.Mono<HttpResponse>
. - Flux – It represents a reactive sequence of
0 to N
items. For example,Flux<Long>
.
4.1. Simple Mono example
Like I mentioned before, Mono produces a single or an empty value.
//Creates a new String Mono which emits "Hi there!"
Mono<String> message = Mono.just("Hi there!");
message.subscribe(System.out::println);
The next article, discusses Mono in details.
4.2. Simple Flux example
Flux produces zero or more number of values. The subscribe
method accepts 3 methods here.
Flux<Integer> $num = Flux.range(1, 10).log()
.map(val -> val * 2).log()
.map(val -> val + 1).log();
//Subscriber - prints 3,5,7.....21
$num.subscribe(
value -> {
System.out.println(value);
}, error -> {
System.out.println(error);
}, () -> {
System.out.println("===== Completed =====");
});
Conclusion:
The Flux and Mono will be discussed in the next articles in details. I hope to have given you a good overview of the Reactive programming.