Spring Framework adopted reactive in 2013 (the same time reactive was born and became more mainstream) with the release of Version 1.0 of Reactor. This was the time when Spring Framework Version 4.0 was released and Spring got itself engaged with Pivotal. In 2016, Spring's 4.3 Version was released with Reactor's Version 3.0. Around this period, the work on Spring's Version 5.0 (major version) was actively under construction.
With new-generation application requirements, many conventional coding practices were challenged. One of the main aspects was to get rid of blocking IO and to find an alternative to conventional imperative programming.
Web applications backed by a Servlet container are inherently blocking, and Spring 5 did a great deal in web application development by introducing a fresh web application framework based on reactive programming: Spring WebFlux.
Spring also has embraced Rx and has used it in many ways within Spring 5. With Spring 5, reactive features are baked into it in many aspects, helping developers to embrace reactive programming easily in a slow-paced manner.
Pivotal is heavily invested in Reactor but has exposed APIs, allowing developers to choose the library of their choice between Reactor and RxJava.
The following diagram depicts Spring 5's reactive programming support:
Figure 5: Spring Framework + Reactor + Rx
Reactor is Pivotal's (SpringSource) answer to implementing Reactive Streams Specification. As mentioned earlier, Spring is heavily invested in Reactor and this section aims to delve a bit deeper into Reactor.
Reactor is a fourth-generation reactive library for building non-blocking applications on the JVM based on the Reactive Streams Specification.
An overview of the history of Project Reactor can be pictorially represented in the following figure:
Figure 6: Project Reactor history
The figure above shows the major releases of Project Reactor. The project kick started in the year 2013 (1.x version) and the major release of 3.x was released in the year 2016. As of writing this book, the core module of the framework is at version 3.1.8.RELEASE.
Now that we have a brief understanding of Spring Framework and its connection with reactive programming, lets dive a bit deep into Project Reactor.
With the latest release of Reactor 3.0 the project has been structured with modularity in mind. Reactor 3.0 consists of four major components namely Core, IO, Addons, and Reactive Streams Commons.
- Reactor Core (https://github.com/reactor/reactor-core): The main library within Reactor. It provides foundational, non-blocking JVM-compliant Reactive Streams Specification implementations. It also contains code for Reactor types, such as
Flux
andMono
. - Reactor IO (https://github.com/reactor/reactor-ipc): It contains backpressure-ready components that can be used to encode, decode, send (unicast, multicast, or request/response), and then serve connections. It also contains support for Kafka (https://kafka.apache.org/), Netty (http://netty.io/), and Aeron (https://github.com/real-logic/aeron).
- Addons (https://github.com/reactor/reactor-addons): As the name suggests, these are add-ons that consist of three components:
reactor-adapter
: Contains a bridge to RxJava 1 or 2 types, such as Observable, Completable, Single, Maybe, and Mono/Flux back and forth.reactor-logback
: Supports logback over asynchronous reactor-core processors.reactor-extra
: Contains more operations forFlux
, which include mathematical operations such as sum and average.
- Reactive Streams Commons (https://github.com/reactor/reactive-streams-commons): A collaboration experiment project between Spring's Reactor and RxJava. It also contains Reactor-Streams-compliant operators that both projects implement. Issues fixed on one project are also fixed on the other.
Reactor provided two reactive types, Flux
and Mono
, that implement Rx extensively. They can be represented as a timeline in which elements are sequenced according to how they arrived. It is important that you get the hang of these two types. Let's do that in the following subsections.
A Reactive Streams publisher with Rx operators that emits 0 to N elements, and then completes (successfully or with an error). For more information, you can check the following link: https://projectreactor.io
Flux<T>
is a Publisher<T>
with basic flow operations and supports 0..n elements.
The definition of Flux
is as follows:
public abstract class Flux<T> extends Object implements Publisher<T>
The following figure, as depicted in the Flux
documentation, explains the working of Flux
in more detail:
Figure 7: Working of Flux
Flux support is in Spring 5 and a variety of other important modules, including Spring Security. Operators acting on Flux
would create new publishers.
Please refer to the Reactor Flux documentation for more information: https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html.
Now, let's have a look at some code examples where usage of Flux
is shown:
- Creating empty
Flux
:
Flux<String> emptyFlux = Flux.empty();
- Creating
Flux
with items in it:
Flux<String> itemFlux = Flux.just("Spring”, "Security”, "Reactive”);
- Creating
Flux
from an existing list:
List<String> existingList = Arrays.asList("Spring”, "Security”, "Reactive”); Flux<String> listFlux = Flux.fromIterable(existingList);
- Creating
Flux
that emits everyx
milliseconds in an infinite manner:
Flux<Long> timer = Flux.interval(Duration.ofMillis(x));
- Creating
Flux
that emits an exception:
Flux.error(new CreatedException());
A Reactive Streams Publisher with basic Rx operators that completes successfully by emitting an element, or with an error.
– Mono JavaDoc
Mono<T>
is a Publisher<T>
that supports 0..1 elements.
The definition of Mono
is as follows:
public abstract class Mono<T> extends Object implements Publisher<T>
As detailed in the documentation, the following figure shows the workings of Mono
:
Figure 08: Working of Mono
Mono<Void>
should be used for a Publisher
that completes with no value. The documentation explains each method and how it works using a marble diagram, which is self-explanatory. Again, this type is also supported by Spring 5 and Spring Security.
JavaDoc for Mono
contains more information: https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html.
Let's have a look at some examples:
- Creating empty
Mono:
Mono<String> emptyMono = Mono.empty();
- Creating
Mono
with a value in it:
Mono<String> itemMono = Mono.just("Spring Security Reactive”);
- Creating
Mono
that emits an exception:
Mono.error(new CreatedException());
Broadly, data streams can be categorized into two types:
- Cold data streams: There are a number of names by which this is known, such as Cold Source, Cold Observable, and Cold Publisher. These emit data only when one subscribes to it and because of this, all messages produced from start are delivered to the subscriber. If a new
Subscriber
connects to it, the messages are replayed in ascending order and this is same for any newSubscriber
. TheSubscriber
also has a provision to dictate the rate at which thePublisher
should emit messages. These data streams are good candidates for applying reactive backpressure (request(n)
), for example, a database cursor or file stream (reading a file). - Hot data streams: Again, this has a number of different names, such as Hot Source, Hot Observable, and Hot Publisher. These emit data irrespective of any subscribers connected. When a new
Subscriber
connects, it just emits the messages from that point in time and cannot replay messages from the start. These cannot pause message emissions, so an alternate mechanism is required to control flow, such as a buffer. Examples of this stream include mouse events and stock prices.
It's important to note that operators on a stream can change their property, going from cold to hot and vice versa. Also, there are times when a merge between hot and cold can happen and their properties change.
One of the main aspects between the two is RxJava 2.x which is Java 6+ compatible, but Reactor is Java 8+ compatible. If you are going with Spring 5, I urge you to use a Reactor. If you are comfortable with RxJava 2.x, there is no need to migrate to Reactor. Reactor is an implementation of the Reactive Streams Specification, so you can remain agnostic of what the underlying implementation is.
Spring 5 has brought reactive concepts into the world of web application development with the inclusion of a number of important components. Let's cover them here.
Spring 5 has a reactive stack baked into it, using which, web applications can be built on top of Reactive Streams capable of running on new non-blocking servers, such as Netty, Undertow, and Servlet containers, running on Servlet specifications greater than 3.1.
Existing web application frameworks, such as Spring MVC, are built for Servlet containers from the outset, but Spring 5 brings with it a new web application framework, Spring WebFlux, created with reactive in mind. We have a dedicated chapter in this book covering Spring WebFlux (Chapter 5, Integrating with Spring WebFlux), so I won't be delving deep into this here. It's good to know that Spring 5 has serious thoughts on reactive and that it is reflected clearly in all these new additions.
Spring WebFlux requires Reactor to be included as one of its core dependencies. But, as always, it does allow you to switch implementations quite easily, if needs be.
The Spring Web Module (https://github.com/spring-projects/spring-framework/tree/master/spring-web) has many foundational pieces used to build reactive web applications. It allows you to do operations pertaining to the server and the client.
The capabilities that it provides on the server are divided into two areas:
- HTTP: Contained within the
org.springframework.http
package inspring-web
and contains various APIs for HTTP request handling for supported servers - Web: Contained within the
org.springframework.web
package inspring-web
and contains various APIs for request processing
This module also contains message codecs that work on the client and aid in encoding and decoding requests and responses. These codecs can also be used on the server.
The interface org.springframework.web.reactive.function.client.WebClient
is a reactive web client introduced in Spring 5 that can be used to perform web requests. Similarly there is org.springframework.test.web.reactive.server.WebTestClient
interface, which is a special WebClient
—used to write unit tests within your application. WebClient
is the reactive version of RestTemplate
, which works over the HTTP/1.1 protocol. They are packaged as part of the spring-webflux
module.