Techwondoe

Reactive Programming - Part 1.

RP-1
21 Nov 2022

Introduction

Before I talk about this blog, I do want to declare my honest intentions, I want to reignite the spark in the dev community for Java. Over the past decade itself, the number of organisations that used to use Java has declined. If you check the TIOBE index you can see that as of December 2021 Java is the 3rd most popular language whereas it was the most popular language back in 2011 and even back in 2016 it was the most popular language. Anyway, this blog is not about explaining why the decline happened or why the world is moving to other languages but this blog is just an attempt from me to educate the world that like other languages Java too has also evolved with the time and is now an even more mature language then it was 10 years ago and what better way to prove it other than talking about one of the best features of Java i.e. Reactive Programming 5 Things to Know About Reactive Programming | Red Hat Developer

What Is Reactive Programming

Let's make a start by understanding the jargon I just coined above i.e. Reactive Programming. According to Wikipedia:

Reactive programming is a programming paradigm oriented around data flows and the propagation of change. This means that it should be possible to express static or dynamic data flows with ease in the programming languages used, and that the underlying execution model will automatically propagate changes through the data flow.

In simpler terms, Reactive programming is a programming paradigm where the main focus is to build asynchronous and non-blocking components and the interactions between these components happen via streams and events.

Reactive programming can be represented as the combination of

  • Streams: A sequence of data values over time

  • Observable: An Observable is basically a function that can return a stream of values to an observer over time. The data can be returned synchronously or asynchronously.

  • Observers: An observer is someone who subscribes beforehand and acts as the receiver of the data

  • Schedulers: Schedulers are like thread management that tell the observable and observers about which threads to run on.

Reactive vs Thread Based Programming

Before we jump into the coding part of this blog, let us first look at what are the main differences and when should we use reactive programming vs when should we use thread-based programming.

Execution Style

  • Thread Based - Pull Based - Pull based code doesn’t react to data arriving, instead, it gets ready to process data and only then ask for data.

  • Reactive - Push Based - In this style, the data arrives regardless of whether the code is ready to process it or not.

Thread Usage

  • Thread Based - For each request a thread is created

  • Reactive - Number of threads are limited (usually number of CPU cores - 1) and tasks are managed by event loop

Memory Consumption

  • Thread Based - Each thread consumes around ~512 KB - 2MB and this model can lead to memory issues

  • Reactive - Memory is not wasted in multiple thread creation

Context Switching

  • Thread Based - Thread scheduling causes frequent context-switching (which is CPU intensive)

  • Reactive - Thread context switching is prevented and thus using this approach we won’t run into race condition

Throughput

  • Thread Based - Throughput is un-predicatable

  • Reactive - Throughput is predictable.

We will keep this blog short as just getting a basic understanding of reactive programming can be a bit too much. In the next blog we will go through an example of how exactly would you apply reactive programming in a live application.

Learning Through Example

Now let us further expand our knowledge by learning how to do reactive programming using one of the most popular libraries i.e Reactor Core. Reactor Core is a Java 8 library that implements the reactive programming model, it is built on top of reactive stream specifications, which is a standard for building reactive applications. Let us quickly look at the common building blocks of Reactor Core, so that we can form an understanding before we dive into it further

  • Publisher

    • Flux: Flux is a generic and standard publisher in Reactor which can produce data/event of type <T> and can produce from 0 to N values asynchronously.

    • Mono: Mono is simply a publisher which can produce 0 or at most 1 value

  • Subscriber: A subscriber is someone who has subscribed to receive events, unless subscribed you can’t receive events published by the publisher.

  • Subscription: Represents the relation between a subscriber and a publisher

  • Scheduler: A scheduler has responsibilities similar to Executor Service in a thread-based model to schedule events between a publisher and a subscriber.

Project Description

In the below example all we are doing is creating a simple CRUD API, reactive style. Where-in you would be able to make API calls to add a new user, update an existing, read all your users and eventually delete a user. We are going to learn how and when to use Flux and Mono publishers, how to use ReactiveCrudRepository of Spring data and understand how everything works internally.

There are two styles of programming-model: Annotation-based Programming model: The same @Controller programming model and the same annotations as used in Spring MVC, the difference being the underlying core, framework contracts Functional Programming model: Lambda based, lightweight and uses a functional style of programming. You can read more about the above two approaches here

Project Setup

I will be using IntelliJ Idea for this tutorial, you are welcome to pick any IDE of your choice. For the initial setup follow these steps

  • Click on New Project

  • Select Spring Initializr and fill out the basic information like Name, Location, Group, Artifact etc

  • As I am creating an example project to add a new user and retrieve users, these are the values I am going to put

    • Name: user-reactive-example

    • Location: ~/Documents/example/user-reactive-example

    • Language: Java

    • Type: Maven

    • Group: com.techwondoe

    • Artifiact: user-reactive-example

    • Package name: com.techwondoe.userreactiveexample

    • Project SDK: 11 Amazon Corretto version 11.0

    • Java: 11

    • Packaging: Jar

  • Click on Next and select the following dependencies

    • Spring Reactive Web: Build reactive web application with Spring WebFlux and Netty.

    • Spring Data R2DBC: Provide reactive relational database connectivity to persist data in SQL stores using Spring Data in reactive applications.

    • Lombok: Java annotation library which helps to reduce boilerplate code

    • H2 Database: Provides a fast in-memory database that supports JDBC API and R2DBC access, with a small (2MB) footprint. It is required for Integration testing.

    • Postgres SQL Driver: Postgres JDBC and R2DBC driver

  • Once all the above dependencies are selected click on Finish and wait for the project to get initialised.

  • After initialisation see if you have the following dependencies defined in your project

<dependencies>
    <dependency>
        <groupId>
          org.springframework.boot
      </groupId>
        <artifactId>
          spring-boot-starter-webflux
      </artifactId>
    </dependency>
    <dependency>
        <groupId>
          org.springframework.boot
      </groupId>
        <artifactId>
          spring-boot-starter-data-r2dbc
      </artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>io.r2dbc</groupId>
        <artifactId>r2dbc-h2</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>io.r2dbc</groupId>
        <artifactId>
          r2dbc-postgresql
      </artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>
          org.projectlombok
      </groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>
          org.springframework.boot
      </groupId>
        <artifactId>
          spring-boot-starter-test
      </artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>
          org.springframework.data
      </groupId>
        <artifactId>
          spring-data-relational
      </artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>
          io.projectreactor
      </groupId>
        <artifactId>
          reactor-test
      </artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
  • If at all you see any of them missing, add them and refresh your dependencies.

Database Setup

  • In case you don’t have Postgres already installed, please do so

  • Update application.properties with database URL, username, password like shown below

spring.r2dbc.url=r2dbc:postgresql:
//localhost:5432/postgres?
currentSchema=user_reactive_db
spring.r2dbc.username=postgres
spring.r2dbc.password=postgres
  • Execute the following SQL script to create the necessary schema and table

CREATE SCHEMA user_reactive_db;
SET SCHEMA 'user_reactive_db';
create table users (
id INT GENERATED BY DEFAULT
AS IDENTITY PRIMARY KEY,
name VARCHAR(100) NOT NULL,
age integer,
salary decimal
);

So that is enough information overload for one blog. Hopefully all of the above made sense, I have written a follow-up blog which talks about the exact usage of reactive libraries throughout the MVC layer and also how to write test cases against it. So please have a read through it to get a full understand of reactive programming.