This tutorial will introduce you to basic concepts of reactive programming along with Java libraries to achieve this.
Reactive programming has been picking up pace lately due to its effective concurrent processing capabilities. In simplest terms, Reactive programming is about registering callbacks to an event to allow callback executions whenever a concerned event is occurred. This avoids the need of polling for events and hence facilitates the optimized usage of system resources such as threads, memory, CPUs etc.
CompletableFuture class in Java is one of the basic examples of Reactive programming as you register completion, success or error callbacks to the executing threads. A more advanced support for Reactive programming will be introduced in Java 9.
However, in order to understand Reactive programming, one needs to have basic knowledge of Functional programming. Functional programming helps you make your code thread-safe and predictable. Here are the basic concepts of Functional programming -
- Pure functions - These represent the functions that return same output for the same input irrespective of any state i.e. these functions don't utilize internal mutable/random state to process input data.
- Functions as first class citizens - This refers to ability to store a function as a variable and pass function as parameter. In coding terms, functions can have types and be assigned to variables.
- High order functions - These represent the functions that can return a function. It is quite useful for Lazy execution and one of the basic idea of Reactive programming.
Java 8 has introduced Lambda functions to support Functional programming in Java. You can get up to speed with Lambda by following tutorial - Working with Lambda Expressions in Java.
After getting the basic idea of Reactive programming, it's now time to talk about Reactive Manifesto.
Reactive Manifesto is basically an online document that defines the tenants of Reactive Programming. These tenants define the behaviors that an application need to exhibit in order to be qualified as Reactive Application -
- Responsive - Reactive applications need to respond in a timely manner if at all possible. Responsiveness means that problems may be detected early and dealt with effectively. Responsive systems tend to provide rapid and consistent response times. This consistent behavior builds end user confidence and encourages further interaction.
- Resilient - It means that application stays responsive even in case of any failures. Any application that is not resilient will not be responsive after a failure. Resilience is achieved by replication, containment, isolation and delegation.
- Elastic - Elasticness talks about responsiveness in case of varying workloads. Reactive applications react to changes in the input rate by increasing or decreasing the resources allocated to service these inputs. This implies designs that have no contention points or central bottlenecks, resulting in the ability to shard or replicate components and distribute inputs among them.
- Message Driven - Reactive applications rely on asynchronous message-passing to establish a boundary between components that ensures loose coupling, isolation and location transparency. This boundary also provides the means to delegate failures as messages. Message driven paradigm is slightly different from Event driven paradigm as former stresses on consumers while later stresses more on event sources.
Reactive Libraries in Java
After learning what Reactive programming is all about, it's time to discuss the libraries that enable us to do Reactive Programming. However, it is often desirable to have a reference/specification on which libraries are built. It makes it easy to switch implementations without code changes.
Reactive Streams is one such specification for Reactive programming libraries. It is basically an initiative to provide a standard for asynchronous stream processing with non-blocking back pressure. Back pressure refers to overwhelming of consumers due to high input rates of messages. It often creates problem as consumers are forced to keep the messages in memory resulting in application/system crash and lose of messages.
The scope of Reactive Streams is to find a minimal set of interfaces, methods and protocols that describe the necessary operations and entities to achieve the goal - asynchronous streams of data with non-blocking back pressure. In subsequent tutorials, we will deep dive into these interfaces, methods and protocols of Reactive Streams.
Here are some of libraries that provide implementations of Reactive Streams specification -
- Reactor - It is a Reactive library for building non-blocking applications on the JVM based on the Reactive Streams Specification. It however is a low-level library and lacks Location Transparency (ability to use remote resources like local ones).
- RxJava - RxJava is another Reactive library that was developed by Netflix. It initially did not conform to Reactive Streams specification but now provides an adapter called rxjava-reactive-streams to use Reactive Streams interfaces.
- Akka - Akka is currently most mature and feature rich Reactive programming toolkit. It provides an implementation of Reactive Streams using its module called Akka Stream.
All of above libraries will be covered in detail in subsequent tutorials.
Use Cases of Reactive Programming
Finally, let's now discuss the use cases where Reactive programming can make a difference -
- Highly Concurrent Message Consumers - Since Reactive programming is all about non-blocking operations, it helps you utilize threads/fibers efficiently and thus increasing the system capability to process more messages concurrently.
- Remote Service Calls - Often our applications need to call other internal/external remote services, these calls usually block calling threads. These blocking calls prevent us from leveraging the threads efficiently. By utilizing Reactive Programming for these service calls, calling threads do not wait for complete for service call and instead get free for other operations. As soon as service call returns, an available thread reacts to it by executing the registered callbacks, if any.
Thank you for reading through the tutorial. In case of any feedback/questions/concerns, you can communicate same to us through your comments and we shall get back to you as soon as possible.