Slide 1

Slide 1 text

Get Reactive With Spring 5 And Project Reactor by Oleh Dokuka

Slide 2

Slide 2 text

• JSE at Levi9 • 6+ dev experience • Spring fan • Reactivity preacher /oleh.dokuka /OlegDokuka /OlehDokuka WHO AM I?

Slide 3

Slide 3 text

Agenda 1. Why Reactive? 2. Reactivity Generations 3. Reactive Streams 4. Project Reactor 5. Reactivity in Action (Project Reactor + Spring 5)

Slide 4

Slide 4 text

So, why Reactive?1

Slide 5

Slide 5 text

Requirements of Nowadays https://sites.psu.edu/luopassion2/2016/01/25/a-brief-history-of-the-internet-of-things-iot/

Slide 6

Slide 6 text

Lean resource management https://i.ytimg.com/vi/EiH1sJCDs9c/maxresdefault.jpg

Slide 7

Slide 7 text

Asynchrony http://www.cntraveler.com/story/the-main-reasons-your-passport-application-will-be-denied

Slide 8

Slide 8 text

Fault Tolerance

Slide 9

Slide 9 text

Powerful way of thinking http://www.wallpaperup.com/200710/pipes_cranes.html

Slide 10

Slide 10 text

Reactive-Manifesto2

Slide 11

Slide 11 text

Sounds Cool

Slide 12

Slide 12 text

Reactivity Generations 3

Slide 13

Slide 13 text

Handler Observer Java

Slide 14

Slide 14 text

Skill Knowledge Rx.NET

Slide 15

Slide 15 text

Akka RxJava

Slide 16

Slide 16 text

RxJava AkkaStreams

Slide 17

Slide 17 text

RxJava 2 AkkaStream Project Reactor Reactive Streams Specified

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

Reactive Streams4

Slide 20

Slide 20 text

What is the Purpose?

Slide 21

Slide 21 text

Backpressure

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

Common API

Slide 24

Slide 24 text

Publisher Subscriber

Slide 25

Slide 25 text

Publisher Subscriber public interface Publisher { public void subscribe( Subscriber super T> s ); }

Slide 26

Slide 26 text

Publisher Subscriber public interface Subscriber { public void onSubscribe(Subscription s); public void onNext(T t); public void onError(Throwable t); public void onComplete(); }

Slide 27

Slide 27 text

Publisher Subscriber Subscription

Slide 28

Slide 28 text

Publisher Subscriber Subscription public interface Subscription { public void request(long n); public void cancel(); }

Slide 29

Slide 29 text

Publisher Subscriber Subscription public interface Subscription { public void request(long n); public void cancel(); }

Slide 30

Slide 30 text

Publisher Subscriber Subscription

Slide 31

Slide 31 text

Processor Publisher Subscriber Subscription

Slide 32

Slide 32 text

Publisher Subscriber Subscription Processor public interface Processor extends Subscriber, Publisher {}

Slide 33

Slide 33 text

Example

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

No content

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

No content

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

Project Reactor

Slide 44

Slide 44 text

by

Slide 45

Slide 45 text

RxJava-like API

Slide 46

Slide 46 text

Reactive Types

Slide 47

Slide 47 text

Flux

Slide 48

Slide 48 text

like Stream

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

Mono

Slide 51

Slide 51 text

like CompletableFuture

Slide 52

Slide 52 text

No content

Slide 53

Slide 53 text

Useful Operators

Slide 54

Slide 54 text

Operator == Very Smart Publisher

Slide 55

Slide 55 text

merge .merge(…)

Slide 56

Slide 56 text

zip .zip(…)

Slide 57

Slide 57 text

zip .zip(…)

Slide 58

Slide 58 text

publish .publish(…)

Slide 59

Slide 59 text

.materialize(…) materialize

Slide 60

Slide 60 text

materialize .materialize(…)

Slide 61

Slide 61 text

Thread A Thread Main .publishOn(…) publishOn

Slide 62

Slide 62 text

No content

Slide 63

Slide 63 text

RxJava.observeOn == Reactor.publishOn

Slide 64

Slide 64 text

Remember!

Slide 65

Slide 65 text

Nothing happens until .subscribe ()

