
In the previous chapter we understood what is reactive programming and it’s characteristic. Before we proceed further, let’s try to understand one of the main concept/foundation behind reactive programming, which is Reactive Streams.
Reactive Streams
Reactive Streams is a specification for reactive programming created jointly by multiple organisation. These specifications are as follows —
Publisher
A Publisher is a provider of a potentially unbounded number of sequenced messages, publishing them according to the demand received from its Subscriber(s). Additionally a Publisher can serve multiple Subscriber(s) dynamically at various points in time.
The Publisher interface looks like as follows —
public interface Publisher<T> {
public void subscribe(Subscriber<? super T> s);
}
With the help of subscribe(Subscriber<? super T> s) method, we can request the Publisher to start streaming data to it’s Subscriber(s).
In real world, the Publisher represents Database, remote service or other data sources.
Subscriber
The consumer/receiver of the messages needs to implement Subscriber interface. Typically this is the end for every Flow processing because the instance of it does not send messages further.
The Subscriber interface looks like as follows —
public interface Subscriber<T> {
public void onSubscribe(Subscription s);
public void onNext(T t);
public void onError(Throwable t);
public void onComplete();
}
onSubscribe(Subscription s) is called before data processing. The passed argument of Subscription instance is used to control the flow of data between Publisher and Subscriber.
onNext(T t) is invoked by the Publisher in order to transfer the data to Subscriber. This method is keep getting invoked until Subscription stops requesting for new data or there are no more data available in the data source (Publisher).
onComplete() is invoked by the Publisher to notify that there are no more data available.
onError(Throwable T) is invoked when something goes wrong. Once onError method is invoked, no more further data will sent even if there are new requests from Subscription.
Subscription
A Subscription represents a one-to-one lifecycle of a Subscriber subscribing to a Publisher. It can only be used once by a single Subscriber. The Subscription is use demanded data or cancel demand (which allows to cleanup the resources) from Publisher.
The Subscription interface looks like as follows —
public interface Subscription {
public void request(long n);
public void cancel();
}
request(long n) method in used to demand n numbers of data from the Publisher. No data will be transferred from Publisher until demand is signalled.
cancel() method is used to request the publisher to stop sending further data and cleanup the resources. Some data may still be sent to fulfil the demand from previous request.
Processor
A Processor represents processing stage, which has characteristic of both Subscriber and Publisher. This specification is not really used in day to day basis.
The Processor interface looks like as follows —
public interface Processor<T, R> extends Subscriber<T>, Publisher<R> {}
Conclusion
In summary, Reactive Streams revolutionise application development, offering resilience, responsiveness, and scalability. Standardizing asynchronous data handling, they empower real-time event response. Embracing these principles is pivotal for staying ahead in software development’s dynamic landscape.
This article is a segment of the Cooking up Reactivity: The Spring Way series. To explore the entire series, click here.
Originally posted on medium.com.