This article is about an app I've made for learning the basics of Reactive Programming in Java.
It was in reaction to the lack of practical sources that I've decided to make it on my own.
There's a lot of resources already available, and I really thank all the authors for giving me the ABC of this definitely new programming paradigm, but they often describe the same concepts and basic stuff. It is important of course, but the subject is hard when time comes to make it concrete and working.
This post is an introduction. I need it to explain my motivations and convince you that the points I will mention are relevant. Explanations about the app itself will come in the next post that I'm actively writing.
Before you start, you have to know the followings :
- this technology is quite recent in the Java world. Spring's engeeniers work hard on it. Things you learn today may change.
- this technology just begins to be used in enterprises. People mostly don't know anything about it.
- this technology has a hard learning curve
You can find the app on my Github repo.
ReactivePipeline is a simple library of my own, built around the TaskPipeline project.
Its aim is simply to provide a clear single class, named
ReactiveContext, with a few static methods providing all necessary objects to build a simple yet working reactive application. Under the hood, there's the Spring's Reactor project, a very little part to be honest.
Why did I do that ? For both the pleasure of learning reactive programming and share that little knowledge with the ones who are interested in it, the ones who would like to learn more but have not enough time, and maybe the ones who, just like I do, remain hungry after reading available tutorials.
If you have ever read some tutorials about reactive programming, maybe did you tell yourself that creating a Flux was not the most difficult part.
Take a simple example from Baeldung's post related to Reactor core :
With such code :
List<Integer> elements = new ArrayList<>(); Flux.just(1, 2, 3, 4) .log() .subscribe(elements::add); assertThat(elements).containsExactly(1, 2, 3, 4);
you will produce this result in the console, thanks to the
.log() statement :
20:25:19.550 [main] INFO reactor.Flux.Array.1 - | onSubscribe([Synchronous Fuseable] FluxArray.ArraySubscription) 20:25:19.553 [main] INFO reactor.Flux.Array.1 - | request(unbounded) 20:25:19.553 [main] INFO reactor.Flux.Array.1 - | onNext(1) 20:25:19.553 [main] INFO reactor.Flux.Array.1 - | onNext(2) 20:25:19.553 [main] INFO reactor.Flux.Array.1 - | onNext(3) 20:25:19.553 [main] INFO reactor.Flux.Array.1 - | onNext(4) 20:25:19.553 [main] INFO reactor.Flux.Array.1 - | onComplete()
Of course, the
.subscribe() statement does the job and will fill the
elements collection with each received value. The assertion confirm that.
But... don't you find this very frustrating ?
As you can see, there's no difficulty in creating a Flux dispatching integer values before putting each of them in a collection.
But it is not sufficient, because for me the main question is :
How to maintain a process as a Flux from the beginning to the end of our processing operations ?
My main objective in writing this app, consequently, was to find out a simple way to keep all operations reactive, from the very first one to the very last one. Because writing a reactive app is just like a relay race : when a runner is about to end his tour, the next runner has already started to run so that there's no waiting time, no speed loss at the very moment of passing the baton.
This is why reactive programming seems a good alternative to imperative paradigm.
Imperative programming is our everyday-way of making our job. We know it so much that we don't question it and accept its constraints for 2 main reasons :
- it is normal to do as we learnt to, but the way we learnt is also induced by the procedural nature of most of the languages
- it is the way our brain works : cause -> consequence in a single thread and sequentially
In an imperative programming style, we use to design operations that will be executed one after the other.
methodA(...) --> methodB(...) --> methodC(...)
methodA(...) is called, it does its stuff and triggers the next method when ending. During this time,
methodB(...) is waiting, and so is
Of course, we all know some workarounds like iterating on a collection and parallelizing calls to
methodB(...) and then
methodC(...). But we have to deal with threads, what is funny in fact but hard to debug in fact too.
Or we can of course exploit all the possibilities of Functional programming, like parallel-streaming collections, but code will quickly become unreadable with functions into functions into functions...
Think about a call to a repository that is returning many objects. You won't be able to process any of these results before the database server has returned its result set. It could be a request taking a long time, and nothing happens in the meanwhile.
At the opposite, reactive programming will send you objects from the repository each time one is found. While the database server is still processing your request, you can start processing what has already been found so far.
A reactive app can run faster not because it is intrinsically faster but just never waits.
Never waiting is what we want to design and build. We want pipes with
liquid data flowing inside. We want a Flux.
This is what the ReactivePipeline is about : create a persistent Flux across the whole application.
Does-it mean that there's no reactive code to write ?
No. I will talk to you about the
Operation class that is a pure reactive object.
Does-it mean that you won't have to wire all operations in a
continuous flux by yourself ?
Yes. I will talk to you about the
Pipeline classes that are dedicated to wire operations together so easily.
Is it the perfect app for making things in a reactive way ?
Well, I guess that once you will understand how this modest project works, you will have all the necessary knowledge to use pure Spring Reactor classes. Just take it as a work-in-progress library, with known defaults, that can be improved in so many ways (I will transparently talk about too).
See you next time for practical things : Reactive Pipeline : the App
Written with StackEdit.