Reactive Programming in Java-RxJava

Jitendra Godani
Globant
Published in
5 min readJun 9, 2022

Reactive Programming is an another paradigm just like other Procedural, Object Oriented and Functional Programing. Reactive programming is a programming paradigm that promotes an asynchronous, non-blocking, event-driven approach to data processing. Reactive programming involves modeling data and events as observable data streams and implementing data processing routines to react to the changes in those streams.

In the reactive style of programming, we make a request for the resource and start performing other things. When the data is available, we get the notification along with data in the form of call back function. In the callback function, we handle the response as per application/user needs.

There is four pillar to move towards Reactive Programming -
1. Responsive
2. Resilient
3. Elastic
4. Message Driven

  1. Responsive : Responsiveness means that problems may be detected quickly and dealt with effectively. Responsive systems focus on providing rapid and consistent response times and quality of service. For example, in the case of a web application, if a user clicked a button to download some data from the Internet and show it on the screen, we would register a callback, show a loading screen at the same time, and return the execution back. At this point, the user can still interact with the screen, cancel this request, or select another option. Earlier, in our button click handler, if we didn’t register a callback and synchronously load the data, then the whole screen would be non-responsive until our operation is done. So this is an example where we have designed our system to be responsive.

Below is asynchronous and non-blocking example -

Here we use Observable.fromCallable() to create an Observable (the observer). The fromCallable method creates a lazy Observable, and the incoming code is executed only when someone listens to it.
Then, you can use subscribeOn(Schedulers.io()) to specify the thread pool executed by the observer. observeOn(Schedulers.single()) specifies the thread pool that the downstream observer executes. (*The map method is an observer.) The map method, like many stream programming APIs, transforms each upstream element into another element. Finally, the current downstream observer, which refers to the thread pool executed by the incoming observer (Lambda mode) in the last subscribe, is formulated through observeOn(Schedulers.newThread()).

After the preceding code is executed, the printed thread name shows that the observed, map, and observer are all different threads, and the last “end” of the main thread will be executed first. This means asynchronous non-blocking is implemented.

2. Resilient : Resilient means system stays responsive at the time of failure. Resilience is achieved by replication, containment, isolation and delegation. Failures are contained within each component, isolating components from each other and thereby ensuring that parts of the system can fail and recover without compromising the system as a whole. Recovery of each component is delegated to another (external) component and high-availability is ensured by replication where necessary. The client of a component is not burdened with handling its failures.
In a microservice architecture, this is especially important because as we move away from monolithic solutions to disaggregated architectures that are network accessible, the unreliable nature of the network is something we cannot ignore. For example, in Microservice we make use of the circuit breaker pattern in short-circuiting a failing backend service to immediately respond to the caller until the backend service is healthy again. An example of this can be seen below -

  1. Add spring-cloud-starter-netflix-hystrix dependency in pom.xml
  2. Add @EnableHystrix annotation on application class:
    This annotation enables the Circuit breaker implementation. It tells the Spring that circuit breaking is being used in this application.

3. Specify the fallback method using @HystrixCommand annotation:

Spring Cloud Netflix Hystrix looks for the methods annotated with @HystrixCommand annotation. It makes the method fault tolerant. Using it we can specify the fallback method which will be executed in case of an error, timeout or circuit break situation.

4. Add below properties in application.properties:

hystrix.command.default.circuitBreaker.requestVolumeThreshold=2
hystrix.command.default.metrics.rollingStats.timeInMilliseconds=10000
hystrix.command.default.circuitBreaker.errorThresholdPercentage=50
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=30000

With all the above steps Resilient can be achieved for Microservice architecture, where system will always return response at the time of service failure.

3. Elastic : The system stays responsive under varying workload i.e. it can handle N no of request and capable of load balancing them. It has the ability to spin up new instances of services and also to discover new endpoints to communicate with them. With the advent of cloud computing platforms, these services have become a commodity now. This has been accelerated with the adoption of container-based technologies like Docker, and container orchestration systems like Kubernetes.

4. Message Driven : System rely on asynchronous flow of execution, where we send request to server and flow continues with next step of program without waiting for first response as it gets handled by callback mechanism once response is available.

Message-driven system approach is also used by Microservices architecture. This enforces loose coupling, isolation, and better resilience against failures. In using message passing, we make sure future extensions of the system such as adding new services that consume an existing service can be done seamlessly without redeploying any of the existing services in the system. The best practices in microservices architecture, supports many leading messaging solutions in its standard library, such as NATS, Kafka, and RabbitMQ.

Message-driven microservices

Conclusion :
Here we had talked about Reactive Programming and its importance in Java with detail explanation of four pillars which help in moving towards Reactive Programming with examples and code snippet for better understanding.

You can comment if anything is confusing or want to add your ideas or content in this article.

Thank you for your time!

--

--