Reactive in the context of software development and design, they generally mean one of below things:
The
Reactive Systems is generally message-driven.
Reactive programming is all about handling asynchronous streams of data. It is concerned with data streams and the propagation of change.
The core of reactive programming is a data stream that we can observe and react to, even apply
In reactive programming, Observables
emit data, and send it to the subscribers
. This can be seen as data being PUSHed
in reactive programming, as opposed to data being PULLed
in imperative programming, where you explicitly request data (iterating over collection, requesting data from the DB, etc).
By being built around the core pillars of being fully asynchronous and non-blocking, Reactive Programming is an alternative to the more limited ways of doing asynchronous code in the JDK: namely Callback
based APIs and Future
.
Reactive programming is generally event-driven.
Reactive programming, with the concept of Functional programming is termed as functional reactive programming a.k.a FRP
.
FRP helps us to think about asynchronous programs (high-level abstractions), makes the flow of your application easier, and improves standard error handling (data structure = less code, less bugs). That is the reactive
part. The functional
part is the reactive extensions. Rx allow you to manipulate and combine streams of events. Together, that is really the power of functional reactive programming: the ability to combine functions, operate, and transform the stream of events.
Reactive Streams is an initiative to provide a standard for asynchronous stream processing with non-blocking back pressure. This encompasses efforts aimed at runtime environments (JVM and JavaScript) as well as network protocols.
The scope of Reactive Streams is to find a minimal set of interfaces, methods and protocols that will describe the necessary operations and entities to achieve the goal—asynchronous streams of data with non-blocking back pressure.
Semantics of the implementation is defined and maintained at
Using reactive programming does not build a reactive system.
Reactive programming is a great technique for managing internal logic and dataflow transformation, locally within the components, as a way of optimizing code clarity, performance and resource efficiency.
Reactive systems, being a set of architectural principles, puts the emphasis on distributed communication and gives us tools to tackle resilience and elasticity in distributed systems.
Reactive programming is event-driven, in contrast to reactive systems, which are message-driven.
message-driven system have long-lived addressable components where messages are inherently directed and have a clear (single) destination.
event-driven have dataflow-driven model where events are facts for others to observe.
To summarize, an event-driven system focuses on addressable event sources while a message-driven system concentrates on addressable recipients.
Reactive programming is an important step towards implementing a reactive system, but it is not the only way, But a Reactive System which uses reactive programming, both events and messages will be present—as one is a great tool for communication (messages), and another is a great way of representing facts (events).
Reactive programming is a programming paradigm where as Reactive Streams is a specification where as Reactive Streams gives us a common API for Reactive Programming in Java.
Reactive Streams gives us an API interface we can code to without needing to worry about the underlying implementation.
Observables
- Observables are the data source/stream that can emit multiple values, just one, or none. They can also emit errors and can be infinite or finite, in which case they emit their completion event.Subscribers
- Subscribers subscribe to Observables. They consume/observe the data and also receive the errors and completion events from the Observable.Operators
- They are used to create
, transform
, filter
or combine
Observables.Schedulers
- It is a mechanism that allows us to easily add threading to our Observables and Subscribers.The Reactive Streams API consists of just four interfaces.
Publisher
- A Subscriber
(s).A Publisher
can serve multiple Subscribers
subscribed subscribe(Subscriber)
dynamically at various points in time.
public interface Publisher<T> {
public void subscribe(Subscriber<? super T> s);
}
Subscriber
- Will receive calls to Subscriber.onSubscribe(Subscription) once after passing an instance of Publisher.subscribe(Subscriber)
.public interface Subscriber<T> {
public void onSubscribe(Subscription s);
public void onNext(T t);
public void onError(Throwable t);
public void onComplete();
}
Subscription
- A Subscriber
subscribing to a Publisher
. It can only be used once by a single Subscriber
.It is used to both signal desire for data and cancel demand (and allow resource cleanup).
public interface Subscription {
public void request(long n);
public void cancel();
}
Processor
- A Subscriber
and a Publisher
and obeys the contracts of both.public interface Processor<T, R> extends Subscriber<T>, Publisher<R> {
}
There are multiple implementations available to implement Reactive streams Flow, but most of them align to the core principals as below
Reactive Streams specification provides support for Java 1.8 by adding additional dependency to the project.
<dependency>
<groupId>org.reactivestreams</groupId>
<artifactId>reactive-streams</artifactId>
<version>1.0.0</version>
</dependency>>
Reactive Streams specification has been part of
Reactive Streams interfaces move under the
RxJava is a Reactive Extensions Java implementation library for composing asynchronous and event-based programs by using observable sequences.
It extends the
More information at
Reactor is a fully non-blocking reactive programming framework for java that integrates with java 8 functional APIs.
Spring framework version 5 introduced a reactive stack called Spring webflux which is built upon reactor and is a fully reactive non-blocking servlet stack.
Reactor exposes two main operators:
More information at
Ratpack is a set of Java libraries for building modern high-performance HTTP applications.
Ratpack uses Java 8, Netty, and Reactive principles. Ratpack provides a basic implementation of the Reactive Stream API but is not designed to be a fully-featured reactive toolkit.
More information at
Vert.x is an Eclipse Foundation project. It is a polyglot event-driven application framework for the JVM.
Reactive support in Vert.x is similar to Ratpack. Vert.x allows you to use RxJava or their native implementation of the Reactive Streams API.
More information at
Akka Streams also fully implements the Reactive Streams specification.
Akka uses Actors to deal with streaming data. While Akka Streams is compliant with the Reactive Streams API specification, the Akka Streams API is completely decoupled from the Reactive Streams interfaces.
More information at
SmallRye Mutiny is a reactive programming library. It’s an event-driven reactive programming library, supporting (Reactive Streams) based back-pressure.
It reuses ideas from Reactive eXtensions but does not follow the same API guidelines and operators. Also, it can be used to build Reactive Systems, for example, by combining, Mutiny, and
More information at
When one component is struggling to keep-up, the system as a whole needs to respond in a sensible way. It is unacceptable for the component under stress to fail catastrophically or to drop messages in an uncontrolled fashion. Since it can’t cope and it can’t fail it should communicate the fact that it is under stress to upstream components and so get them to reduce the load.
This back-pressure is an important feedback mechanism that allows systems to gracefully respond to load rather than collapse under it.
The back-pressure may cascade all the way up to the user, at which point responsiveness may degrade, but this mechanism will ensure that the system is resilient under load, and will provide information that may allow the system itself to apply other resources to help distribute the load.
To be more specific (Java – in process), exchanging data from one Thread to another needs to be a cooperative mechanism where the consuming component needs to indicate how much data it wants and the producing component needs to reciprocate up to that amount, so as not to overload the consumer. Strategies can then be designed to indicate how producers notify interested parties when the system is under strain and cannot handle any more data or possibly scale the system to meet said demands.
In concurrent programming an algorithm is considered non-blocking if threads competing for a resource do not have their execution indefinitely postponed by mutual exclusion protecting that resource.
In practice this usually manifests as an API that allows access to the resource if it is available otherwise it immediately returns informing the caller that the resource is not currently available or that the operation has been initiated and not yet completed.
A non-blocking API to a resource allows the caller the option to do other work rather than be blocked waiting on the resource to become available. This may be complemented by allowing the client of the resource to register for getting notified when the resource is available or the operation has completed.
A Flux<T>
is a Reactive Streams Publisher, augmented with a lot of operators that can be used to generate, transform, orchestrate Flux sequences.
It can emit 0 to n <T>
elements (onNext
event) then either completes or errors (onComplete
and onError
terminal events). If no terminal event is triggered, the Flux
is infinite.
Flux#subscribe()
or multicasting operation such as Flux#publish
and Flux#publishNext
will materialize a dedicated instance of the pipeline and trigger the data flow inside it.// Create a Flux that completes without emitting any item.
static <T> Flux<T> empty()
// Create a new Flux that emits the specified item(s) and then complete.
static <T> Flux<T> just(T... data)
// Create a Flux that emits the items contained in the provided Iterable.
static <T> Flux<T> fromIterable(Iterable<? extends T> it)
// Create a Flux that completes with the specified error.
static <T> Flux<T> error(Throwable error)
// Create a new Flux that emits an ever incrementing long starting with 0 every period on the global timer.
static Flux<Long> interval(Duration period)
More information at
A Mono<T>
is a Reactive Streams Publisher
, also augmented with a lot of operators that can be used to generate, transform, orchestrate Mono sequences.
It is a specialization of Flux
that can emit at most 1 element: a Mono is either valued (complete with element), empty (complete without element) or failed (error).
A Mono<Void>
can be used in cases where only the completion signal is interesting (the Reactive Streams equivalent of a Runnable
task completing).
Like for Flux
, the operators can be used to define an asynchronous pipeline which will be materialized anew for each Subscription
.
Note that some API that change the sequence’s cardinality will return a Flux
(and vice-versa, APIs that reduce the cardinality to 1 in a Flux
return a Mono
).
Mono.just(1)
.map(integer -> "foo" + integer)
.or(Mono.delay(Duration.ofMillis(100)))
.subscribe(System.out::println);
More information at