Slide 1

Slide 1 text

Got a question during this session? 
 Post it on sli.do ( #K100 )

Slide 2

Slide 2 text

RxJava, RxJava 2, Reactor State of the art of Reactive Streams on the JVM

Slide 3

Slide 3 text

David Wursteisen

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Writing asynchronous code: 
 it sucks

Slide 6

Slide 6 text

Future ExecutorService ex = Executors.newCachedThreadPool();
 Future future = ex.submit(() -> longProcessing());
 String result = future.get(); Blocking call

Slide 7

Slide 7 text

Future Future> future1 = /* ... */
 Future> future2 = /* ... */
 Future> future3 = /* ... */
 Future> future4 = /* ... */
 Future> future5 = /* ... */ Optimal Orchestration ?

Slide 8

Slide 8 text

Callback RemoteService service = buildRemoteService();
 service.getUser(id -> {
 service.getData(id, data -> {
 service.getSomething(data, whut -> { service.neverEndingCallBack(whut, () -> { }); });
 });
 }); Callback Hell

Slide 9

Slide 9 text

Relationship Status:
 it’s complicated

Slide 10

Slide 10 text

The problem of synchronous code

Slide 11

Slide 11 text

Synchronous Waiting for the response Caller Called

Slide 12

Slide 12 text

Impact on response time Slow server

Slide 13

Slide 13 text

It never works! It piss me off!

Slide 14

Slide 14 text

Asynchronous Caller Called Continuous work

Slide 15

Slide 15 text

Asynchronous allow to take advantage of the waiting time

Slide 16

Slide 16 text

Minimal impact on the response time

Slide 17

Slide 17 text

Write asynchronous code easily?

Slide 18

Slide 18 text

Emergence 
 of different approaches

Slide 19

Slide 19 text

2 Reactive Streams

Slide 20

Slide 20 text

Reactive Streams Reactive Streams API RxJava 2 Reactor Interface Implementation

Slide 21

Slide 21 text

Reactive Streams API is 
 a bridge 
 between implementations

Slide 22

Slide 22 text

Reactive Streams contract onSubscribe onNext onError onComplete

Slide 23

Slide 23 text

RxJava is not compatible 
 with Reactive Streams (You’ll have to use an adapter: RxJavaReactiveStreams) https://github.com/ReactiveX/RxJavaReactiveStreams

Slide 24

Slide 24 text

onNext * ( onError | onComplete ) 
 onNext * ( onError | onCompleted ) RxJava Reactive Streams

Slide 25

Slide 25 text

onNext * ( onError | onComplete ) 
 onNext * ( onError | onCompleted ) RxJava Reactive Streams Different name

Slide 26

Slide 26 text

Common approach

Slide 27

Slide 27 text

A P I t o h a n d l e e v e n t s synchronously or asynchronously through a flow of events

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

Map ( ⃝ → ⬛)

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

remoteApi.people(1).flatMap(luke -> { 
 Observable vehicles = Observable.from(luke.getVehiclesIds())
 .flatMap(remoteApi::vehicle)
 .map(vehicle -> luke.getName() + " can drive " + vehicle.getName());
 
 Observable starships = Observable.from(luke.getStarshipsIds())
 .flatMap(remoteApi::starship)
 .map(starship -> luke.getName() + " can fly with " + starship.getName());
 
 return Observable.merge(vehicles, starships); 
 }).subscribe(System.out::println);

Slide 32

Slide 32 text

remoteApi.people(1).flatMap(luke -> { 
 Observable vehicles = Observable.from(luke.getVehiclesIds())
 .flatMap(remoteApi::vehicle)
 .map(vehicle -> luke.getName() + " can drive " + vehicle.getName());
 
 Observable starships = Observable.from(luke.getStarshipsIds())
 .flatMap(remoteApi::starship)
 .map(starship -> luke.getName() + " can fly with " + starship.getName());
 
 return Observable.merge(vehicles, starships); 
 }).subscribe(System.out::println); Push of the result

Slide 33

Slide 33 text

remoteApi.people(1).flatMap(luke -> { 
 Observable vehicles = Observable.from(luke.getVehiclesIds())
 .flatMap(remoteApi::vehicle)
 .map(vehicle -> luke.getName() + " can drive " + vehicle.getName());
 
 Observable starships = Observable.from(luke.getStarshipsIds())
 .flatMap(remoteApi::starship)
 .map(starship -> luke.getName() + " can fly with " + starship.getName());
 
 return Observable.merge(vehicles, starships); 
 }).subscribe(System.out::println); Get Luke’s vehicles Get Luke’s starships

Slide 34

Slide 34 text

remoteApi.people(1).flatMap(luke -> { 
 Observable vehicles = Observable.from(luke.getVehiclesIds())
 .flatMap(remoteApi::vehicle)
 .map(vehicle -> luke.getName() + " can drive " + vehicle.getName());
 
 Observable starships = Observable.from(luke.getStarshipsIds())
 .flatMap(remoteApi::starship)
 .map(starship -> luke.getName() + " can fly with " + starship.getName());
 
 return Observable.merge(vehicles, starships); 
 }).subscribe(System.out::println); Merge of two flows

Slide 35

Slide 35 text

remoteApi.people(1).flatMap(luke -> { 
 Observable vehicles = Observable.from(luke.getVehiclesIds())
 .flatMap(remoteApi::vehicle)
 .map(vehicle -> luke.getName() + " can drive " + vehicle.getName());
 
 Observable starships = Observable.from(luke.getStarshipsIds())
 .flatMap(remoteApi::starship)
 .map(starship -> luke.getName() + " can fly with " + starship.getName());
 
 return Observable.merge(vehicles, starships); 
 }).subscribe(System.out::println); Really execute the code

Slide 36

Slide 36 text

remoteApi.people(1).flatMap(luke -> { 
 Observable vehicles = Observable.from(luke.getVehiclesIds())
 .flatMap(remoteApi::vehicle)
 .map(vehicle -> luke.getName() + " can drive " + vehicle.getName());
 
 Observable starships = Observable.from(luke.getStarshipsIds())
 .flatMap(remoteApi::starship)
 .map(starship -> luke.getName() + " can fly with " + starship.getName());
 
 return Observable.merge(vehicles, starships); 
 }).subscribe(System.out::println); Flow of events

Slide 37

Slide 37 text

remoteApi.people(1).flatMap(luke -> { 
 Observable vehicles = Observable.from(luke.getVehiclesIds())
 .flatMap(remoteApi::vehicle)
 .map(vehicle -> luke.getName() + " can drive " + vehicle.getName());
 
 Observable starships = Observable.from(luke.getStarshipsIds())
 .flatMap(remoteApi::starship)
 .map(starship -> luke.getName() + " can fly with " + starship.getName());
 
 return Observable.merge(vehicles, starships); 
 }).subscribe(System.out::println); Flow of events Flow of events

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

Button btn = new Button();
 btn.setText("Click Me");
 
 JavaFx.fromClick(btn) 
 .observeOn(Schedulers.io()) 
 .switchMap(evt -> remoteApi.getData())
 .observeOn(javaFx()) 
 .doOnNext(value -> btn.setText("Data: " + value))
 .subscribe();

Slide 40

Slide 40 text

Button btn = new Button();
 btn.setText("Click Me");
 
 JavaFx.fromClick(btn) // Observable
 .observeOn(Schedulers.io())
 .switchMap(evt -> remoteApi.getData())
 .observeOn(javaFx()) 
 .doOnNext(value -> btn.setText("Data: " + value))
 .subscribe(); Listen for clicks

Slide 41

Slide 41 text

Button btn = new Button();
 btn.setText("Click Me");
 
 JavaFx.fromClick(btn) // Observable
 .observeOn(Schedulers.io())
 .switchMap(evt -> remoteApi.getData())
 .observeOn(javaFx()) 
 .doOnNext(value -> btn.setText("Data: " + value))
 .subscribe(); Execution context switch

Slide 42

Slide 42 text

Button btn = new Button();
 btn.setText("Click Me");
 
 JavaFx.fromClick(btn) // Observable
 .observeOn(Schedulers.io())
 .switchMap(evt -> remoteApi.getData()) // Observable
 .observeOn(javaFx()) 
 .doOnNext(value -> btn.setText("Data: " + value))
 .subscribe(); Asynchronous call to a web service

Slide 43

Slide 43 text

Button btn = new Button();
 btn.setText("Click Me");
 
 JavaFx.fromClick(btn) // Observable
 .observeOn(Schedulers.io())
 .switchMap(evt -> remoteApi.getData()) // Observable
 .observeOn(javaFx()) 
 .doOnNext(value -> btn.setText("Data: " + value))
 .subscribe(); Execution context switch

Slide 44

Slide 44 text

Button btn = new Button();
 btn.setText("Click Me");
 
 JavaFx.fromClick(btn) // Observable
 .observeOn(Schedulers.io())
 .switchMap(evt -> remoteApi.getData()) // Observable
 .observeOn(javaFx()) 
 .doOnNext(value -> btn.setText("Data: " + value))
 .subscribe(); Update on the UI

Slide 45

Slide 45 text

Button btn = new Button();
 btn.setText("Click Me");
 
 JavaFx.fromClick(btn) // Observable
 .observeOn(Schedulers.io())
 .switchMap(evt -> remoteApi.getData()) // Observable
 .observeOn(javaFx()) 
 .doOnNext(value -> btn.setText("Data: " + value))
 .subscribe(); Flow of events

Slide 46

Slide 46 text

Thanks to RxJava and Reactor …

Slide 47

Slide 47 text

Writing asynchronous code: 
 it sucks

Slide 48

Slide 48 text

Once upon a time…

Slide 49

Slide 49 text

Creation of 
 Reactive Extensions Creation of RxJava Active Participation Resumption of 
 RxJava & RxJava 2 Creation of Reactor Work on Reactor

Slide 50

Slide 50 text

RxJava 
 is a 
 proved
 technologie

Slide 51

Slide 51 text

Reactor
 benefits from the experience of
 RxJava (and vice versa)

Slide 52

Slide 52 text

Object types

Slide 53

Slide 53 text

Observable

Slide 54

Slide 54 text

No content

Slide 55

Slide 55 text

No content

Slide 56

Slide 56 text

No content

Slide 57

Slide 57 text

No content

Slide 58

Slide 58 text

No content

Slide 59

Slide 59 text

Single

Slide 60

Slide 60 text

No content

Slide 61

Slide 61 text

Completable

Slide 62

Slide 62 text

No content

Slide 63

Slide 63 text

RxJava Contrat Backpressure Observable [N] Yes Single [1] No Completable [0] No Added afterward Web service call Background process

Slide 64

Slide 64 text

Listen a websocket, for each received command, compose a response by calling 3 different webservices, then execute 2 jobs sequentially ?

Slide 65

Slide 65 text

Listen a websocket, for each received command, compose a response by calling 3 different webservices, then execute 2 jobs sequentially ?

Slide 66

Slide 66 text

Listen a websocket, for each received command, compose a response by calling 3 different webservices, then execute 2 jobs sequentially ?

Slide 67

Slide 67 text

Listen a websocket, for each received command, compose a response by calling 3 different webservices, then execute 2 jobs sequentially ?

Slide 68

Slide 68 text

websocket("/topics/cmd")
 .observeOn(Schedulers.io())
 .switchMap(cmd ->
 Single.zip(
 api.getActions(),
 api.getScore(),
 api.getUserData(),
 this::composeResult).toObservable())
 .observeOn(Schedulers.computation())
 .concatMap(result -> updateDb(result).andThen(getLastResults()))
 .subscribe(last -> System.out.println("last results -> " + last));

Slide 69

Slide 69 text

websocket("/topics/cmd")
 .observeOn(Schedulers.io())
 .switchMap(cmd ->
 Single.zip(
 api.getActions(),
 api.getScore(),
 api.getUserData(),
 this::composeResult).toObservable())
 .observeOn(Schedulers.computation())
 .concatMap(result -> updateDb(result).andThen(getLastResults()))
 .subscribe(last -> System.out.println("last results -> " + last)); Listen a websocket Observable

Slide 70

Slide 70 text

websocket("/topics/cmd")
 .observeOn(Schedulers.io())
 .switchMap(cmd ->
 Single.zip(
 api.getActions(),
 api.getScore(),
 api.getUserData(),
 this::composeResult).toObservable())
 .observeOn(Schedulers.computation())
 .concatMap(result -> updateDb(result).andThen(getLastResults()))
 .subscribe(last -> System.out.println("last results -> " + last)); Webservices composition Single

Slide 71

Slide 71 text

websocket("/topics/cmd")
 .observeOn(Schedulers.io())
 .switchMap(cmd ->
 Single.zip(
 api.getActions(),
 api.getScore(),
 api.getUserData(),
 this::composeResult).toObservable())
 .observeOn(Schedulers.computation())
 .concatMap(result -> updateDb(result).andThen(getLastResults()))
 .subscribe(last -> System.out.println("last results -> " + last)); Completable 2 jobs executions

Slide 72

Slide 72 text

websocket("/topics/cmd")
 .observeOn(Schedulers.io())
 .switchMap(cmd ->
 Single.zip(
 api.getActions(),
 api.getScore(),
 api.getUserData(),
 this::composeResult).toObservable())
 .observeOn(Schedulers.computation())
 .concatMap(result -> updateDb(result).andThen(getLastResults()))
 .subscribe(last -> System.out.println("last results -> " + last)); Listen a websocket Observable Webservices composition Single Completable 2 jobs executions

Slide 73

Slide 73 text

RxJava 2 Contrat Backpressure Observable [N] No Single [1] No Completable [0] No Maybe [0|1] No New! Close to Java 8 Optional

Slide 74

Slide 74 text

Maybe

Slide 75

Slide 75 text

No content

Slide 76

Slide 76 text

Backpressure using RxJava 2

Slide 77

Slide 77 text

Consumer

Slide 78

Slide 78 text

Consumer To many things !

Slide 79

Slide 79 text

backpressure

Slide 80

Slide 80 text

MissingBackpressureException ?

Slide 81

Slide 81 text

acceptedIntent
 .filter(intent -> !intent.getBooleanExtra("UpdatePhoneMode", false))
 .concatMap(intent -> approximatedEngine.detectCurrentPlace())
 .doOnNext(score -> Log.info(TAG, "Scan completed with result " + score))
 .concatMap(this::detectSleepMode)
 .concatMap((score) -> isNewPlace(score.getScore().getPlace()).map(p -> score))
 .doOnNext((p) -> Log.info(TAG, "Current place found is : " + p))
 .subscribe()

Slide 82

Slide 82 text

acceptedIntent
 .filter(intent -> !intent.getBooleanExtra("UpdatePhoneMode", false)) .onBackpressureDrop()
 .concatMap(intent -> approximatedEngine.detectCurrentPlace())
 .doOnNext(score -> Log.info(TAG, "Scan completed with result " + score))
 .onBackpressureDrop() .concatMap(this::detectSleepMode)
 .onBackpressureDrop()
 .concatMap((score) -> isNewPlace(score.getScore().getPlace()).map(p -> score))
 .doOnNext((p) -> Log.info(TAG, "Current place found is : " + p))
 .subscribe() Added while I panicked

Slide 83

Slide 83 text

RxJava 2 Contrat Backpressure Observable [N] No Single [1] No Completable [0] No Maybe [0|1] No New! Close to Java 8 Optional

Slide 84

Slide 84 text

RxJava 2 Contrat Backpressure Observable [N] No Single [1] No Completable [0] No Maybe [0|1] No Flowable [N] Yes New! Observable with 
 back pressure Close to Java 8 Optional

Slide 85

Slide 85 text

Observable → less than 1000 events → User interface management → To be used instead of Java 8 Streams Flowable → more than 10 000 events → Control the data flow → Network stream with flow management

Slide 86

Slide 86 text

What does Reactor offer ?

Slide 87

Slide 87 text

Flux Mono Maximum of 1 element

Slide 88

Slide 88 text

Reactor Contrat Backpressure Flux [N] Yes Mono [0|1] Yes Identical to Flowable Flux with only 
 1 element

Slide 89

Slide 89 text

Object types and
 Reactive Streams

Slide 90

Slide 90 text

Publisher Flux Flowable Reactive Streams

Slide 91

Slide 91 text

Flux.range(1, 10)
 .flatMap(i -> Flux.just(1))
 .subscribe();

Slide 92

Slide 92 text

Flux.range(1, 10)
 .flatMap(i -> Flux.just(1))
 .subscribe(); Publisher

Slide 93

Slide 93 text

Flux.range(1, 10)
 .flatMap(i -> Flowable.just(1))
 .subscribe(); Publisher RxJava 2

Slide 94

Slide 94 text

Flowable.defer(() -> Flux.range(1, 10))
 .subscribe(System.out::println); RxJava 2 Reactor

Slide 95

Slide 95 text

Flux.defer(() -> Flowable.range(1, 10))
 .subscribe(System.out::println); RxJava 2 Reactor

Slide 96

Slide 96 text

You can use a library which use RxJava 2 in your Reactor project (and vice versa)

Slide 97

Slide 97 text

Operators

Slide 98

Slide 98 text

Consequent and homogenous Catalogue

Slide 99

Slide 99 text

all amb ambArray ambWith any as awaitOnSubscribe blockFirst blockFirstMillis blockLast blockLastMillis blockingFirst blockingForEach blockingIterable blockingLast blockingLatest blockingMostRecent blockingNext blockingSingle blockingSubscribe buffer bufferMillis bufferSize bufferTimeout bufferTimeoutMillis bufferUntil bufferWhile cache cacheWithInitialCapacity cancelOn cast checkpoint collect collectInto collectList collectMap collectMultimap collectSortedList combineLatest combineLatestDelayError compose concat concatArray concatArrayDelayError concatArrayEager concatDelayError concatEager concatMap concatMapDelayError concatMapEager concatMapEagerDelayError concatMapIterable concatWith contains count create debounce defaultIfEmpty defer delay delayElements delayElementsMillis delayMillis delaySubscription delaySubscriptionMillis dematerialize distinct distinctUntilChanged doAfterNext doAfterTerminate doFinally doOnCancel doOnComplete doOnEach doOnError doOnLifecycle doOnNext doOnRequest doOnSubscribe doOnTerminate elapsed elementAt elementAtOrError empty equals error filter first firstElement firstEmitting firstEmittingWith firstOrError flatMap flatMapCompletable flatMapIterable flatMapMaybe flatMapSequential flatMapSingle forEach forEachWhile from fromArray fromCallable fromFuture fromIterable fromPublisher fromStream generate getClass getPrefetch groupBy groupJoin handle hasElement hasElements hashCode hide ignoreElements interval intervalMillis intervalRange isEmpty join just last lastElement lastOrError lift limitRate log map mapError materialize merge mergeArray mergeArrayDelayError mergeDelayError mergeSequential mergeWith never next notify notifyAll observeOn ofType onBackpressureBuffer onBackpressureDrop onBackpressureError onBackpressureLatest onErrorResumeNext onErrorResumeWith onErrorReturn onErrorReturnItem onExceptionResumeNext onTerminateDetach parallel publish publishNext publishOn range rangeLong rebatchRequests reduce reduceWith repeat repeatUntil repeatWhen replay replayMillis retry retryUntil retryWhen safeSubscribe sample sampleFirst sampleFirstMillis sampleMillis sampleTimeout scan scanWith sequenceEqual serialize share single singleElement singleOrEmpty singleOrError skip skipLast skipMillis skipUntil skipUntilOther skipWhile sort sorted startWith startWithArray strict subscribe subscribeOn subscribeWith switchIfEmpty switchMap switchMapDelayError switchOnError switchOnNext switchOnNextDelayError take takeLast takeMillis takeUntil takeUntilOther takeWhile test then thenEmpty thenMany throttleFirst throttleLast throttleWithTimeout timeInterval timeout timeoutMillis timer timestamp to toFuture toIterable toList toMap toMultimap toObservable toSortedList toStream toString transform unsafeCreate unsubscribeOn using wait window windowMillis windowTimeout windowTimeoutMillis windowUntil windowWhile withLatestFrom zip zipArray zipIterable zipWith zipWithIterable

Slide 100

Slide 100 text

RxJava RxJava 2 Reactor flatMap flatMap flatMap Emit Noe, one or more events amb amb firstEmitting Emit events from the first emitting stream … … … … debounce debounce N/A Ignore events during a time laps

Slide 101

Slide 101 text

RxJava RxJava 2 Reactor flatMap flatMap flatMap Emit Noe, one or more events amb amb firstEmitting Emit events from the first emitting stream … … … … debounce debounce N/A Ignore events during a time laps Renamed

Slide 102

Slide 102 text

Operators cover a lot of scenarios

Slide 103

Slide 103 text

Nota bene

Slide 104

Slide 104 text

https://github.com/ReactiveX/RxJava/wiki/Implementing-custom-operators-(draft) writing operators is hard when one writes an operator, the Observable protocol, unsubscription, backpressure and concurrency have to be taken into account and adhered to the letter

Slide 105

Slide 105 text

Writing a new operator with RxJava 2 is more complex than with RxJava

Slide 106

Slide 106 text

Make a application Reactive

Slide 107

Slide 107 text

Reactive Reactive Synchronous API Callback Reactive Reactive

Slide 108

Slide 108 text

Factory

Slide 109

Slide 109 text

RxJava
 RxJava 2 Reactor Flowable.just Flux.just Emitting existing value Flowable.defer Flux.defer Lazy emitting Flowable.fromCallable Mono.fromCallable Lazy emitting, computed from a method call Flowable.create Flux.create Manual emitting Flowable.using Flux.using Resource management Flowable.fromPublisher Flux.from Using a Publisher (Reactive Streams) Flowable.generate Flux.generate Using a value generator

Slide 110

Slide 110 text

RxJava
 RxJava 2 Reactor Flowable.just Flux.just Emitting existing value Flowable.defer Flux.defer Lazy emitting Flowable.fromCallable Mono.fromCallable Lazy emitting, computed from a method call Flowable.create Flux.create Manual emitting Flowable.using Flux.using Resource management Flowable.fromPublisher Flux.from Using a Publisher (Reactive Streams) Flowable.generate Flux.generate Using a value generator

Slide 111

Slide 111 text

RxJava
 RxJava 2 Reactor Flowable.just Flux.just Emitting existing value Flowable.defer Flux.defer Lazy emitting Flowable.fromCallable Mono.fromCallable Lazy emitting, computed from a method call Flowable.create Flux.create Manual emitting Flowable.using Flux.using Resource management Flowable.fromPublisher Flux.from Using a Publisher (Reactive Streams) Flowable.generate Flux.generate Using a value generator

Slide 112

Slide 112 text

RxJava
 RxJava 2 Reactor Flowable.just Flux.just Emitting existing value Flowable.defer Flux.defer Lazy emitting Flowable.fromCallable Mono.fromCallable Lazy emitting, computed from a method call Flowable.create Flux.create Manual emitting Flowable.using Flux.using Resource management Flowable.fromPublisher Flux.from Using a Publisher (Reactive Streams) Flowable.generate Flux.generate Using a value generator

Slide 113

Slide 113 text

example of wrapping

Slide 114

Slide 114 text

@RestController
 public class HelloController {
 
 private static final byte[] TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis")
 private String redis() throws InterruptedException {
 CountDownLatch latch = new CountDownLatch(1);
 AtomicReference result = new AtomicReference<>();
 this.connection.subscribe((message, pattern) -> {
 result.set(message.toString());
 latch.countDown();
 }, TOPIC_NAME);
 latch.await();
 return result.get();
 } }

Slide 115

Slide 115 text

@RestController
 public class HelloController {
 
 private static final byte[] TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis")
 private String redis() throws InterruptedException {
 CountDownLatch latch = new CountDownLatch(1);
 AtomicReference result = new AtomicReference<>();
 this.connection.subscribe((message, pattern) -> {
 result.set(message.toString());
 latch.countDown();
 }, TOPIC_NAME);
 latch.await();
 return result.get();
 } }

Slide 116

Slide 116 text

@RestController
 public class HelloController {
 
 private static final byte[] TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis")
 private String redis() throws InterruptedException {
 CountDownLatch latch = new CountDownLatch(1);
 AtomicReference result = new AtomicReference<>();
 this.connection.subscribe((message, pattern) -> {
 result.set(message.toString());
 latch.countDown();
 }, TOPIC_NAME);
 latch.await();
 return result.get();
 } }

Slide 117

Slide 117 text

@RestController
 public class HelloController {
 
 private static final byte[] TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis")
 private String redis() throws InterruptedException {
 CountDownLatch latch = new CountDownLatch(1);
 AtomicReference result = new AtomicReference<>();
 this.connection.subscribe((message, pattern) -> {
 result.set(message.toString());
 latch.countDown();
 }, TOPIC_NAME);
 latch.await();
 return result.get();
 } } Code for synchronisation Code for synchronisation

Slide 118

Slide 118 text

Step 1 
 Wrapping

Slide 119

Slide 119 text

@RestController
 public class HelloController {
 
 private static final byte[] TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis")
 private String redis() throws InterruptedException {
 
 String result = Flowable.create(sub -> {
 this.connection.subscribe((message, pattern) -> {
 sub.onNext(message.toString());
 sub.onComplete();
 }, TOPIC_NAME);
 }, BackpressureStrategy.BUFFER)
 .blockingFirst();
 return result;
 } }

Slide 120

Slide 120 text

@RestController
 public class HelloController {
 
 private static final byte[] TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis")
 private String redis() throws InterruptedException {
 
 String result = Flowable.create(sub -> {
 this.connection.subscribe((message, pattern) -> {
 sub.onNext(message.toString());
 sub.onComplete();
 }, TOPIC_NAME);
 }, BackpressureStrategy.BUFFER)
 .blockingFirst();
 return result;
 } } Wrapping Synchronisation Reactive Contract

Slide 121

Slide 121 text

Step 2 Asynchronous

Slide 122

Slide 122 text

@RestController
 public class HelloController {
 
 private static final byte[] TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis")
 private DeferredResult redis() throws InterruptedException {
 
 DeferredResult result = new DeferredResult<>(10_000l);
 
 Flowable.create(sub -> {
 this.connection.subscribe((message, pattern) -> {
 sub.onNext(message.toString());
 sub.onComplete();
 }, TOPIC_NAME);
 }, BackpressureStrategy.BUFFER)
 .subscribe(result::setResult);
 
 return result;
 }

Slide 123

Slide 123 text

@RestController
 public class HelloController {
 
 private static final byte[] TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis")
 private DeferredResult redis() throws InterruptedException {
 
 DeferredResult result = new DeferredResult<>(10_000l);
 
 Flowable.create(sub -> {
 this.connection.subscribe((message, pattern) -> {
 sub.onNext(message.toString());
 sub.onComplete();
 }, TOPIC_NAME);
 }, BackpressureStrategy.BUFFER)
 .subscribe(result::setResult);
 
 return result;
 } Lazy result Use of DeferredResult

Slide 124

Slide 124 text

Step 3 
 Reactive Streams

Slide 125

Slide 125 text

@RestController
 public class HelloController {
 
 private static final byte[] TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
 private Flux redis() throws InterruptedException {
 
 Flowable rxjava = Flowable.create(sub -> {
 this.connection.subscribe((message, pattern) -> sub.onNext(message.toString()), TOPIC_NAME);
 }, BackpressureStrategy.BUFFER);
 
 return Flux.defer(() -> rxjava);
 } }

Slide 126

Slide 126 text

@RestController
 public class HelloController {
 
 private static final byte[] TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
 private Flux redis() throws InterruptedException {
 
 Flowable rxjava = Flowable.create(sub -> {
 this.connection.subscribe((message, pattern) -> sub.onNext(message.toString()), TOPIC_NAME);
 }, BackpressureStrategy.BUFFER);
 
 return Flux.defer(() -> rxjava);
 } } RxJava 2 → Flux Flux → SSE Return a Flux

Slide 127

Slide 127 text

@RestController
 public class HelloController {
 
 private static final byte[] TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
 private Publisher redis() throws InterruptedException {
 return Flowable.create(sub -> {
 this.connection.subscribe((message, pattern) -> sub.onNext(message.toString()), TOPIC_NAME);
 }, BackpressureStrategy.BUFFER);
 
 }

Slide 128

Slide 128 text

@RestController
 public class HelloController {
 
 private static final byte[] TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
 private Publisher redis() throws InterruptedException {
 return Flowable.create(sub -> {
 this.connection.subscribe((message, pattern) -> sub.onNext(message.toString()), TOPIC_NAME);
 }, BackpressureStrategy.BUFFER);
 
 } Publisher

Slide 129

Slide 129 text

No content

Slide 130

Slide 130 text

Reactor use Java 8 while RxJava 2 use Java 6

Slide 131

Slide 131 text

Reactor use Java 8 while RxJava 2 use Java 6

Slide 132

Slide 132 text

Asynchronous Execution context management

Slide 133

Slide 133 text

Schedulers Rethink cette partie là

Slide 134

Slide 134 text

Scheduler 
 (Thread Pool) Task 1 Task 2 Task 3 Task 4

Slide 135

Slide 135 text

Task 1 Task 2 Task 3 Task 4 Scheduler 
 (Thread Pool)

Slide 136

Slide 136 text

Task 1 Task 2 Task 3 Task 4 Scheduler 
 (Thread Pool)

Slide 137

Slide 137 text

Task 1 Task 2 Task 3 Task 4 Scheduler 
 (Thread Pool)

Slide 138

Slide 138 text

Task 1 Task 2 Task 3 Task 4 Scheduler 
 (Thread Pool)

Slide 139

Slide 139 text

Task 1 Task 2 Task 3 Task 4 Scheduler 
 (Thread Pool)

Slide 140

Slide 140 text

Task 1 Task 2 Task 3 Task 4 Scheduler 
 (Thread Pool)

Slide 141

Slide 141 text

Task 1 Task 2 Task 3 Task 4 Scheduler 
 (Thread Pool)

Slide 142

Slide 142 text

Task 1 Task 2 Task 3 Task 4 Scheduler 
 (Thread Pool)

Slide 143

Slide 143 text

java.lang.IllegalStateException: 
 Not on the main thread NetworkOnMainThreadException

Slide 144

Slide 144 text

JavaFx.fromClick(btn) 
 .observeOn(Schedulers.io())
 .switchMap(evt -> remoteApi.getData())
 .observeOn(Schedulers.computation())
 .flatMap(data -> intensiveComputation(data))
 .observeOn(javaFx())
 .doOnNext(value -> btn.setText("Data: " + value)) 
 .subscribe();

Slide 145

Slide 145 text

JavaFx.fromClick(btn) 
 .observeOn(Schedulers.io())
 .switchMap(evt -> remoteApi.getData())
 .observeOn(Schedulers.computation())
 .flatMap(data -> intensiveComputation(data))
 .observeOn(javaFx())
 .doOnNext(value -> btn.setText("Data: " + value)) 
 .subscribe(); i/o computation UI Thread

Slide 146

Slide 146 text

RxJava RxJava 2 Reactor Description io() io() elastic() Thread pool which grow up if needed computation() computation() parallel() Limited thread pool single() single() single() Pool of 1 thread immediate() immediate() Execute the task immediately trampoline() trampoline() Queue the current task

Slide 147

Slide 147 text

RxJava RxJava 2 Reactor Description io() io() elastic() Thread pool which grow up if needed computation() computation() parallel() Limited thread pool single() single() single() Pool of 1 thread immediate() immediate() Execute the task immediately trampoline() trampoline() Queue the current task

Slide 148

Slide 148 text

RxJava RxJava 2 Reactor Description io() io() elastic() Thread pool which grow up if needed computation() computation() parallel() Limited thread pool single() single() single() Pool of 1 thread immediate() immediate() Execute the task immediately trampoline() trampoline() Queue the current task

Slide 149

Slide 149 text

Reactor Technical naming

Slide 150

Slide 150 text

RxJava Functional naming

Slide 151

Slide 151 text

Performance

Slide 152

Slide 152 text

Generation 3 4 5+ Fusion RxJava 2 Reactor

Slide 153

Slide 153 text

Warning Conceptuel slides

Slide 154

Slide 154 text

Without fusion

Slide 155

Slide 155 text

Transform ( ⬛ → ⃝ ) Transform ( ⃝ → ⬛)

Slide 156

Slide 156 text

Transform ( ⬛ → ⃝ ) Transform ( ⃝ → ⬛)

Slide 157

Slide 157 text

Transform ( ⬛ → ⃝ ) Transform ( ⃝ → ⬛)

Slide 158

Slide 158 text

Transform ( ⬛ → ⃝ ) Transform ( ⃝ → ⬛)

Slide 159

Slide 159 text

Transform ( ⬛ → ⃝ ) Transform ( ⃝ → ⬛)

Slide 160

Slide 160 text

Transform ( ⬛ → ⃝ ) Transform ( ⃝ → ⬛)

Slide 161

Slide 161 text

With fusion

Slide 162

Slide 162 text

Transform ( ⬛ → ⃝ ) Transform ( ⃝ → ⬛)

Slide 163

Slide 163 text

Transform ( ⬛ → ⃝ ) Transform ( ⃝ → ⬛)

Slide 164

Slide 164 text

Transform ( ⬛ → ⃝ ) Transform ( ⃝ → ⬛)

Slide 165

Slide 165 text

Transform ( ⬛ → ⃝ ) Transform ( ⃝ → ⬛)

Slide 166

Slide 166 text

Transform ( ⬛ → ⃝ ) Transform ( ⃝ → ⬛)

Slide 167

Slide 167 text

Fusion decreases memory consumption and increases performances

Slide 168

Slide 168 text

for (int x = 0; x < 10_000; x++) {
 
 Observable.interval(10, TimeUnit.MILLISECONDS)
 .takeWhile(i -> take.get())
 .flatMap(i -> Observable.range(1, 100))
 .subscribe();
 }

Slide 169

Slide 169 text

RxJava 2 RxJava Reactor

Slide 170

Slide 170 text

http://akarnokd.blogspot.fr/2016/12/the-reactive-scrabble-benchmarks.html Java 8 Stream RxJava 2 / Reactor RxJava December 2016

Slide 171

Slide 171 text

Java 8 Stream RxJava 2 / Reactor RxJava https://twitter.com/akarnokd/status/844555409012740096 March 2017

Slide 172

Slide 172 text

Ecosystem

Slide 173

Slide 173 text

RxJava RxJava 2 Reactor Retrofit Yes Yes No RxAndroid Yes Yes No Realm Yes No No Hystrix Yes No No Couchbase Yes No No MongoDB Yes No No Spring Data 2.0 Yes No Yes Reactor IPC No No Yes WebFlux No Yes Yes Android Spring

Slide 174

Slide 174 text

RxJava RxJava 2 Reactor Retrofit Yes Yes No RxAndroid Yes Yes No Realm Yes No No Hystrix Yes No No Couchbase Yes No No MongoDB Yes No No Spring Data 2.0 Yes No Yes Reactor IPC No No Yes WebFlux No Yes Yes Android Spring

Slide 175

Slide 175 text

We are aggressively 
 migrating our internal code to RxJava 2 https://github.com/uber/AutoDispose

Slide 176

Slide 176 text

RxJava RxJava 2 Reactor Retrofit Yes Yes No RxAndroid Yes Yes No Realm Yes No No Hystrix Yes No No Couchbase Yes No No MongoDB Yes No No Spring Data 2.0 Yes No Yes Reactor IPC No No Yes WebFlux No Yes Yes Android Spring

Slide 177

Slide 177 text

Inertia to migrate

Slide 178

Slide 178 text

RxJava RxJava 2 Reactor Retrofit Yes Yes No RxAndroid Yes Yes No Realm Yes No No Hystrix Yes No No Couchbase Yes No No MongoDB Yes No No Spring Data 2.0 Yes No Yes Reactor IPC No No Yes WebFlux No Yes Yes Android Spring

Slide 179

Slide 179 text

Spring 5 will accelerate the adoption of Reactor

Slide 180

Slide 180 text

Android RxJava 2

Slide 181

Slide 181 text

Backend RxJava 2

Slide 182

Slide 182 text

Spring Reactor

Slide 183

Slide 183 text

Thanks for your attention We stay in touch? [email protected] @dwursteisen http://blog.soat.fr Post your question on sli.do ( #K100 )