Slide 1

Slide 1 text

Practical RxJava

Slide 2

Slide 2 text

@Couchbase @InfoQFR @bbl_fr @SimonBasle

Slide 3

Slide 3 text

the Plan & Goals

Slide 4

Slide 4 text

RxJava 101

Slide 5

Slide 5 text

migrate a Legacy application RxJava 101

Slide 6

Slide 6 text

migrate a Legacy application learn Operators of interest RxJava 101

Slide 7

Slide 7 text

migrate a Legacy application learn Operators of interest 9 steps + Q& A RxJava 101

Slide 8

Slide 8 text

Why?

Slide 9

Slide 9 text

Blocking it’s Evil, m’kay?

Slide 10

Slide 10 text

Blocking it’s Evil, m’kay?

Slide 11

Slide 11 text

we need asynchronous code

Slide 12

Slide 12 text

we need reactive asynchronous code

Slide 13

Slide 13 text

we need parallelisable asynchronous code

Slide 14

Slide 14 text

we need composable asynchronous code

Slide 15

Slide 15 text

we need readable asynchronous code

Slide 16

Slide 16 text

but how ?

Slide 17

Slide 17 text

Futures? Callbacks?

Slide 18

Slide 18 text

Futures? Callbacks? too easy to block (get) complex beyond 1 level of composition no composition have you heared of Callback Hell?

Slide 19

Slide 19 text

