113
RxJava Reactive Extensions for the JVM An introduction to RxJava By Sanjay Acharya and Joel Weight Twitter: @sanjayvacharya and @digitaljoel 1 RxJava 06/17/2022

An Introduction to RxJava

Embed Size (px)

Citation preview

Page 1: An Introduction to RxJava

05/02/2023RxJava

1

RxJava – Reactive Extensions for the JVM

An introduction to RxJavaBy

Sanjay Acharya and Joel Weight

Twitter: @sanjayvacharya and @digitaljoel

Page 2: An Introduction to RxJava

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

Page 3: An Introduction to RxJava

05/02/2023RxJava

3

So How do we meet today’s demands ? Reactive Systems

Page 4: An Introduction to RxJava

05/02/2023RxJava

4

Reactive Definition

Reactive is being readily responsive to a stimulus

Page 5: An Introduction to RxJava

05/02/2023RxJava

5

http://www.reactivemanifesto.org

Responsive Elastic Resilien

tMessageDriven

September 16, 2014

Reactive Manifesto

Page 6: An Introduction to RxJava

05/02/2023RxJava

6

Event Stream(s)

Mouse Clicks

Stocks Splunk Events

Tweets

Page 7: An Introduction to RxJava

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

Page 8: An Introduction to RxJava

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

Page 9: An Introduction to RxJava

05/02/2023RxJava

9

GOF Observer Pattern

Page 10: An Introduction to RxJava

05/02/2023RxJava

10

Reactive Components

Observable Observer

Subject

Emits Events Observes Emitted Events

Observes and Emits Events

Page 11: An Introduction to RxJava

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)

Page 12: An Introduction to RxJava

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

Page 13: An Introduction to RxJava

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!

Page 14: An Introduction to RxJava

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…());

Page 15: An Introduction to RxJava

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();

Page 16: An Introduction to RxJava

05/02/2023RxJava

16

Observable Operator Categories

Page 17: An Introduction to RxJava

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

Page 18: An Introduction to RxJava

05/02/2023RxJava

18

Marble Diagram

Page 19: An Introduction to RxJava

05/02/2023RxJava

19

Transformational

Operations that transform items emitted by an Observable

Commonly used.. map flatmap

Page 20: An Introduction to RxJava

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);

Page 21: An Introduction to RxJava

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));

Page 22: An Introduction to RxJava

05/02/2023RxJava

22

Filtering

Operators that selectively emit items from a source Observable

Commonly used filter distinct take first

Page 23: An Introduction to RxJava

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);

Page 24: An Introduction to RxJava

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);

Page 25: An Introduction to RxJava

05/02/2023RxJava

25

Combining Observables

Operators that work with multiple source Observables to create a single Observable

Commonly used Merge Concat Zip zipWith

Page 26: An Introduction to RxJava

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);

Page 27: An Introduction to RxJava

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);

Page 28: An Introduction to RxJava

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”

Page 29: An Introduction to RxJava

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”

Page 30: An Introduction to RxJava

05/02/2023RxJava

30

Decision Tree of Observables

http://reactivex.io/documentation/operators.html#tree

Page 31: An Introduction to RxJava

05/02/2023RxJava

31

Schedulers and Observable Utility Operators

Page 32: An Introduction to RxJava

05/02/2023RxJava

32

Schedulers

io() computational()

newThread() trampoline()

immediate() test()

from(Executor)

Page 33: An Introduction to RxJava

05/02/2023RxJava

33

Observable Utility Operators Utility Operators for

working with Observables

Common Utility Operators – Observable.observeOn(Scheduler) Observable.subscribeOn(Scheduler)

ObserveOn()

SubscribeOn()

Page 34: An Introduction to RxJava

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

Page 35: An Introduction to RxJava

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

Page 36: An Introduction to RxJava

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

Page 37: An Introduction to RxJava

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

Page 38: An Introduction to RxJava

05/02/2023RxJava

38

Reactive Example – Putting it together

Page 39: An Introduction to RxJava

05/02/2023RxJava

39

Product Gateway Service

Base Product Service

Pricing Service

Inventory Service

Product Gatewa

y Service

Product

BaseProduct

Inventory

Price

Page 40: An Introduction to RxJava

05/02/2023RxJava

40

Product Gateway Service

Page 41: An Introduction to RxJava

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

Page 42: An Introduction to RxJava

05/02/2023RxJava

42

Synchronously Assembled ProductProduct getProduct(Long productId) {

BaseProduct bp = baseProductClient.getBaseProduct(productId); // Blocking WS Call

}

Obtain Base Product.

Page 43: An Introduction to RxJava

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

Page 44: An Introduction to RxJava

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

Page 45: An Introduction to RxJava

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

Page 46: An Introduction to RxJava

05/02/2023RxJava

46

Observable Non Blocking

Page 47: An Introduction to RxJava

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.

Page 48: An Introduction to RxJava

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(); } });}

Page 49: An Introduction to RxJava

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());}

Page 50: An Introduction to RxJava

05/02/2023RxJava

50

getProduct(id) Observable<Product>

Page 51: An Introduction to RxJava

05/02/2023RxJava

51

getProduct(id)

baseProductClient.getBaseProduct(id) Observable<BaseProduct>

Observable<Product>

Page 52: An Introduction to RxJava

05/02/2023RxJava

52

getProduct(id)

baseProductClient.getBaseProduct(id)

flatMap()

Observable<BaseProduct>

Observable<Product>

Observable<Product>

Page 53: An Introduction to RxJava

05/02/2023RxJava

53

