Upload
sanjay-acharya
View
980
Download
1
Embed Size (px)
Citation preview
05/02/2023RxJava
1
RxJava – Reactive Extensions for the JVM
An introduction to RxJavaBy
Sanjay Acharya and Joel Weight
Twitter: @sanjayvacharya and @digitaljoel
05/02/2023RxJava
2
Some reflection… Only recently…
Large applications with 10s of servers Seconds of response times Hours of offline maintenance Gigabytes of Data
Today’s Applications Deployed on anything from Mobile to Cloud Clusters with
thousands of multi core processors Millisecond response times 100% uptime Petabytes of Data
Traditional Architectures fail to meet today’s demands
05/02/2023RxJava
3
So How do we meet today’s demands ? Reactive Systems
05/02/2023RxJava
4
Reactive Definition
Reactive is being readily responsive to a stimulus
05/02/2023RxJava
5
http://www.reactivemanifesto.org
Responsive Elastic Resilien
tMessageDriven
September 16, 2014
Reactive Manifesto
05/02/2023RxJava
6
Event Stream(s)
Mouse Clicks
Stocks Splunk Events
Tweets
05/02/2023RxJava
7
Functional Reactive Programming
Values are pushed when ready in a non blocking manner
Facilitates parallelism Application of ‘functions’ on data
stream to transform data – Examples - map, filter, zip
Reactive Model is Push rather than Pull
05/02/2023RxJava
8
ReactiveX A library for composing asynchronous and event based
programs by using observable sequences
Created by Microsoft initially for the .NET platformBy Erik Meijer
Extends Observer Pattern to Support sequence of data and/or events Adds operators that allow you to compose sequences together
declaratively Abstracts away concerns around
Threading and Thread Safety Concurrent data structures and non blocking I/O.
RxJava is a port of Reactive Extensions created by Netflix
05/02/2023RxJava
9
GOF Observer Pattern
05/02/2023RxJava
10
Reactive Components
Observable Observer
Subject
Emits Events Observes Emitted Events
Observes and Emits Events
05/02/2023RxJava
11
rx.Observablepublic class Observable<T> { … }
Emits zero or more values
Life Cycle Notifies Observer
onNext element Completes with
onError Or onCompletion
Observable
Observer
onNext(T)
onComplete()
onError(Throwable)
05/02/2023RxJava
12
Observable CreationObservable<Integer> o = Observable .create(new Observable.OnSubscribe<Integer>(){ // Action @Override public void call(Subscriber<Integer> subscriber){ try { for (int i = 0; i < 10 && ! subscriber.isUnsubscribed(); i++) { subscriber.onNext(i); } if (!subscriber.isUnsubscribed()) { subscriber.onCompleted(); } } catch (RuntimeException e) { if (!subscriber.isUnsubscribed()) { subscriber.onError(e); } } } });
Using JDK 7Downstream Slide examples will use JDK 8 Lambdas
05/02/2023RxJava
13
Subscribing (Observer)Observable<Integer> o = Observable.create(…);
Subscription s = o.subscribe(new Observer<Integer>() { @Override public void onNext(Integer i) { System.out.print(i); }
@Override public void onCompleted() { System.out.println(“\nAll Done!”); } @Override public void onError(Throwable t) { t.printStackTrace(); } });
Prints – 0 to 9!
Observable from previous
slide
0123456789All Done!
Prints – All Done!
05/02/2023RxJava
14
Operator Description ExampleObservable.just(T) Simple values
wrappedObservable.just(“HelloWorld”);
Observable.empty() Empty Sequence that completes right away
Observable.empty();
Observable.from(Iterable<T>) Sequence from an Iterable
Observable.from(Lists.newArrayList(“A”, “B”));
Observable.from(T []) Sequence from Array
Observable.from(new Integer[] {0, 1, 2, 3, 4});
Observable.defer(ObservableFactory)
Defer emitting of items for each subscriber
Example shown later.
Observable.interval(long, TimeUnit)
Emit a sequence of numbers separated by an interval
Observable.interval(100, TimeUnit.MILLISECONDS);
Observable.range(start, count) Emits a sequence of integers in a range
Observable.range(100, 20);
Observable.create(OnSubscribe<T>)
Most flexible and powerful
Observable.create(new OnSubscribe…());
05/02/2023RxJava
15
Observable Vs Iterator
Event Iterable (PULL) Observable (PUSH)
Retrieve Data T next(); onNext(T);
Discover the Error throws Exception onError(Throwable)
Complete !hasNext() onCompleted();
05/02/2023RxJava
16
Observable Operator Categories
05/02/2023RxJava
17
Operator Categories
Creating Observables
CombiningObservables
FilteringObservables
TransformingObservables
Error HandlingOperators
Observable Utility Operators
Conditional & Boolean
Operators
Mathematical & Aggregate Operators
Back Pressure Operators
05/02/2023RxJava
18
Marble Diagram
05/02/2023RxJava
19
Transformational
Operations that transform items emitted by an Observable
Commonly used.. map flatmap
05/02/2023RxJava
20
Map
Transform the items emitted by an Observable by applying a function to each item
Observable<Integer> o = Observable.range(0,10);
Observable<Integer> timesTen = o.map(t -> t * 10);
05/02/2023RxJava
21
Flatmap
Transforms items emitted from an Observable into Observables and then merges those emissions into a single Observable
Observable<Integer> o = Observable.range(0, 10);
Observable<Integer> numbersAndNegatives = o.flatmap(t -> Observable.just(t, -t));
05/02/2023RxJava
22
Filtering
Operators that selectively emit items from a source Observable
Commonly used filter distinct take first
05/02/2023RxJava
23
Filter
Emit only items from an Observable that match a predicate test
Observable<Integer> o = Observable.range(0,10);
Observable<Integer> evenNos = o.filter(t -> (t % 2) == 0);
05/02/2023RxJava
24
Take
Emit only the first n items emitted by an Observable.
Observable<Integer> o = Observable.range(0,10);
Observable<Integer> firstTwo = o.take(2);
05/02/2023RxJava
25
Combining Observables
Operators that work with multiple source Observables to create a single Observable
Commonly used Merge Concat Zip zipWith
05/02/2023RxJava
26
Merge
Combine multiple Observables by merging their emissions
May interleave items
Observable<Integer> first = Observable.range(0,10);Observable<Integer> second = Observable.range(10, 20);
Observable<Integer> merged = Observable.merge(first, second);
05/02/2023RxJava
27
Concat
Similar to merge but combines observable without interleaving
Observable<Integer> first = Observable.range(0,10);Observable<Integer> second = Observable.range(10, 20);
Observable<Integer> concat = Observable.concat(first, second);
05/02/2023RxJava
28
Zip
combine the emissions of multiple Observables together via a specified function and emit single items for each combination based on the results of this functionObservable<Integer> first = Observable.just(1, 2, 3);
Observable<String> second = Observable.just(“A”,“B”, “C”, “D”);
Observable<String> zipped = Observable.zip(first, second (x,y) -> String.valueOf(x)+y);
// on subscription emits “1A”, “2B”, “3C”
05/02/2023RxJava
29
ZipWith
Instance-version of zip
Observable<Integer> first = Observable.just(1, 2, 3);Observable<String> second = Observable.just(“A”,“B”, “C”, “D”);
Observable<String> zipped = first.zipWith(second, (x, y) -> String.valueOf(x)+y);
// on subscription emits “1A”, “2B”, “3C”
05/02/2023RxJava
30
Decision Tree of Observables
http://reactivex.io/documentation/operators.html#tree
05/02/2023RxJava
31
Schedulers and Observable Utility Operators
05/02/2023RxJava
32
Schedulers
io() computational()
newThread() trampoline()
immediate() test()
from(Executor)
05/02/2023RxJava
33
Observable Utility Operators Utility Operators for
working with Observables
Common Utility Operators – Observable.observeOn(Scheduler) Observable.subscribeOn(Scheduler)
ObserveOn()
SubscribeOn()
05/02/2023RxJava
34
Main Thread SubscribeObservable<String> hello = Observable.create(subscriber -> { System.out.println(“Observable executing on:” + Thread.currentThread()); subscriber.onNext(“Hello World!”); subscriber.onCompleted(); }});
hello.subscribe(s - > { System.out.println(“Observing on:” + Thread.currentThread() + s); });
Observable executing on: [main,5,main] Observing on: [main,5,main] Hello World
05/02/2023RxJava
35
ObserveOnObservable<String> hello = Observable.create(subscriber -> { System.out.println(“Observable executing on:” + Thread.currentThread()); subscriber.onNext(“Hello World!”); subscriber.onCompleted(); }});
hello.observeOn(Schedulers.io()).subscribe(s - > {
System.out.println(“Observing on:” + Thread.currentThread() + s);});
Observable executing on: [main,5,main] Observing on: [RxCachedThreadScheduler-1,5,main] Hello World
05/02/2023RxJava
36
SubscribeOnObservable<String> hello = Observable.create(subscriber -> { System.out.println(“Observable executing on:” + Thread.currentThread()); subscriber.onNext(“Hello World!”); subscriber.onCompleted(); }});
hello.subscribeOn(Schedulers.io()).subscribe(s - > { System.out.println(“Observing on:” + Thread.currentThread() + s);});
Observable executing on:[RxCachedThreadScheduler-1,5,main] Observing on: [RxCachedThreadScheduler-1,5,main] Hello World
05/02/2023RxJava
37
SubscribeOn and ObserveOnObservable<String> hello = Observable.create(subscriber -> { System.out.println(“Observable executing on:” + Thread.currentThread()); subscriber.onNext(“Hello World!”); subscriber.onCompleted(); }});
hello.subscribeOn(Schedulers.computation())
.observeOn(Schedulers.io())
.subscribe(s - > { System.out.println(“Observing on:”+ Thread.currentThread());});
Observable executing on: [RxCompuationThreadPool-3,5,main] Observing on: [RxCachedThreadScheduler-1,5,main] Hello World
05/02/2023RxJava
38
Reactive Example – Putting it together
05/02/2023RxJava
39
Product Gateway Service
Base Product Service
Pricing Service
Inventory Service
Product Gatewa
y Service
Product
BaseProduct
Inventory
Price
05/02/2023RxJava
40
Product Gateway Service
05/02/2023RxJava
41
Model
PriceInventory• Product display
price is lowest Option price
• Product inventory is total of all Option Inventory
• Inventory and Price are inferred for the Product
• Product contains Options
05/02/2023RxJava
42
Synchronously Assembled ProductProduct getProduct(Long productId) {
BaseProduct bp = baseProductClient.getBaseProduct(productId); // Blocking WS Call
}
Obtain Base Product.
05/02/2023RxJava
43
Synchronously Assembled ProductProduct getProduct(Long productId) { BaseProduct bp = baseProductClient.getBaseProduct(productId); // Blocking WS Call Double displayPrice = Double.MAX_VALUE; List<Option> optionList = Lists.newArrayList(); int totalInventory = 0;
for (BaseOption bo : bp.getOptions()) { } }
For Each BaseOption
05/02/2023RxJava
44
Synchronously Assembled ProductProduct getProduct(Long productId) { BaseProduct bp = baseProductClient.getBaseProduct(productId); // Blocking WS Call Double displayPrice = Double.MAX_VALUE; List<Option> optionList = Lists.newArrayList(); int totalInventory = 0;
for (BaseOption bo : bp.getOptions()) {
Double price = priceClient.getPrice(bo.getId()); // Blocking WS Call Integer inventory = inventoryClient.getInventory(bo.getId()); // Blocking WS Call optionList.add(new Option().withId(bo.getId())..withPrice(..).withInventory(..)); totalInventory += inventory; displayPrice = (price < lowestPrice) ? price : lowestPrice; }
}Obtain Price, Inventory for ever BaseOption and create Option.
Compute total inventory and lowest price
05/02/2023RxJava
45
Synchronously Assembled ProductProduct getProduct(Long productId) { BaseProduct bp = baseProductClient.getBaseProduct(productId); // Blocking WS Call Double displayPrice = Double.MAX_VALUE; List<Option> optionList = Lists.newArrayList(); int totalInventory = 0;
for (BaseOption bo : bp.getOptions()) { Double price = priceClient.getPrice(bo.getId()); // Blocking WS Call Integer inventory = inventoryClient.getInventory(bo.getId()); // Blocking WS Call optionList.add(new Option().withId(bo.getId())..withPrice(..).withInventory(..)); totalInventory += inventory; displayPrice = (price < lowestPrice) ? price : lowestPrice; } return new Product().withId(bp.getId().withDescription(bp.getDescription()) .withInventory(totalInventory).withPrice(displayPrice).withOptions(optionList);}
Build and return Product
05/02/2023RxJava
46
Observable Non Blocking
05/02/2023RxJava
47
Blocking to Non Blocking (?)BaseProduct getBaseProductSync(Long productId) { // Synchronous Blocking WS Call return …;}
Observable<BaseProduct> getBaseProduct(Long productId) {
return Observable.just(getBaseProductSync(productId));
}
Call to getBaseProductSync() is executed right away. A
blocking operation.
05/02/2023RxJava
48
Blocking to Non BlockingBaseProduct getBaseProductSync(Long productId) { // Synchronous Blocking WS Call return …;}
Observable<BaseProduct> getBaseProduct(Long productId) { return Observable.defer(() -> Observable.just(getBaseProductSync(productId)));}
Observable<BaseProduct> getBaseProduct(Long productId) { return Observable.create(t -> { BaseProduct bp = getBaseProductSync(productId); if (!t.isUnsubscribed()) { t.onNext(bp); t.onCompleted(); } });}
05/02/2023RxJava
49
Subscribe On Schedulers.io()BaseProduct getBaseProductSync(Long productId) { // Synchronous Blocking WS Call return …;}
Observable<BaseProduct> getBaseProduct(Long productId) { return Observable.defer(() -> Observable.just(getBaseProductSync(productId))) .subscribeOn(Schedulers.io());}
Observable<BaseProduct> getBaseProduct(Long productId) { return Observable.create(t -> { BaseProduct bp = getBaseProductSync(productId); if (!t.isUnsubscribed()) { t.onNext(bp); t.onCompleted(); } }).subscribeOn(Schedulers.io());}
05/02/2023RxJava
50
getProduct(id) Observable<Product>
05/02/2023RxJava
51
getProduct(id)
baseProductClient.getBaseProduct(id) Observable<BaseProduct>
Observable<Product>
05/02/2023RxJava
52
getProduct(id)
baseProductClient.getBaseProduct(id)
flatMap()
Observable<BaseProduct>
Observable<Product>
Observable<Product>
05/02/2023RxJava
53
getProduct(id)
baseProductClient.getBaseProduct(id)
flatMap()
from(baseProduct.baseOptions)
Observable<BaseProduct>
Observable<Product>
Observable<BaseOption>
Observable<Product>
BaseProduct
05/02/2023RxJava
54
getProduct(id)
baseProductClient.getBaseProduct(id)
from(baseProduct.baseOptions)
flatMap()
Observable<BaseProduct>
Observable<Product>
Observable<BaseOption>
Observable<Option>
Observable<Product>
flatMap()
05/02/2023RxJava
55
getProduct(id)
baseProductClient.getBaseProduct(id)
from(baseProduct.baseOptions)
flatMap()
invClient.getInventory(optionId)
Observable<BaseProduct>
Observable<Product>
Observable<BaseOption>
Observable<Option>
Observable<Integer>
Observable<Product>
BaseOption
flatMap()
05/02/2023RxJava
56
getProduct(id)
baseProductClient.getBaseProduct(id)
from(baseProduct.baseOptions)
flatMap()
invClient.getInventory(optionId)
priceClient.getPrice(optionId)
Observable<BaseProduct>
Observable<Product>
Observable<BaseOption>
Observable<Option>
Observable<Double>
Observable<Product>
Observable<Integer>
flatMap()
05/02/2023RxJava
57
getProduct(id)
baseProductClient.getBaseProduct(id)
from(baseProduct.baseOptions)
flatMap()
invClient.getInventory(optionId)
priceClient.getPrice(optionId)
zip()
Observable<BaseProduct>
Observable<Product>
Observable<BaseOption>
Observable<Option>
Observable<Option>
Observable<Product>
Observable<Integer>
Observable<Double>
flatMap()
05/02/2023RxJava
58
getProduct(id)
baseProductClient.getBaseProduct(id)
from(baseProduct.baseOptions)
flatMap()
invClient.getInventory(optionId)
priceClient.getPrice(optionId)
zip()
Observable<BaseProduct>
Observable<Product>
Observable<BaseOption>
Observable<Option>
Observable<Option>
Observable<Product>
Observable<List<Option>>toList()
Observable<Integer>
Observable<Double>
flatMap()
05/02/2023RxJava
59
getProduct(id)
baseProductClient.getBaseProduct(id)
from(baseProduct.baseOptions)
flatMap()
invClient.getInventory(optionId)
priceClient.getPrice(optionId)
zip()
Observable<BaseProduct>
Observable<Product>
Observable<BaseOption>
Observable<Option>
Observable<Option>
just(Product)
Observable<Product>
Observable<List<Option>>toList()
Observable<Product>
Observable<Integer>
Observable<Double>
flatMap()
05/02/2023RxJava
60
getProduct(id)
baseProductClient.getBaseProduct(id)
from(baseProduct.baseOptions)
flatMap()
invClient.getInventory(optionId)
priceClient.getPrice(optionId)
zip()
Observable<BaseProduct>
Observable<Product>
Observable<BaseOption>
Observable<Option>
Observable<Option>
just(Product)
zipWith(options)
Observable<Product>
Observable<List<Option>>
Observable<Product>
toList()
Observable<Product>
Observable<Integer>
Observable<Double>
flatMap()
05/02/2023RxJava
61
getProduct(id)
baseProductClient.getBaseProduct(id)
from(baseProduct.baseOptions)
flatMap()
invClient.getInventory(optionId)
priceClient.getPrice(optionId)
zip()
Observable<BaseProduct>
Observable<Product>
Observable<BaseOption>
Observable<Option>
Observable<Option>
just(Product)
zipWith(options)
Observable<Product>
Observable<List<Option>>
Observable<Product>
toList()
Observable<Product>
Observable<Integer>
Observable<Double>
flatMap()
05/02/2023RxJava
62
Observable ProductObservable<Product> getProduct(Long productId) { return baseProductClient.getBaseProduct(productId)…
}
Get Non Blocking Base Product
05/02/2023RxJava
63
Observable ProductObservable<Product> getProduct(Long productId) { return baseProductClient.getBaseProduct(productId).flatMap(baseProduct -> {
}
Flat Map Base Product
05/02/2023RxJava
64
Observable ProductObservable<Product> getProduct(Long productId) { return baseProductClient.getBaseProduct(productId).flatMap(baseProduct -> {
Observable<Option> options = Observable.from(baseProduct.getBaseOptions()) .flatMap(bo -> {
}
For Every BaseOption,
flatMap.
05/02/2023RxJava
65
Observable ProductObservable<Product> getProduct(Long productId) { return baseProductClient.getBaseProduct(productId).flatMap(baseProduct -> {
Observable<Option> options = Observable.from(baseProduct.getBaseOptions()) .flatMap(bo -> { Observable<Double> optionPrice = priceClient.getPrice(bo.getId())); Observable<Integer> optionInventory = inventoryClient.getInventory(bo.getId())); }
For Every Base Option obtain
Inventory and Price
05/02/2023RxJava
66
Observable ProductObservable<Product> getProduct(Long productId) { return baseProductClient.getBaseProduct(productId).flatMap(baseProduct -> {
Observable<Option> options = Observable.from(baseProduct.getBaseOptions()) .flatMap(bo -> { Observable<Double> optionPrice = priceClient.getPrice(bo.getId())); Observable<Integer> optionInventory = inventoryClient.getInventory(bo.getId())); return Observable.zip(optionPrice , optionInventory, (price , inventory) - > { return new Option().withId(bo.getId()).withDescription(bo.getDescription()) .withPrice(price ).withInventory(inventory); } );
}
Option = Zip [Base Option + Inventory + Price]
05/02/2023RxJava
67
Observable ProductObservable<Product> getProduct(Long productId) { return baseProductClient.getBaseProduct(productId).flatMap(baseProduct -> {
Observable<Option> options = Observable.from(baseProduct.getBaseOptions()) .flatMap(bo -> { Observable<Double> optionPrice = priceClient.getPrice(bo.getId())); Observable<Integer> optionInventory = inventoryClient.getInventory(bo.getId())); return Observable.zip(optionPrice , optionInventory, (price , inventory) - > { return new Option().withId(bo.getId()).withDescription(bo.getDescription()) .withPrice(price ).withInventory(inventory); } );
return Observable.just(new Product()).zipWith(options.toList(), (product, optionList) -> { Integer totalInventory = computeMaxInventory(optionList); Double lowestPrice = computeLowestPrice(optionList); return product.withId(baseProduct.getId()) .withDescription(baseProduct.getDescription()).withPrice(lowestPrice) .withInventory(totalInventory).withOptions(optionList); }); });}
Create Product from Options,
compute Inventory and
price
05/02/2023RxJava
68
Observable Product - TestLong productId = 1L;
Observable<Product> product = getProduct(productId);
// The Observable only starts doing something after// an observer subscribesproduct.subscribe(p -> LOG.debug(p));
05/02/2023RxJava
69
Example Run
05/02/2023RxJava
70
Cold and Hot Observable
05/02/2023RxJava
71
Observable CreationObservable<Customer> getCustomers() { return Observable.create(new Observable.OnSubscribe<Customer>(){ public void call(Subscriber<Customer> subscriber){ Connection conn = getConnection(); Stmt stmt = conn.createStatement(); String sql = “select id, name from customer”; ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { Long id = rs.getLong(“id”); String name = rs.getString(“name”); Customer c = new Customer(id, name); subscriber.onNext(c); }
subscriber.onComplete(); … } });}
Observable<Customer> customer = getCustomers();
What happens
when this statement
is executed?
05/02/2023RxJava
72
Cold Observable
Is the more common types of Observables you will deal with
Does nothing until subscribed to In example shown, Database was not
accessed till a subscriber was present
05/02/2023RxJava
73
Hot Observable
Hot observables are "live" sequences that are occurring whether they are being observed or not.
The canonical example is a mouse, which of course is free to move regardless of whether you subscribe to an Observable<MouseMoveEvent> or not.
05/02/2023RxJava
74
Hot Observable Example – Earth emitting Greetings
Hello 1439838374206
Hola1439838374207
Namaste 1439838374210
Bonjour 1439838375707
Emitting Greetings in multiple languages + Timestamp
05/02/2023RxJava
75
One Curious Observer
Hello 143983837900
Hola143983837901
Namaste 1439838374210
Bonjour 1439123123000
05/02/2023RxJava
76
Second Curious Observer
Hello 143983837900
Hola143983837901
Namaste 1439838374210
Bonjour 1439123123000
05/02/2023RxJava
77
Hot Observable using - ConnectableObservable
A Connectable Observable resembles an ordinary Observable, except that it does not begin emitting items when it is subscribed to, but only when its connect() method is called. Calling connect(), makes the Observable ‘HOT’.
ConnectableObservables can be created from any Observable by calling publish() or replay()
05/02/2023RxJava
78
Connectable ObservableObservable<String> earthGreetings = Observable.create(new AlienGreetingOnSubscribe());
An Observable that emits
Greetings from Earth
05/02/2023RxJava
79
Connectable ObservableObservable<String> earthGreetings = Observable.create(new AlienGreetingOnSubscribe());
ConnectableObservable<String> hotGreetingObservable = earthGreetings.publish();
ConnectableObservable from source by calling
publish ()
05/02/2023RxJava
80
Connectable ObservableObservable<String> earthGreetings = Observable.create(new AlienGreetingOnSubscribe());
ConnectableObservable<String> hotGreetingObservable = earthGreetings.publish();
hotGreetingObservable.connect();
connect() makes the Observable HOT! Starts
emitting greetings.
05/02/2023RxJava
81
Connectable ObservableObservable<String> earthGreetings = Observable.create(new AlienGreetingOnSubscribe());
ConnectableObservable<String> hotGreetingObservable = earthGreetings.publish();
hotGreetingObservable.connect();
Subscription firstAlienShip = hotGreetingObservable .subscribe(t -> LOG.debug(“First Alien Ship Received:” + t));
First Alien Ship
subscribes for messages.
05/02/2023RxJava
82
Connectable ObservableObservable<String> earthGreeting = Observable.create(new AlienGreetingOnSubscribe());
ConnectableObservable<String> hotGreetingObservable = earthGreeting.publish();
hotGreetingObservable.connect();
Subscription firstAlienShip = hotGreetingObservable .subscribe(t -> LOG.debug(“First Alien Ship Received:” + t));
Thread.sleep(200); Simulate time passing.
05/02/2023RxJava
83
Connectable ObservableObservable<String> earthGreetings = Observable.create(new AlienGreetingOnSubscribe());
ConnectableObservable<String> hotGreetingObservable = earthGreetings.publish();
hotGreetingObservable.connect();
Subscription firstAlienShip = hotGreetingObservable .subscribe(t -> LOG.debug(“First Alien Ship Received:” + t));
Thread.sleep(200);
Subscription secondAlienShip = hotGreetingObservable .subscribe(t -> LOG.debug(“Second Alien Ship Received:” + t));
Second Alien Ship subscribes and receives
messages.
05/02/2023RxJava
84
ConsoleNo
Subscribers
FirstObserver
SecondObserver
05/02/2023RxJava
85
ConnectableObservable – replay()Observable<String> earthGreetings = Observable.create(new AlienGreetingOnSubscribe());
ConnectableObservable<String> hotGreetingObservable = earthGreeting.replay();
hotGreetingObservable.connect();
Thread.sleep(200); // Simulate a Delay
// Alien ship receives ALL greetings emittedSubscription firstAlienShip = hotGreetingObservable .subscribe(t -> LOG.debug(“First Alien Ship Received:” + t));
HOT!!! Starts emitting
greetings.
05/02/2023RxJava
86
Console – replay()No
Subscribers
Observer gets it all
05/02/2023RxJava
87
PublishSubject to create a Hot Observable
Another way to create a Hot Observable
Left as an exercise for the viewer An example provided in slide deck
addendum
05/02/2023RxJava
88
Error Handling
05/02/2023RxJava
89
Erroring Observable Observable<BaseProduct> getProduct(Long productId) { return Observable.create(new OnSubscribe() { public void call(Subscriber subscriber) { subscriber.onError (new RuntimeException(“I’m Broken!!!”)); } }); }
05/02/2023RxJava
90
Error Handling – Bubbled uptry { Observable<BaseProduct> bp = getProduct(productId); bp.subscribe(p -> LOG.info(p));}catch(RuntimeException e) { LOG.info(“Exception Type:” + e.getClass() + “Message:” + e.getMessage()); }
Exception Type:class rx.exceptions.OnErrorNotImplementedException, Message:Error Occured calling BaseProduct Service
05/02/2023RxJava
91
Error Handling – FallbackObservable<BaseProduct> bp = getProduct(productId);
bp.onErrorResumeNext(t -> { return Observable.just(BaseProduct.DEFAULT); }) .subscribe(p -> LOG.info(p));
BaseProduct{id: {-1}, description: {N/A}, baseOptions: {[]}}
05/02/2023RxJava
92
Error Handling – RetryObservable<BaseProduct> bp = getProduct(productId);
bp.retry((retryCount, throwable) -> { LOG.info(“Base Product Error”, throwable); return retryCount < 2 ? Boolean.TRUE: Boolean.FALSE; }) .subscribe(p -> LOG.info(p));
Would try twice to get the Base Product
05/02/2023RxJava
93
Testing and Debugging
05/02/2023RxJava
94
Unit Testing
rx.observers.TestSubscriber
Do not use in production code
Has a bunch of convenience methods awaitTerminalEvent() assertNoErrors() assertReceivedOnNext(…) assertUnsubscribed()
05/02/2023RxJava
95
TestingTestSubscriber<String> ts = new TestSubscriber<>();
Observable.interval(200, TimeUnit.MILLISECONDS) .take(3) .map(t -> {return “Hello:” + t}) .subscribe(ts);
ts.awaitTerminalEvent();ts.assertNotErrors();ts.assertReceivedOnNext(Lists.newArrayList(“Hello:0”, “Hello:1”, “Hello:2”));
This is async!
05/02/2023RxJava
96
What is the hardest part of concurrent programming?
05/02/2023RxJava
97
Debugging
Never easy! Not just a problem of Rx as much as simply the nature
of it
Stepping through code is severely limited
Stack Trace can be difficult to understand
System.out.println or debug statements your friends
doOnNext(), doOnError()
05/02/2023RxJava
98
doOnNext()@Test
public void doOnNextTest() {
List<String> received = Lists.newArrayList();
Observable<String> o = Observable.just(“a”,“b”,“c”) // Test Observable
.doOnNext( s -> received.add(s));
TestSubscriber<String> test = new TestSubscriber();
o.subscribe(test);
test.awaitTerminalEvent();
assertEquals(Lists.newArrayList(“a”,“b”,“c”), received);
}
05/02/2023RxJava
99
doOnCompleted()
Observable.just(1, 2, 3, 4)
.take(3) // only emit 3 items
.doOnCompleted(() ->System.out.println(“DONE!”))
.subscribe(i -> System.out.print( i ));
Output:
123DONE!
05/02/2023RxJava
100
Conclusion
05/02/2023RxJava
101
The Good Makes Asynchronous code easy to develop Lots of online resources and examples Strong use of functional style of
programming Netflix used RxNetty and Reactive
Programming to considerable performance advantage over Tomcat
Web Service Clients like Jersey and Retrofit support RxJava
05/02/2023RxJava
102
The Bad The Bad
Learning curve and mind set change to use functional reactive programming
Appears like more code and more complex code initially – Requires time for it to grow on you
If on java 7, anonymous classes would make this a non-starter Thank heavens for Java 8 Lambdas
05/02/2023RxJava
103
The Ugly
The Ugly Debugging and Stepping through
async code is painful Stack Traces are difficult to follow Author’s recommend
System.out.println or Log.debug(..) doOnNext() and doOnError()
05/02/2023RxJava
104
Resources Intro to Rx - http://www.introtorx.com/ ReactiveX – http://reactivex.io RxMarbles - http://rxmarbles.com/ RxJava - https://github.com/ReactiveX/
RxJava Air Traffic Control Simulation
https://github.com/digitaljoel/rxAir
05/02/2023RxJava
105
Thank you and Questions…https://github.com/digitaljoel/rxAir
05/02/2023RxJava
106
Addendum
05/02/2023RxJava
107
Subjects
05/02/2023RxJava
108
Subject
Subject is an object that can be both Observable and Observer
Bridge between Observable and Observer
Subject can subscribe to an Observable acting like an Observer
Subject can emit new items like an Observable
05/02/2023RxJava
109
Publish Subject Subject that, once an
Observer has subscribed, emits all subsequently observed items to the subscriber
PublishSubject<Object> subject = PublishSubject.create();subject.onNext(“one”);subject.subscribe(t - > LOG.info(“Observer1:” + t));subject.onNext(“two”);subject.subscribe(t - > LOG.info(“Observer2:” + t));subject.onNext(“three”);
05/02/2023RxJava
110
Replay Subject Subject that buffers all items
it observes and replays them to any Observer that subscribes.
ReplaySubject<Object> subject = ReplaySubject.create();subject.onNext(“one”);subject.onNext(“two”);subject.onNext(“three”);subject.onCompleted();
subject.subscribe(t - > LOG.info(“Observer1:” + t));subject.subscribe(t - > LOG.info(“Observer2:” + t));
05/02/2023RxJava
111
Subjects not discussed
Behavior Subject Async Subject Slides provided at end
05/02/2023RxJava
112
Publish Subject for Hot ObservableObservable<String> earthGreeting = Observable.create(new AlienGreetingOnSubscribe());
Subject<String, String> publishSubject = PublishSubject.create();
earthGreeting.subscribe(publishSubject);
Subscription firstAlienShip = publishSubject .subscribe(t -> LOG.debug(“First Alien Ship Received:” + t));
Thread.sleep(200);
Subscription secondAlienShip = publishSubject .subscribe(t -> LOG.debug(“Second Alien Ship Received:” + t));
HOT!!!
05/02/2023RxJava
113
ConsoleNo
Subscribers
FirstObserver
SecondObserver