Posts Tagged ‘RxJava’
[DevoxxPL2019] Reactive for the Impatient: A Gentle Introduction to Reactive Programming and Systems
Lecturer
Mary Grygleski serves as a developer advocate at IBM, based in Chicago. She organizes the Chicago Java Users Group (CJUG) and leads IBM-sponsored meetups on topics like reactive systems and cloud technologies. Her background includes promoting community engagement and advancing Java-based reactive frameworks.
Abstract
This article provides an in-depth exploration of reactive programming and systems, emphasizing their emergence to address modern computing demands for responsiveness and scalability. It delineates core principles from the Reactive Manifesto, differentiates reactive paradigms, and surveys key Java libraries: RxJava, Spring Reactor, Akka, and Vert.x. Analytical insights into patterns, methodologies, and real-world applications underscore the significance of asynchronicity, elasticity, and fault tolerance in building impatient-user-friendly systems.
Emergence and Principles of Reactive Systems
The surge in reactive methodologies arises from hardware advancements, such as multi-core CPUs and cloud virtualization, coupled with escalating user expectations for instantaneous responses. Mary traces reactive roots to the 1980s actor model in Erlang for real-time telecommunications, now adapted to handle proliferating devices and concurrent requests. Human impatience drives this evolution, mirroring family dynamics where multiple demands require asynchronous handling.
The Reactive Manifesto, led by Lightbend (creators of Akka), outlines four pillars: responsiveness, elasticity, resiliency, and message-driven architecture. Responsiveness ensures timely replies, even in failures, forming the usability foundation. Elasticity scales resources dynamically under varying loads, maintaining throughput. Resiliency employs replication and isolation for fault containment, preventing systemic collapses. Message-driven mechanics enable the others, facilitating asynchronous, non-blocking communication akin to event-driven systems but with addressed destinations.
Mary clarifies distinctions: reactive programming propagates changes via event streams, functional reactive programming advances via execution threads, and reactive systems orchestrate isolated components cohesively. Event-driven emits unaddressed events for observers, while message-driven specifies recipients, enhancing coordination.
Patterns and Terminologies in Reactive Programming
Reactive programming revolves around responding to external stimuli through event propagation. Streams represent sequential data elements, fundamental to reactivity. Observables emit event streams, observed by subscribers, drawing from design patterns like observer, composite, and iterator.
Using marble diagrams, Mary illustrates streams: empty timelines await events, marbles denote data, vertical lines signal completion. Backpressure management prevents overwhelming consumers. Reactive extensions (Rx) standardize these, with RxJava implementing them in Java.
A noodle shop analogy piques interest: ordering mimics reactive flows, where requests (events) trigger preparations (responses) asynchronously, handling multiple patrons without blocking.
Survey of Java Reactive Libraries: RxJava and Spring Reactor
RxJava, Netflix’s 2013 port of Microsoft’s Reactive Extensions, supports Java 6+ with backpressure in version 2 (2016). It enables declarative, functional-style programming for asynchronous data streams.
Code sample for a simple observable:
import io.reactivex.Flowable;
public class HelloWorld {
public static void main(String[] args) {
Flowable.fromArray(args).subscribe(System.out::println);
}
}
This pipelines arguments into a flowable, subscribing for output.
Spring Reactor, from Pivotal, leverages Java 8 streams for cleaner APIs, fully supporting reactive streams. It integrates with Kafka, Netty, and others.
Comparative example:
// Traditional Spring MVC (blocking)
@GetMapping("/products")
public List<Product> getProducts() {
System.out.println("Traditional way started");
List<Product> products = productService.getProducts();
System.out.println("Traditional way completed");
return products;
}
// Reactive WebFlux (non-blocking)
@GetMapping(value = "/product-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Product> getProductStream() {
System.out.println("Reactive way using Flux started");
Flux<Product> productFlux = productService.getProductStream();
System.out.println("Reactive way using Flux completed");
return productFlux;
}
The reactive version returns a Flux (ticket) immediately, processing asynchronously.
RxJava partially supports reactive streams; Reactor fully, with Reactor favoring Java 8+ for elegance.
Advanced Frameworks: Akka and Vert.x
Akka, from Lightbend, embodies the actor model for event-driven, location-transparent systems. Actors handle functions isolately, with supervisors managing failures for resiliency.
Java Akka hello world:
import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
public class HelloWorld extends AbstractActor {
@Override
public void preStart() {
final ActorRef greeter = getContext().actorOf(Props.create(Greeter.class), "greeter");
greeter.tell(Greeter.Msg.GREET, getSelf());
}
@Override
public Receive createReceive() {
return receiveBuilder()
.matchEquals(Greeter.Msg.DONE, msg -> getContext().stop(getSelf()))
.build();
}
}
Scala variant condenses this, leveraging functional conciseness.
Vert.x, from Eclipse, is polyglot, supporting mixed languages. Verticles (actor-like) execute on events, with an event bus for communication.
Vert.x HTTP server:
import io.vertx.core.Vertx;
public class HelloWorldServer {
public static void main(String[] args) {
Vertx.vertx().createHttpServer()
.requestHandler(req -> req.response().end("Hello World"))
.listen(8080);
}
}
Vert.x’s lightweight, non-container-bound nature suits diverse integrations.
Implications for Modern Software Development
Reactive approaches mitigate blocking I/O pitfalls, though database engines lag in full reactivity (e.g., R2DBC offers non-blocking connectivity, but underlying engines remain blocking). Mary advocates community participation, like her reactive meetup group, to foster learning.
In conclusion, reactive paradigms empower scalable, responsive systems, aligning software with hardware and user demands. Frameworks like RxJava, Reactor, Akka, and Vert.x provide tools for implementation, promising flexible, fault-tolerant architectures.
Links:
[KotlinConf2018] Taming State with Sealed Classes: Patrick Cousins’ Approach at Etsy
Lecturer
Patrick Cousins is a software engineer at Etsy with nearly 20 years of programming experience, passionate about new patterns and languages. He is known for his work on state management and seal-related puns. Relevant links: Etsy Code as Craft Blog (publications); LinkedIn Profile (professional page).
Abstract
This article examines Patrick Cousins’ use of Kotlin sealed classes to manage complex state in Etsy’s mobile apps. Contextualized in event-driven architectures, it explores methodologies for event streams with RxJava and when expressions. The analysis highlights innovations in exhaustiveness and type safety, contrasting Java’s limitations, with implications for robust state handling.
Introduction and Context
Patrick Cousins spoke at KotlinConf 2018 about sealed classes, inspired by his blog post on Etsy’s engineering site. Etsy’s mobile apps juggle complex state—listings, tags, shipping profiles—forming a “matrix of possibilities.” Sealed classes offer a type-safe way to model these, replacing Java’s error-prone instanceof checks and visitor patterns. This narrative unfolds where mobile apps demand reliable state management to avoid costly errors.
Methodological Approaches to State Management
Cousins modeled state as sealed class hierarchies, emitting events via RxJava streams. Using filterIsInstance and when, he ensured exhaustive handling of state types like Loading, Success, or Error. This avoided Java’s polymorphic indirection, where unrelated types forced artificial interfaces. Sealed classes, confined to one file, prevented unintended extensions, ensuring safety.
Analysis of Innovations and Features
Sealed classes innovate by guaranteeing exhaustiveness in when, unlike Java’s instanceof, which risks missing branches. Kotlin’s final-by-default classes eliminate Liskov substitution issues, avoiding polymorphic pitfalls. RxJava integration enables reactive updates, though requires careful ordering. Compared to Java, sealed classes simplify state logic without forced commonality, though complex hierarchies demand discipline.
Implications and Consequences
Cousins’ approach implies safer, more maintainable state management, critical for e-commerce apps. It reduces bugs from unhandled states, enhancing user experience. Consequences include a shift from polymorphic designs, though developers must adapt to sealed class constraints. The pattern encourages adoption in reactive systems.
Conclusion
Cousins’ use of sealed classes redefines state handling at Etsy, leveraging Kotlin’s type safety to create robust, readable mobile architectures.
Links
- Lecture video: https://www.youtube.com/watch?v=uGMm3StjqLI
- Lecturer’s X/Twitter: @patrickcousins
- Lecturer’s LinkedIn: Patrick Cousins
- Organization’s X/Twitter: @EtsyEng
- Organization’s LinkedIn: Etsy
[DevoxxFR2014] Reactive Programming with RxJava: Building Responsive Applications
Lecturer
Ben Christensen works as a software engineer at Netflix. He leads the development of reactive libraries for the JVM. Ben serves as a core contributor to RxJava. He possesses extensive experience in constructing resilient, low-latency systems for streaming platforms. His expertise centers on applying functional reactive programming principles to microservices architectures.
Abstract
This article provides an in-depth exploration of RxJava, Netflix’s implementation of Reactive Extensions for the JVM. It analyzes the Observable pattern as a foundation for composing asynchronous and event-driven programs. The discussion covers essential operators for data transformation and composition, schedulers for concurrency management, and advanced error handling strategies. Through concrete Netflix use cases, the article demonstrates how RxJava enables non-blocking, resilient applications and contrasts this approach with traditional callback-based paradigms.
The Observable Pattern and Push vs. Pull Models
RxJava revolves around the Observable, which functions as a push-based, composable iterator. Unlike the traditional pull-based Iterable, Observables emit items asynchronously to subscribers. This fundamental duality enables uniform treatment of synchronous and asynchronous data sources:
Observable<String> greeting = Observable.just("Hello", "RxJava");
greeting.subscribe(System.out::println);
The Observer interface defines three callbacks: onNext for data emission, onError for exceptions, and onCompleted for stream termination. RxJava enforces strict contracts for backpressure—ensuring producers respect consumer consumption rates—and cancellation through unsubscribe operations.
Operator Composition and Declarative Programming
RxJava provides over 100 operators that transform, filter, and combine Observables in a declarative manner. These operators form a functional composition pipeline:
Observable.range(1, 10)
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.subscribe(square -> System.out.println("Square: " + square));
The flatMap operator proves particularly powerful for concurrent operations, such as parallel API calls:
Observable<User> users = getUserIds();
users.flatMap(userId -> userService.getDetails(userId), 5)
.subscribe(user -> process(user));
This approach eliminates callback nesting (callback hell) while maintaining readability and composability. Marble diagrams visually represent operator behavior, illustrating timing, concurrency, and error propagation.
Concurrency Control with Schedulers
RxJava decouples computation from threading through Schedulers, which abstract thread pools:
Observable.just(1, 2, 3)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.computation())
.map(this::cpuIntensiveTask)
.subscribe(result -> display(result));
Common schedulers include:
– Schedulers.io() for I/O-bound operations (network, disk).
– Schedulers.computation() for CPU-bound tasks.
– Schedulers.newThread() for fire-and-forget operations.
This abstraction enables non-blocking I/O without manual thread management or blocking queues.
Error Handling and Resilience Patterns
RxJava treats errors as first-class citizens in the data stream:
Observable risky = Observable.create(subscriber -> {
subscriber.onNext(computeRiskyValue());
subscriber.onError(new RuntimeException("Failed"));
});
risky.onErrorResumeNext(throwable -> Observable.just("Default"))
.subscribe(value -> System.out.println(value));
Operators like retry, retryWhen, and onErrorReturn implement resilience patterns such as exponential backoff and circuit breakers—critical for microservices in failure-prone networks.
Netflix Production Use Cases
Netflix employs RxJava across its entire stack. The UI layer composes multiple backend API calls for personalized homepages:
Observable<Recommendation> recs = userIdObservable
.flatMap(this::fetchUserProfile)
.flatMap(profile -> Observable.zip(
fetchTopMovies(profile),
fetchSimilarUsers(profile),
this::combineRecommendations));
The API gateway uses RxJava for timeout handling, fallbacks, and request collapsing. Backend services leverage it for event processing and data aggregation.
Broader Impact on Software Architecture
RxJava embodies the Reactive Manifesto principles: responsive, resilient, elastic, and message-driven. It eliminates common concurrency bugs like race conditions and deadlocks. For JVM developers, RxJava offers a functional, declarative alternative to imperative threading models, enabling cleaner, more maintainable asynchronous code.