Reactive programming with Project Reactor

Reactive Programming

  1. Asynchronous and Non blocking.
  2. Data flow as Event/Message Driven stream
  3. Functional Style Code
  4. Backpressure or the ability for the consumer to signal the producer that the rate of emission is too high.
  5. Nothing happens until you subscribe.

Advantages of Reactive Programming

  1. Cleaner code, more concise
  2. Easier to read (once you get the hang of it)
  3. Easier to scale (pipe any operation)
  4. Better error handling
  5. Event-driven inspired
  6. Backpressure (client can control flow)

Reactive Stream Specification

  • Publisher: A source of data (from 0 to N signals where N can be unlimited). It optionally provides for 2 terminal events: error and completion.
  • Subscriber: A consumer of a data sequence (from 0 to N signals where N can be unlimited). It receives a subscription on initialisation to request how much data it wants to process next. The other callbacks interact with the data sequence signals: next (new message) and the optional completion/error.
  • Subscription: A small tracker passed on initialisation to the Subscriber. It controls how much data we are ready to consume and when do we want to stop consuming (cancel).
  • Processor: A marker for components that are both Subscriber and Publisher!
Publish-Subscribe Model

Reactor Core Features

Flux — 0 to N elements

Flux<String> stringFlux = Flux.just("Spring", "Spring Boot", "Reactive Spring").log(); stringFlux
.subscribe(System.out::println,
(e) -> System.err.println("Exception is " + e)
, () -> System.out.println("Completed"));
Output of the above code
Flux<String> stringFlux = Flux.just("A", "B", "C").log()
.concatWith(Flux.error(new RuntimeException("Exception Occurred")))
.concatWith(Flux.just("D"))
.onErrorResume((e) -> { // this block gets executed
System.out.println("Exception is : " + e);
return Flux.just("default", "default1");
});


stringFlux.subscribe(System.out::println);
Mono.just(1).log()
.map(integer -> "foo" + integer)
.subscribe(System.out::println);

Backpressure

Publisher produces the stream of data and a Subscriber that consumes data. If the rate at which a Consumer consumes data is less than the rate at which a Producer produces data (referred to as a Fast Producer/Slow Consumer), then signals from the consumer can constrain the rate of production. In this consumer will never be able to catch up.

Backpressure
Flux<Integer> finiteFlux = Flux.range(1, 10)
.log();

finiteFlux.subscribe((element) -> System.out.println("Element is : " + element)
, (e) -> System.err.println("Exception is : " + e)
, () -> System.out.println("Done")
, (subscription -> subscription.request(2)));
Output

Conclusion

So this is the basic of reactive programming and project reactor capabilities.There are multiple reactive toolkits available, project reactor is one of them. Though it takes time to grasp reactive programming but it is worth the features it comes with and its capabilities. Project reactor handles much of the complexity of timeouts, threading, backpressure, and so forth, freeing us to think about the bigger picture of how signals flow through our systems.For more details you can follow the documentation:https://projectreactor.io/docs/core/release/reference/#getting-started

--

--

SDE-3 at PayPal

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store