DocumentService.find("userId", new Callback>() { public void onSuccess(List result) { final List jsonList = new ArrayList(10); int taken = 0; for (Document doc : result) { if (taken >= 10) break; if (!doc.isStarred()) continue; taken++; final CountDownLatch rendezVous = new CountDownLatch(3); final JsonObject jsonBuffer = new JsonObject(); jsonBuffer.appendInt("id", doc.getId()); jsonBuffer.append("text", doc.getText()); CommentService.findForDoc(doc, new Callback>() { public void onSuccess(List comments) { final JsonObject commentArray = JsonObject.createArray(); CountDownLatch userLatch = new CountDownLatch(comments.size()); for (Comment c : comments) { JsonObject cj = new JsonObject(); cj.append("content", c.getText()); cj.append("date", c.getDate()); UserService.find(c.getUserId(), new Callback() { public void onSuccess(User user) { cj.append("author", user.getName()); cj.append("nickname", user.getLogin()); Futures? Callbacks? too easy to block (get) complex beyond 1 level of composition no composition have you heared of Callback Hell?

Slide 20

Slide 20 text

RxJava 101

Slide 21

Slide 21 text

RxJava 101

Slide 22

Slide 22 text

Netflix OpenSource

Slide 23

Slide 23 text

dual of Iterable - Iterator

Slide 24

Slide 24 text

Iterable - Iterator becomes Observable - Observer

Slide 25

Slide 25 text

Iterable - Iterator becomes Observable - Observer “Pull” “Push”

Slide 26

Slide 26 text

compose

Slide 27

Slide 27 text

compose asynchronous programs based on events

Slide 28

Slide 28 text

compose asynchronous programs based on events using observable sequences

Slide 29

Slide 29 text

the Reactive Manifesto reactivemanifesto.org

Slide 30

Slide 30 text

reactive-streams.org standardize on the jvm

Slide 31

Slide 31 text

reactive-streams.org standardize on the jvm akka - reactor - rxjava

Slide 32

Slide 32 text

Show Me how it works !

Slide 33

Slide 33 text

interface Observer

Slide 34

Slide 34 text

interface Observer onNext(T data)

Slide 35

Slide 35 text

interface Observer onNext(T data) onCompleted()

Slide 36

Slide 36 text

interface Observer onNext(T data) onCompleted() onError(Throwable t)

Slide 37

Slide 37 text

interface Observer onNext(T data) onCompleted() onError(Throwable t)

Slide 38

Slide 38 text

Observable

Slide 39

Slide 39 text

Observable compose & chain a stream

Slide 40

Slide 40 text

Observable subscribe an Observer

Slide 41

Slide 41 text

so much Choice, you’ll see!

Slide 42

Slide 42 text

still lost… time to practice

Slide 43

Slide 43 text

The Legacy app

Slide 44

Slide 44 text

Wow pool API? Much Legacy!

Slide 45

Slide 45 text

Doge Mining Pool Client (UI?) Rest Controller Rest Controller Rest Controller Rest Controller Service Service Service External API External API External API DB L E G A C Y

Slide 46

Slide 46 text

Doge Mining Pool Client (UI?) Rest Controller Rest Controller Rest Controller Rest Controller Service Service Service External API External API External API DB

Slide 47

Slide 47 text

Doge Mining Pool Client (UI?) Rest Controller Rest Controller Rest Controller Rest Controller Service Service Service External API External API External API DB

Slide 48

Slide 48 text

simple Creation 1

Slide 49

Slide 49 text

Migrate Services ● AdminService ● CoinService ● HashrateService ● PoolService *

Slide 50

Slide 50 text

Useful Operators ● Observable.just ● Observable.from ● Observable.create ● map

Slide 51

Slide 51 text

Useful Operators ● Observable.just ● Observable.from ● Observable.create ● map

Slide 52

Slide 52 text

But now it doesn’t compile how to adapt the Controllers?

Slide 53

Slide 53 text

Naively Block on an Observable take(n) vs single() vs first() xxxOrDefault(t), toList()

Slide 54

Slide 54 text

Take

Slide 55

Slide 55 text

Single

Slide 56

Slide 56 text

SingleOrDefault

Slide 57

Slide 57 text

Transform 2

Slide 58

Slide 58 text

Migrate Services ● PoolService ○ poolGigaHashrate method

Slide 59

Slide 59 text

Useful Operators ● flatMap ● reduce

Slide 60

Slide 60 text

flatMap

Slide 61

Slide 61 text

reduce

Slide 62

Slide 62 text

Filter 3

Slide 63

Slide 63 text

Migrate Services ● UserService ○ findAll for now naively adapted (Observable.from) ○ compose on findAll for getUser / getUserByLogin ● SearchService

Slide 64

Slide 64 text

Useful Operators ● filter ● take ● flatMap to asynchronously retrieve additional data needed for filter

Slide 65

Slide 65 text

filter

Slide 66

Slide 66 text

Count 4

Slide 67

Slide 67 text

Migrate Services RankingService ○ use from for rankByHashrate / rankByCoins ○ complete migration for other methods

Slide 68

Slide 68 text

Useful Operators ● takeUntil ● count ● take

Slide 69

Slide 69 text

takeUntil

Slide 70

Slide 70 text

count

Slide 71

Slide 71 text

Time for a Break :)

Slide 72

Slide 72 text

Side Effects 5

Slide 73

Slide 73 text

doOnXXX ● doOnNext ● doOnError ● doOnCompleted ● doOnEach

Slide 74

Slide 74 text

Migrate Services PoolService ○ add a line of log each time a user connects

Slide 75

Slide 75 text

Combine 6

Slide 76

Slide 76 text

Level: Simple Concat

Slide 77

Slide 77 text

Level: Intermediate Merge

Slide 78

Slide 78 text

Level: Advanced Zip

Slide 79

Slide 79 text

Migrate Services StatService.getAllStats ● for each User ○ retrieve his hashrate ○ retrieve how many coins he mined ○ combine both and make a UserStat

Slide 80

Slide 80 text

Live & Let Die and Retry oo 7

Slide 81

Slide 81 text

The Problem StatService.lastBlockFoundBy ○ fireproof implementation (choose a random User) ○ but what if… we wanted to do it without knowing the number of users in advance?

Slide 82

Slide 82 text

The Plan Generate an index randomly (within a broadly guessed limit) Retry up to 4 times if out of bounds Last resort: use a default User (eg. “Banned User”)

Slide 83

Slide 83 text

Useful Operators ● flatMap ● skip ● retry ● onErrorReturn

Slide 84

Slide 84 text

Retry

Slide 85

Slide 85 text

OnErrorReturn

Slide 86

Slide 86 text

Trap #1

Slide 87

Slide 87 text

skip doesn’t error if overflow Trap #1

Slide 88

Slide 88 text

skip doesn’t error if overflow combine with first/last Trap #1

Slide 89

Slide 89 text

Trap #2

Slide 90

Slide 90 text

just caches the value Trap #2

Slide 91

Slide 91 text

just caches the value use create to regenerate at each retry Trap #2

Slide 92

Slide 92 text

Chain 8

Slide 93

Slide 93 text

Migrate Services ExchangeRateService ○ calls two external APIs: doge-to-dollar rate and currency-to-currency exchange rate ○ two chained REST calls ○ combination of the two gives doge-to-anyCurrency

Slide 94

Slide 94 text

Useful Operators ● Observable.create ○ wrap the REST call on each subscription ○ catch RestClientException and make them into DogePoolException (especially for timeouts)

Slide 95

Slide 95 text

Useful Operators ● zipWith ○ similar to zip but called from stream A instead of statically ○ combine both rates to get the final one

Slide 96

Slide 96 text

Oh Hey! ! WARNING - Incoming Product Owner !

Slide 97

Slide 97 text

"this free exchange rate API crashes too often, make it so we switch to an alternative non-free API when it’s the case" - the Product Owner

Slide 98

Slide 98 text

"this free exchange rate API crashes too often, make it so we switch to an alternative non-free API when it’s the case" - the Product Owner

Slide 99

Slide 99 text

"oh yeah and if you could go on and track costs of these calls it would be great" - the Product Owner, pouring himself a coffee Much Surprise Such Requirements wow

Slide 100

Slide 100 text

The Plan ● AdminService ○ add method+variable to track cost for this month ● ExchangeRateService ○ rate retrieval method similar to current one ○ use endpoint from exchange.nonfree.api.baseUrl ● switch thanks to OnErrorResumeNext ● use side effects ○ log when we switch & track the cost

Slide 101

Slide 101 text

OnErrorResumeNext

Slide 102

Slide 102 text

Clean-up Controllers 9

Slide 103

Slide 103 text

Asynchronous Response ● prepare a DeferredResult ○ that will be returned without blocking ● subscribe on stream ○ onNext: inject T via setResult ○ onError: create a DogePoolException and inject it via setErrorResult

Slide 104

Slide 104 text

This could be Generalized ● using ReturnValueHandler and a simple adapter of Observable to DeferredResult ● each time an Observable is returned, it’ll be converted into this adapter ○ WebAsyncUtils.getAsyncManager(...). startDeferredResultProcessing(...)

Slide 105

Slide 105 text

Migrate Services ● AdminController (simple) ● IndexController (trickier) ○ use zip, flatMap, single… to detect bad users ● UserProfileController (idem)

Slide 106

Slide 106 text

Q& A

Slide 107

Slide 107 text

TakeAway

Slide 108

Slide 108 text

Nonblocking code

Slide 109

Slide 109 text

without Callbacks

Slide 110

Slide 110 text

with a minimum of visual cluter

Slide 111

Slide 111 text

readable and understandable

Slide 112

Slide 112 text

Hope you loved it!

Slide 113

Slide 113 text

No content

Slide 114

Slide 114 text

Merci!

Slide 115

Slide 115 text

➔ RxJava Logo and Marble Diagrams - ReactiveX Documentation http://reactivex.io ➔ Cat Attack - Static416 on Flickr ➔ Stormtroopers Series - J.D. Hancock http://photos.jdhancock.com/series/stormtroopers.html ➔ Blackhole with Corona - NASA on Wikimedia ➔ Broken Keyboard - Santeri Viinamäki on Wikimedia ➔ Gobot Toys- Tom Prankerd on Wikimedia ➔ Coffee Filter - Unsplash on Pixabay ➔ Abacus - Succo on Pixabay ➔ Still from Office Space - Copyright, 20th Century Fox By By-Nc By Cc0 By By Cc0 Cc0 © Credits (1/2)

Slide 116

Slide 116 text

➔ Hand Reaching - Kinseykick on Pixabay ➔ Sidecar Motocross - Jean-Daniel Echenard on Flickr ➔ Twin Falls - Blese on Flickr ➔ Tumbeast Gnawing on Servers - Matthew Inman on Wikimedia ➔ Trap - Anticiv on Flickr ➔ Kane Cleaning Supplies - Collinanderson on Flickr ➔ Chain - Stomchak on Wikimedia ➔ Takeaway - Edimburgh Blog on Flickr ➔ The End Sands - Elektro-Plan on Pixabay Cc0 By-Nd By-Nc By By-Sa By By By Cc0 Credits (2/2)