Saturday, December 30, 2017

Going Reactive with Spring - Spring WebFlux - Part 1

Spring is one of the most popular frameworks used by Java-Developers. Manageable learning curve of Spring has lift it to the top of most-used Java-Framework through out the world. The latest of Spring Family has arrived recently with the flavor of Reactive-Programming in-built to it. This article series is about building a robust-reactive API using spring-webflux.

What is Reactive-Programming ?


Reactive Programming is a programming paradigm where you program with asynchronous-data-streams. In Imperative-Programming we get the data and perform actions on it. But in Reactive-Programming we don't wait for data to present to perform actions rather we instruct what to do when data is available. If you are new to Reactive-Programming I would recommend you to first go through my-article on Reactive-Programming before you start here.

The basic-building blocks of Reactive-Programming is Data-Streams. Data-Stream is like a pipe. From one end we put-data into it and from the other end we will retrieve the data. But we will not pull out the data, but the data will be pushed when it is available. 

In Spring-Webflux, there are two types of Data-Streams, namely Mono and Flux. As the name infers Mono is a data-stream which contains at most one element. In the other hand Flux is a data-stream containing more-than one element. Mono and Flux are derived from Project-Reactor as Spring-Webflux is built on top of Reactor.

Starting with Reactor


Before we dive into Spring-Webflux we should first understand the concept of Mono and Flux
So, lets take a look at how we can compose a Mono.
  Mono<String> sampleMono = Mono.just("sample_mono");
As we can see, this is a Mono which is composed with a single String in it. If we can only use single elements in a data-stream then the concept becomes useless. So that is how Flux come into play. Lets see how we can compose a Flux.
Flux<String> sampleFlux = Flux.just("sample1", "sample2", "sample3");
So, we can compose a data-stream of any type(reference-type) using Mono.just(...) and Flux.just(...). But, in Reactive world a data-stream is the laziest person you can find. Even though you composes and apply some functions on the data, stream might not give you the result unless you have subscribed to the stream. This means data-stream would do nothing unless you have subscribed to it. Lets see how we can subscribe and get the data out.
sampleMono.subscribe(data -> System.out.println(data));
So, if you run the code you will see sample_mono will be printed out in the console. But, this is just a shorthand of writing a Subscriber. A Subscriber is composed with four-functions. onSubscription, onNext, onError and onComplete which will be called out in different stages in subscription. onSubscription will be called when the subscription is started. onNext will be called when the next data item is available in the stream. onError as the name propose will be called when an error occurred in the stream. And finally onComplete will be called when the subscription is completed.
In Reactor there is a Subscriber interface which you can implement and provide as a subscriber to stream. Lest see how we can implement a subscriber for our sampleFlux.
        Subscriber<String> subscriber = new Subscriber<String>() {
            @Override
            public void onSubscribe(Subscription subscription) {
                System.out.printf("Subscription Started");
            }

            @Override
            public void onNext(String s) {
                System.out.println("Next : "+s);
            }

            @Override
            public void onError(Throwable throwable) {
                throw new RuntimeException(throwable);
            }

            @Override
            public void onComplete() {
                System.out.printf("Subscription Completed");
            }
        };
        sampleFlux.subscribe(subscriber);
If you run this code you will see that onSubcription will be called in the first place. And for every element in the stream onNext will be called after every element is over onComplete will be called. You can find out some interesting samples on reactor in this article.