Slide 66

Slide 66 text

Reactivity in Action

Slide 67

Slide 67 text

What we`re going to do?

Slide 68

Slide 68 text

Refactoring

Slide 69

Slide 69 text

What do we have?

Slide 70

Slide 70 text

Chat Application

Slide 71

Slide 71 text

Functionality • Gitter Chat Communication • Messaging Statistic

Slide 72

Slide 72 text

Demo

Slide 73

Slide 73 text

No content

Slide 74

Slide 74 text

Toolkit • Spring Framework 4 • Spring Boot • Spring MVC • Spring Data JPA

Slide 75

Slide 75 text

Architecture

Slide 76

Slide 76 text

User Client Gitter Service Whole Application DB Layer Service Layer Controllers Layer

Slide 77

Slide 77 text

Controllers Layer

Slide 78

Slide 78 text

Returns Thymeleaf View

Slide 79

Slide 79 text

REST Resources

Slide 80

Slide 80 text

Services Layer

Slide 81

Slide 81 text

External Chats SPI

Slide 82

Slide 82 text

Domain Services

Slide 83

Slide 83 text

Gitter integration

Slide 84

Slide 84 text

Implementation

Slide 85

Slide 85 text

Persistence Layer

Slide 86

Slide 86 text

Database Model

Slide 87

Slide 87 text

How it works?

Slide 88

Slide 88 text

No content

Slide 89

Slide 89 text

No content

Slide 90

Slide 90 text

No content

Slide 91

Slide 91 text

No content

Slide 92

Slide 92 text

Problems

Slide 93

Slide 93 text

Problems • Pulling model

Slide 94

Slide 94 text

No content

Slide 95

Slide 95 text

Problems • Pulling model • Too much blocking I/O

Slide 96

Slide 96 text

Solutions

Slide 97

Slide 97 text

Apply Reactive Manifesto

Slide 98

Slide 98 text

No content

Slide 99

Slide 99 text

Async Messaging Push Model

Slide 100

Slide 100 text

Apply Streaming API

Slide 101

Slide 101 text

No content

Slide 102

Slide 102 text

No content

Slide 103

Slide 103 text

Async Messaging Elasticity

Slide 104

Slide 104 text

Dedicate ThreadPool

Slide 105

Slide 105 text

No content

Slide 106

Slide 106 text

No content

Slide 107

Slide 107 text

Async Messaging Push Model

Slide 108

Slide 108 text

Apply WebSocket

Slide 109

Slide 109 text

No content

Slide 110

Slide 110 text

How to bring it all together?

Slide 111

Slide 111 text

Spring 5

Slide 112

Slide 112 text

Painless replacement

Slide 113

Slide 113 text

WebFlux @Controller, @RequestMapping,… Spring MVC Servlet API Servlet Container Spring Web Reactive Reactive HTTP Servlet, Netty, Undertow

Slide 114

Slide 114 text

No content

Slide 115

Slide 115 text

No content

Slide 116

Slide 116 text

@RestController @RequestMapping("/api/v1/statistics") public class StatisticResource { private final StatisticService statisticService; @Autowired public StatisticResource( StatisticService statisticService) { this.statisticService = statisticService; } @GetMapping("/users") public List getUsersStatistic() { return statisticService.getUsersStatistic(); } }

Slide 117

Slide 117 text

@RestController @RequestMapping("/api/v1/statistics") public class StatisticResource { private final StatisticService statisticService; @Autowired public StatisticResource( StatisticService statisticService) { this.statisticService = statisticService; } @GetMapping("/users") public List getUsersStatistic() { return statisticService.getUsersStatistic(); } }

Slide 118

Slide 118 text

@RestController @RequestMapping("/api/v1/statistics") public class StatisticResource { private final StatisticService statisticService; @Autowired public StatisticResource( StatisticService statisticService) { this.statisticService = statisticService; } @GetMapping("/users") public Flux getUsersStatistic() { return Flux.fromIterable(statisticService .getUsersStatistic()); }

Slide 119

Slide 119 text

@RestController @RequestMapping("/api/v1/statistics") public class StatisticResource { private final StatisticService statisticService; @Autowired public StatisticResource( StatisticService statisticService) { this.statisticService = statisticService; } @GetMapping("/users") public Flux getUsersStatistic() { return Flux.fromIterable(statisticService .getUsersStatistic()); }

Slide 120

Slide 120 text

Project Reactor + Netty Integration

Slide 121

Slide 121 text

Why Netty?

Slide 122

Slide 122 text

Non-Blocking,Reactive Server

Slide 123

Slide 123 text

Reactive Architecture

Slide 124

Slide 124 text

Data Base Connection Pipe Gitter Connection Pipe

Slide 125

Slide 125 text

Refactoring Structure

Slide 126

Slide 126 text

1. Blocking I/O Refactoring 2. Service Refactoring 3. Endpoints Refactoring 4. Pipeline Testing

Slide 127

Slide 127 text

No content

Slide 128

Slide 128 text

Blocking I/O Refactoring

Slide 129

Slide 129 text

No content

Slide 130

Slide 130 text

Reactive DB Access via ReactiveCrudRepository

Slide 131

Slide 131 text

interface ReactiveCrudRepository extends Repository Mono save(S entity); Flux saveAll(Iterable entities); Flux saveAll(Publisher entityStream); Mono findById(ID id); Mono findById(Mono id); Mono existsById(ID id); Mono existsById(Mono id); Flux findAll(); Flux findAllById(Iterable ids); Flux findAllById(Publisher idStream); Mono count(); Mono deleteById(ID id); Mono delete(T entity); Mono deleteAll(Iterable extends T> entities); Mono deleteAll(Publisher extends T> entityStream); Mono deleteAll(); }

Slide 132

Slide 132 text

interface ReactiveCrudRepository extends Repository Mono save(S entity); Flux saveAll(Iterable entities); Flux saveAll(Publisher entityStream); Mono findById(ID id); Mono findById(Mono id); Mono existsById(ID id); Mono existsById(Mono id); Flux findAll(); Flux findAllById(Iterable ids); Flux findAllById(Publisher idStream); Mono count(); Mono deleteById(ID id); Mono delete(T entity); Mono deleteAll(Iterable extends T> entities); Mono deleteAll(Publisher extends T> entityStream); Mono deleteAll(); }

Slide 133

Slide 133 text

Code session

Slide 134

Slide 134 text

.publishOn() public static Mono mono( Mono input, Function<...> transformer ) { MonoProcessor monoProcessor = MonoProcessor.create(); input .publishOn(Schedulers.elastic()) .transform(transformer) .subscribe(monoProcessor); return monoProcessor .subscribeOn(Schedulers.elastic()); }

Slide 135

Slide 135 text

.publishOn() public static Mono mono( Mono input, Function<...> transformer ) { MonoProcessor monoProcessor = MonoProcessor.create(); input .publishOn(Schedulers.elastic()) .transform(transformer) .subscribe(monoProcessor); return monoProcessor .subscribeOn(Schedulers.elastic()); }

Slide 136

Slide 136 text

.publishOn() public static Mono mono( Mono input, Function<...> transformer ) { MonoProcessor monoProcessor = MonoProcessor.create(); input .publishOn(Schedulers.elastic()) .transform(transformer) .subscribe(monoProcessor); return monoProcessor .subscribeOn(Schedulers.elastic()); }

Slide 137

Slide 137 text

.publishOn() public static Mono mono( Mono input, Function<...> transformer ) { MonoProcessor monoProcessor = MonoProcessor.create(); input .publishOn(Schedulers.elastic()) .transform(transformer) .subscribe(monoProcessor); return monoProcessor .subscribeOn(Schedulers.elastic()); }

Slide 138

Slide 138 text

.publishOn() public static Mono mono( Mono input, Function<...> transformer ) { MonoProcessor monoProcessor = MonoProcessor.create(); input .publishOn(Schedulers.elastic()) .transform(transformer) .subscribe(monoProcessor); return monoProcessor .subscribeOn(Schedulers.elastic()); }

Slide 139

Slide 139 text

.publishOn() public static Mono mono( Mono input, Function<...> transformer ) { MonoProcessor monoProcessor = MonoProcessor.create(); input .publishOn(Schedulers.elastic()) .transform(transformer) .subscribe(monoProcessor); return monoProcessor .subscribeOn(Schedulers.elastic()); }

Slide 140

Slide 140 text

public static Mono mono( Mono input, Function<...> transformer ) { MonoProcessor monoProcessor = MonoProcessor.create(); input .publishOn(Schedulers.elastic()) .transform(transformer) .subscribe(monoProcessor); return monoProcessor .subscribeOn(Schedulers.elastic()); } .publishOn()

Slide 141

Slide 141 text

public static Mono mono( Mono input, Function<...> transformer ) { MonoProcessor monoProcessor = MonoProcessor.create(); input .publishOn(Schedulers.elastic()) .transform(transformer) .subscribe(monoProcessor); return monoProcessor .subscribeOn(Schedulers.elastic()); } .subscribeOn() MonoProcessor

Slide 142

Slide 142 text

public static Mono mono( Mono input, Function<...> transformer ) { MonoProcessor monoProcessor = MonoProcessor.create(); input .publishOn(Schedulers.elastic()) .transform(transformer) .subscribe(monoProcessor); return monoProcessor .subscribeOn(Schedulers.elastic()); } .subscribeOn() MonoProcessor

Slide 143

Slide 143 text

public static Mono mono( Mono input, Function<...> transformer ) { MonoProcessor monoProcessor = MonoProcessor.create(); input .publishOn(Schedulers.elastic()) .transform(transformer) .subscribe(monoProcessor); return monoProcessor .subscribeOn(Schedulers.elastic()); } MonoProcessor .subscribeOn() …subscribe();

Slide 144

Slide 144 text

public static Mono mono( Mono input, Function<...> transformer ) { MonoProcessor monoProcessor = MonoProcessor.create(); input .publishOn(Schedulers.elastic()) .transform(transformer) .subscribe(monoProcessor); return monoProcessor .subscribeOn(Schedulers.elastic()); } …subscribe(); MonoProcessor .subscribeOn() …subscribe();

Slide 145

Slide 145 text

Service Refactoring

Slide 146

Slide 146 text

Gitter Service

Slide 147

Slide 147 text

Reactive WebClient out of the box

Slide 148

Slide 148 text

public interface WebClient { UriSpec> get(); //omitted... static WebClient create() { return new DefaultWebClientBuilder().build(); } interface RequestHeadersSpec> { //omitted... Mono exchange(); //omitted... } interface ResponseSpec { Mono bodyToMono(Class bodyType); Flux bodyToFlux(Class elementType); Mono> toEntity(Class bodyType); Mono>> toEntityList(Class element } }

Slide 149

Slide 149 text

public interface WebClient { UriSpec> get(); //omitted... static WebClient create() { return new DefaultWebClientBuilder().build(); } interface RequestHeadersSpec> { //omitted... Mono exchange(); //omitted... } interface ResponseSpec { Mono bodyToMono(Class bodyType); Flux bodyToFlux(Class elementType); Mono> toEntity(Class bodyType); Mono>> toEntityList(Class element } }

Slide 150

Slide 150 text

No content

Slide 151

Slide 151 text

Code Session

Slide 152

Slide 152 text

@Autowired public GitterService( GitterClient gitterClient ) { gitterMessageSource = Flux.from( gitterClient .getMessages(null) ) .onBackpressureBuffer() .publish(1) .autoConnect(0); }

Slide 153

Slide 153 text

@Autowired public GitterService( GitterClient gitterClient ) { gitterMessageSource = Flux.from( gitterClient .getMessages(null) ) .onBackpressureBuffer() .publish(1) .autoConnect(0); } .onBP()

Slide 154

Slide 154 text

@Autowired public GitterService( GitterClient gitterClient ) { gitterMessageSource = Flux.from( gitterClient .getMessages(null) ) .onBackpressureBuffer() .publish(1) .autoConnect(0); } .onBP()

Slide 155

Slide 155 text

.onBP() @Autowired public GitterService( GitterClient gitterClient ) { gitterMessageSource = Flux.from( gitterClient .getMessages(null) ) .onBackpressureBuffer() .publish(1) .autoConnect(0); }

Slide 156

Slide 156 text

.onBP() @Autowired public GitterService( GitterClient gitterClient ) { gitterMessageSource = Flux.from( gitterClient .getMessages(null) ) .onBackpressureBuffer() .publish(1) .autoConnect(0); }

Slide 157

Slide 157 text

.onBP() @Autowired public GitterService( GitterClient gitterClient ) { gitterMessageSource = Flux.from( gitterClient .getMessages(null) ) .onBackpressureBuffer() .publish(1) .autoConnect(0); }

Slide 158

Slide 158 text

.onBP() @Autowired public GitterService( GitterClient gitterClient ) { gitterMessageSource = Flux.from( gitterClient .getMessages(null) ) .onBackpressureBuffer() .publish(1) .autoConnect(0); } …subscribe();

Slide 159

Slide 159 text

.onBP() @Autowired public GitterService( GitterClient gitterClient ) { gitterMessageSource = Flux.from( gitterClient .getMessages(null) ) .onBackpressureBuffer() .publish(1) .autoConnect(0); } …subscribe(); …subscribe();

Slide 160

Slide 160 text

Message Service

Slide 161

Slide 161 text

No content

Slide 162

Slide 162 text

Code Session

Slide 163

Slide 163 text

@Override public Flux latest() { return chatClient.stream() .transform(MessageMapper ::toViewModelUnits ); } @Override public Flux latest() { return chatClient.stream() .transform(MessageMapper ::toViewModelUnits ); } @Override public Flux latest() { return chatClient.stream() .transform(MessageMapper ::toViewModelUnits ); } .transform()

Slide 164

Slide 164 text

Statistics Service

Slide 165

Slide 165 text

No content

Slide 166

Slide 166 text

Code Session

Slide 167

Slide 167 text

@Autowired public DefaultMessageService( MessageRepository messageRepository, ChatService chatClient, MessageBroker messageBroker ) { this.chatClient = chatClient; Flux saved = messageRepository .saveAll(chatClient.stream() .transform(MessageMapper::toDomainUnits) ); messageBroker.createChannel( "statisticChanged", saved.materialize() ); }

Slide 168

Slide 168 text

@Autowired public DefaultMessageService( MessageRepository messageRepository, ChatService chatClient, MessageBroker messageBroker ) { this.chatClient = chatClient; Flux saved = messageRepository .saveAll(chatClient.stream() .transform(MessageMapper::toDomainUnits) ); messageBroker.createChannel( "statisticChanged", saved.materialize() ); } .transform()

Slide 169

Slide 169 text

@Autowired public DefaultMessageService( MessageRepository messageRepository, ChatService chatClient, MessageBroker messageBroker ) { this.chatClient = chatClient; Flux saved = messageRepository .saveAll(chatClient.stream() .transform(MessageMapper::toDomainUnits) ); messageBroker.createChannel( "statisticChanged", saved.materialize() ); } .transform()

Slide 170

Slide 170 text

@Autowired public DefaultMessageService( MessageRepository messageRepository, ChatService chatClient, MessageBroker messageBroker ) { this.chatClient = chatClient; Flux saved = messageRepository .saveAll(chatClient.stream() .transform(MessageMapper::toDomainUnits) ); messageBroker.createChannel( "statisticChanged", saved.materialize() ); } Channel .materialize()

Slide 171

Slide 171 text

@Autowired public DefaultMessageService( MessageRepository messageRepository, ChatService chatClient, MessageBroker messageBroker ) { this.chatClient = chatClient; Flux saved = messageRepository .saveAll(chatClient.stream() .transform(MessageMapper::toDomainUnits) ); messageBroker.createChannel( "statisticChanged", saved.materialize() ); } .transform()

Slide 172

Slide 172 text

@Autowired public DefaultMessageService( MessageRepository messageRepository, ChatService chatClient, MessageBroker messageBroker ) { this.chatClient = chatClient; Flux saved = messageRepository .saveAll(chatClient.stream() .transform(MessageMapper::toDomainUnits) ); messageBroker.createChannel( "statisticChanged", saved.materialize() ); } .transform()

Slide 173

Slide 173 text

@Autowired public DefaultMessageService( MessageRepository messageRepository, ChatService chatClient, MessageBroker messageBroker ) { this.chatClient = chatClient; Flux saved = messageRepository .saveAll(chatClient.stream() .transform(MessageMapper::toDomainUnits) ); messageBroker.createChannel( "statisticChanged", saved.materialize() ); } .transform()

Slide 174

Slide 174 text

@Autowired public DefaultMessageService( MessageRepository messageRepository, ChatService chatClient, MessageBroker messageBroker ) { this.chatClient = chatClient; Flux saved = messageRepository .saveAll(chatClient.stream() .transform(MessageMapper::toDomainUnits) ); messageBroker.createChannel( "statisticChanged", saved.materialize() ); } .transform()

Slide 175

Slide 175 text

@Autowired public DefaultMessageService( MessageRepository messageRepository, ChatService chatClient, MessageBroker messageBroker ) { this.chatClient = chatClient; Flux saved = messageRepository .saveAll(chatClient.stream() .transform(MessageMapper::toDomainUnits) ); messageBroker.createChannel( "statisticChanged", saved.materialize() ); } .materialize() .transform()

Slide 176

Slide 176 text

@Autowired public DefaultMessageService( MessageRepository messageRepository, ChatService chatClient, MessageBroker messageBroker ) { this.chatClient = chatClient; Flux saved = messageRepository .saveAll(chatClient.stream() .transform(MessageMapper::toDomainUnits) ); messageBroker.createChannel( "statisticChanged", saved.materialize() ); } .transform() .materialize()

Slide 177

Slide 177 text

@Autowired public DefaultMessageService( MessageRepository messageRepository, ChatService chatClient, MessageBroker messageBroker ) { this.chatClient = chatClient; Flux saved = messageRepository .saveAll(chatClient.stream() .transform(MessageMapper::toDomainUnits) ); messageBroker.createChannel( "statisticChanged", saved.materialize() ); } Channel .materialize()

Slide 178

Slide 178 text

Channel @Autowired public DefaultMessageService( MessageRepository messageRepository, ChatService chatClient, MessageBroker messageBroker ) { this.chatClient = chatClient; Flux saved = messageRepository .saveAll(chatClient.stream() .transform(MessageMapper::toDomainUnits) ); messageBroker.createChannel( "statisticChanged", saved.materialize() ); } .materialize()

Slide 179

Slide 179 text

@Autowired public DefaultMessageService( MessageRepository messageRepository, ChatService chatClient, MessageBroker messageBroker ) { this.chatClient = chatClient; Flux saved = messageRepository .saveAll(chatClient.stream() .transform(MessageMapper::toDomainUnits) ); messageBroker.createChannel( "statisticChanged", saved.materialize() ); } .materialize() Channel

Slide 180

Slide 180 text

Code Session

Slide 181

Slide 181 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .retry() Channel

Slide 182

Slide 182 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .retry() Channel

Slide 183

Slide 183 text

.retry() Channel this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1);

Slide 184

Slide 184 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .retry() Channel

Slide 185

Slide 185 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .retry() Channel

Slide 186

Slide 186 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .retry() Channel

Slide 187

Slide 187 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .retry() Channel

Slide 188

Slide 188 text

.retry() Channel this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1);

Slide 189

Slide 189 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .retry() Channel

Slide 190

Slide 190 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .retry() Channel

Slide 191

Slide 191 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .retry() Channel

Slide 192

Slide 192 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .retry() Channel .dematerialize()

Slide 193

Slide 193 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); Channel .retry() .dematerialize()

Slide 194

Slide 194 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .flatMap() .cache(1) .mergeWith .defer(statistic)

Slide 195

Slide 195 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .flatMap() .cache(1) .mergeWith .defer(statistic) …subscribe();

Slide 196

Slide 196 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .flatMap() .cache(1) .mergeWith .defer(statistic) …subscribe();

Slide 197

Slide 197 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .flatMap() .cache(1) …subscribe(); this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .mergeWith .defer(statistic)

Slide 198

Slide 198 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .flatMap() .cache(1) …subscribe();

Slide 199

Slide 199 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .flatMap() .cache(1) …subscribe();

Slide 200

Slide 200 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .flatMap() .cache(1) …subscribe();

Slide 201

Slide 201 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); …subscribe(); .flatMap() .cache(1)

Slide 202

Slide 202 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); Channel .retry() .dematerialize()

Slide 203

Slide 203 text

this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1); .retry() .dematerialize() .flatMap()

Slide 204

Slide 204 text

.retry() .dematerialize() .flatMap() this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1);

Slide 205

Slide 205 text

.dematerialize() .flatMap() .cache(1) this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1);

Slide 206

Slide 206 text

.dematerialize() .flatMap() .cache(1) this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1);

Slide 207

Slide 207 text

.flatMap() .cache(1) this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1);

Slide 208

Slide 208 text

.flatMap() .cache(1) this.statisticPublisher = messageBroker .channel("statisticChanged") .retry(err -> err instanceof USE) .dematerialize() .flatMap(s -> doGetUserStatistic()) .mergeWith(Mono .defer(this::doGetUserStatistic) ) .cache(1);

Slide 209

Slide 209 text

Code Session

Slide 210

Slide 210 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .map(…) .defaultIfEmpty(…) .zip(…)

Slide 211

Slide 211 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .map(…) .defaultIfEmpty(…) .zip(…)

Slide 212

Slide 212 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .map(…) .defaultIfEmpty(…) .zip(…)

Slide 213

Slide 213 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .map(…) .defaultIfEmpty(…) .zip(…)

Slide 214

Slide 214 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .map(…) .defaultIfEmpty(…) .zip(…)

Slide 215

Slide 215 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .map(…) .defaultIfEmpty(…) .zip(…)

Slide 216

Slide 216 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .defaultIfEmpty(…) .zip(…) .fromDirect(…)

Slide 217

Slide 217 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .defaultIfEmpty(…) .zip(…) .fromDirect(…)

Slide 218

Slide 218 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .map(…) .defaultIfEmpty(…) .zip(…) null

Slide 219

Slide 219 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .map(…) .defaultIfEmpty(…) .zip(…) null

Slide 220

Slide 220 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .map(…) .defaultIfEmpty(…) .zip(…) null

Slide 221

Slide 221 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .map(…) .defaultIfEmpty(…) .zip(…) null null

Slide 222

Slide 222 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .map(…) .defaultIfEmpty(…) .zip(…) null

Slide 223

Slide 223 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .map(…) .defaultIfEmpty(…) .zip(…) null

Slide 224

Slide 224 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .map(…) .defaultIfEmpty(…) .zip(…) null

Slide 225

Slide 225 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .map(…) .defaultIfEmpty(…) .zip(…)

Slide 226

Slide 226 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .defaultIfEmpty(…) .zip(…) .fromDirect(…)

Slide 227

Slide 227 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .defaultIfEmpty(…) .zip(…) .fromDirect(…)

Slide 228

Slide 228 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .defaultIfEmpty(…) .zip(…) .fromDirect(…)

Slide 229

Slide 229 text

private Mono doGetUserStatistic Flux topActiveUser = userRepository .findAllOrderedByActivityDesc(PageRequest.o .map(UserMapper::toViewModelUnits); Flux topMentionedUser = userRepository .findAllOrderedByMentionDesc(PageRequest.of .map(UserMapper::toViewModelUnits); return Mono.fromDirect( Flux.zip( topActiveUser.defaultIfEmpty(EMPTY_USER), topMentionedUser.defaultIfEmpty(EMPTY_USER) UsersStatisticVM::new ) ); } .defaultIfEmpty(…) .zip(…) .fromDirect(…)

Slide 230

Slide 230 text

Endpoints Refactoring

Slide 231

Slide 231 text

No content

Slide 232

Slide 232 text

Reactive WS out of the box

Slide 233

Slide 233 text

public interface WebSocketSession { String getId(); HandshakeInfo getHandshakeInfo(); DataBufferFactory bufferFactory(); Flux receive(); Mono send(Publisher messages); default Mono close() { return close(CloseStatus.NORMAL); } Mono close(CloseStatus status); WebSocketMessage textMessage(String payload); WebSocketMessage binaryMessage( Function payloadFactory); WebSocketMessage pingMessage( Function payloadFactory); WebSocketMessage pongMessage( Function payloadFactory); }

Slide 234

Slide 234 text

public interface WebSocketSession { String getId(); HandshakeInfo getHandshakeInfo(); DataBufferFactory bufferFactory(); Flux receive(); Mono send(Publisher messages); default Mono close() { return close(CloseStatus.NORMAL); } Mono close(CloseStatus status); WebSocketMessage textMessage(String payload); WebSocketMessage binaryMessage( Function payloadFactory); WebSocketMessage pingMessage( Function payloadFactory); WebSocketMessage pongMessage( Function payloadFactory); }

Slide 235

Slide 235 text

public interface WebSocketSession { String getId(); HandshakeInfo getHandshakeInfo(); DataBufferFactory bufferFactory(); Flux receive(); Mono send(Publisher messages); default Mono close() { return close(CloseStatus.NORMAL); } Mono close(CloseStatus status); WebSocketMessage textMessage(String payload); WebSocketMessage binaryMessage( Function payloadFactory); WebSocketMessage pingMessage( Function payloadFactory); WebSocketMessage pongMessage( Function payloadFactory); }

Slide 236

Slide 236 text

Code session

Slide 237

Slide 237 text

@Override public Publisher> handle( Publisher in ) { return Flux.merge( messageService.latest(), statisticService .usersStatisticStream() ); } network .merge()

Slide 238

Slide 238 text

@Override public Publisher> handle( Publisher in ) { return Flux.merge( messageService.latest(), statisticService .usersStatisticStream() ); } network .merge()

Slide 239

Slide 239 text

@Override public Publisher> handle( Publisher in ) { return Flux.merge( messageService.latest(), statisticService .usersStatisticStream() ); } network .merge()

Slide 240

Slide 240 text

@Override public Publisher> handle( Publisher in ) { return Flux.merge( messageService.latest(), statisticService .usersStatisticStream() ); } network .merge()

Slide 241

Slide 241 text

.merge() @Override public Publisher> handle( Publisher in ) { return Flux.merge( messageService.latest(), statisticService .usersStatisticStream() ); } network

Slide 242

Slide 242 text

network .merge() @Override public Publisher> handle( Publisher in ) { return Flux.merge( messageService.latest(), statisticService .usersStatisticStream() ); }

Slide 243

Slide 243 text

network .merge() @Override public Publisher> handle( Publisher in ) { return Flux.merge( messageService.latest(), statisticService .usersStatisticStream() ); }

Slide 244

Slide 244 text

@Override public Publisher> handle( Publisher in ) { return Flux.merge( messageService.latest(), statisticService .usersStatisticStream() ); } network .merge()

Slide 245

Slide 245 text

Pipeline Testing

Slide 246

Slide 246 text

StepVerifier

Slide 247

Slide 247 text

StepVerifier .create(myPublisher) .expectNext(“x”, “y”) .expectComplete() .verify();

Slide 248

Slide 248 text

StepVerifier .create(myPublisher) .expectNext(“x”, “y”) .expectComplete() .verify();

Slide 249

Slide 249 text

StepVerifier .create(myPublisher) .expectNext(“x”, “y”) .expectComplete() .verify();

Slide 250

Slide 250 text

StepVerifier .create(myPublisher) .expectNext(“x”, “y”) .expectComplete() .verify();

Slide 251

Slide 251 text

StepVerifier .create(myPublisher) .expectNext(“x”, “y”) .expectComplete() .verify();

Slide 252

Slide 252 text

Code session

Slide 253

Slide 253 text

Demo

Slide 254

Slide 254 text

No content

Slide 255

Slide 255 text

Checkpoints • Message Driven • Resilient • Responsive • Elastic

Slide 256

Slide 256 text

SUMMARY

Slide 257

Slide 257 text

Q&A

Slide 258

Slide 258 text

Resources 1. Why Reactive? [http://www.oreilly.com/programming/ free/why-reactive.csp] 2. Operator Fusion Part 1 [http://akarnokd.blogspot.com/ 2016/03/operator-fusion-part-1.html] 3. Reactive Streams Specification [http://www.reactive- streams.org/] 4. Learn Project Reactor [http://projectreactor.io/learn]

Slide 259

Slide 259 text

Thank you!