getProduct(id)

baseProductClient.getBaseProduct(id)

flatMap()

from(baseProduct.baseOptions)

Observable<BaseProduct>

Observable<Product>

Observable<BaseOption>

Observable<Product>

BaseProduct

Page 54: An Introduction to RxJava

05/02/2023RxJava

54

getProduct(id)

baseProductClient.getBaseProduct(id)

from(baseProduct.baseOptions)

flatMap()

Observable<BaseProduct>

Observable<Product>

Observable<BaseOption>

Observable<Option>

Observable<Product>

flatMap()

Page 55: An Introduction to RxJava

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()

Page 56: An Introduction to RxJava

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()

Page 57: An Introduction to RxJava

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()

Page 58: An Introduction to RxJava

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()

Page 59: An Introduction to RxJava

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()

Page 60: An Introduction to RxJava

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()

Page 61: An Introduction to RxJava

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()

Page 62: An Introduction to RxJava

05/02/2023RxJava

62

Observable ProductObservable<Product> getProduct(Long productId) { return baseProductClient.getBaseProduct(productId)…

}

Get Non Blocking Base Product

Page 63: An Introduction to RxJava

05/02/2023RxJava

63

Observable ProductObservable<Product> getProduct(Long productId) { return baseProductClient.getBaseProduct(productId).flatMap(baseProduct -> {

}

Flat Map Base Product

Page 64: An Introduction to RxJava

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.

Page 65: An Introduction to RxJava

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

Page 66: An Introduction to RxJava

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]

Page 67: An Introduction to RxJava

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

Page 68: An Introduction to RxJava

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));

Page 69: An Introduction to RxJava

05/02/2023RxJava

69

Example Run

Page 70: An Introduction to RxJava

05/02/2023RxJava

70

Cold and Hot Observable

Page 71: An Introduction to RxJava

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?

Page 72: An Introduction to RxJava

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

Page 73: An Introduction to RxJava

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.

Page 74: An Introduction to RxJava

05/02/2023RxJava

74

Hot Observable Example – Earth emitting Greetings

Hello 1439838374206

Hola1439838374207

Namaste 1439838374210

Bonjour 1439838375707

Emitting Greetings in multiple languages + Timestamp

Page 75: An Introduction to RxJava

05/02/2023RxJava

75

One Curious Observer

Hello 143983837900

Hola143983837901

Namaste 1439838374210

Bonjour 1439123123000

Page 76: An Introduction to RxJava

05/02/2023RxJava

76

Second Curious Observer

Hello 143983837900

Hola143983837901

Namaste 1439838374210

Bonjour 1439123123000

Page 77: An Introduction to RxJava

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()

Page 78: An Introduction to RxJava

05/02/2023RxJava

78

Connectable ObservableObservable<String> earthGreetings = Observable.create(new AlienGreetingOnSubscribe());

An Observable that emits

Greetings from Earth

Page 79: An Introduction to RxJava

05/02/2023RxJava

79

Connectable ObservableObservable<String> earthGreetings = Observable.create(new AlienGreetingOnSubscribe());

ConnectableObservable<String> hotGreetingObservable = earthGreetings.publish();

ConnectableObservable from source by calling

publish ()

Page 80: An Introduction to RxJava

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.

Page 81: An Introduction to RxJava

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.

Page 82: An Introduction to RxJava

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.

Page 83: An Introduction to RxJava

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.

Page 84: An Introduction to RxJava

05/02/2023RxJava

84

ConsoleNo

Subscribers

FirstObserver

SecondObserver

Page 85: An Introduction to RxJava

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.

Page 86: An Introduction to RxJava

05/02/2023RxJava

86

Console – replay()No

Subscribers

Observer gets it all

Page 87: An Introduction to RxJava

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

Page 88: An Introduction to RxJava

05/02/2023RxJava

88

Error Handling

Page 89: An Introduction to RxJava

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!!!”)); } }); }

Page 90: An Introduction to RxJava

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

Page 91: An Introduction to RxJava

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: {[]}}

Page 92: An Introduction to RxJava

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

Page 93: An Introduction to RxJava

05/02/2023RxJava

93

Testing and Debugging

Page 94: An Introduction to RxJava

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()

Page 95: An Introduction to RxJava

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!

Page 96: An Introduction to RxJava

05/02/2023RxJava

96

What is the hardest part of concurrent programming?

Page 97: An Introduction to RxJava

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()

Page 98: An Introduction to RxJava

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);

}

Page 99: An Introduction to RxJava

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!

Page 100: An Introduction to RxJava

05/02/2023RxJava

100

Conclusion

Page 101: An Introduction to RxJava

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

Page 102: An Introduction to 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

Page 103: An Introduction to RxJava

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()

Page 104: An Introduction to RxJava

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

Page 105: An Introduction to RxJava

05/02/2023RxJava

105

Thank you and Questions…https://github.com/digitaljoel/rxAir

Page 106: An Introduction to RxJava

05/02/2023RxJava

106

Addendum

Page 107: An Introduction to RxJava

05/02/2023RxJava

107

Subjects

Page 108: An Introduction to RxJava

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

Page 109: An Introduction to RxJava

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”);

Page 110: An Introduction to RxJava

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));

Page 111: An Introduction to RxJava

05/02/2023RxJava

111

Subjects not discussed

Behavior Subject Async Subject Slides provided at end

Page 112: An Introduction to RxJava

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!!!

Page 113: An Introduction to RxJava

05/02/2023RxJava

113

ConsoleNo

Subscribers

FirstObserver

SecondObserver