Slide 1

Slide 1 text

Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Going with . Christoph Strobl
 Pivotal Software Inc.
 @stroblchristoph

Slide 2

Slide 2 text

Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ In a nutshell, reactive programming is about
 non-blocking, event-driven applications
 that scale with a small number of threads
 with back pressure as a key ingredient
 that aims to ensure producers to not overwhelm consumers. (Rossen Stoyanchev)

Slide 3

Slide 3 text

The next 60 Minutes 3 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ - A bit of recent history. - Project Reactor / Spring Data Kay / Spring Framework 5. - Some Code.

Slide 4

Slide 4 text

A bit of recent history. Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Sept 28 5.0 GA Dec 2017 Oct 2017 Kay GA 2.0 GA Sept 25 3.1 GA Sept 29 5.0 M1 Jul 2016 Kay M1 Sept 2016 Nov 2016 3.0 GA Sept 2015 Sept 21 9

Slide 5

Slide 5 text

Imperative Applications 5 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ {…}

Slide 6

Slide 6 text

Imperative Applications - Batching 6 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ {…} Batching

Slide 7

Slide 7 text

Imperative Applications - Async 7 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ {…} Dispatcher Thread: Worker A Thread: Worker B Thread: Worker C

Slide 8

Slide 8 text

Reactive Applications 8 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ {…} Subscriber Publisher Stream

Slide 9

Slide 9 text

Reactive Applications 9 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ {…} Subscriber Publisher Stream .block()

Slide 10

Slide 10 text

NoSQL for the win! 10 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

Slide 11

Slide 11 text

11 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Iterator.next() Future.get() Subscriber.onNext(t) Remember vs

Slide 12

Slide 12 text

Reactor 3.1 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

Slide 13

Slide 13 text

Reactive Streams 13 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Provider of a potentially unbounded number of sequenced elements. Publisher Subscriber A processing stage - actually both a Subscriber and a Publisher. Processor One-to-one lifecycle of a Subscriber subscribing to a Publisher. Subscription

Slide 14

Slide 14 text

14 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Publisher Subscriber Processor Subscription .subscribe(Subscriber) .onSubscribe(Subscription) .request(long) .onNext(T) Reactive Streams

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

Project Reactor 16 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Publisher (0…n) Flux (0…n) Mono (0…1) Reactive Streams

Slide 17

Slide 17 text

Project Reactor 17 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Publisher (0…n) Flux (0…n) Mono (0…1) Reactive Streams Mono findByEmail(String email); Flux findByName(String name); #jürgenized

Slide 18

Slide 18 text

Flux 18 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ [fluhks] - a flowing or flow Flux.just("red", "white", "blue") .flatMap(v !-> Mono.fromCallable(blockingStuff(v)) .subscribeOn(Schedulers.elastic())) .collect(Result!::new, Result!::add) .doOnNext(Result!::stop) .subscribe(doWithResult);

Slide 19

Slide 19 text

Mono 19 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ [mon-oh] - alone, single, one Mono.fromCallable(blockingStuff()) .map(v !-> unwarp(v)) .subscribe();

Slide 20

Slide 20 text

Reactive Applications with Spring Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring Framework
 5 Project Reactor
 3.1 Spring Data
 Kay

Slide 21

Slide 21 text

Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Apply familiar concepts
 to an new way of expressing functionality.
 With minimal fluff and surprise!

Slide 22

Slide 22 text

Reactive Template (MongoDB) 22 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ /**
 * Query for a {@link Flux} of objects of type T from the specified collection.
 *
 * @param entityClass the parametrized type of the returned {@link Flux}.
 * @param collectionName name of the collection to retrieve the objects from
 * @return the converted collection
 */
 Flux findAll(Class entityClass, String collectionName); /**
 * Map the results of an ad-hoc query on the collection for the entity class to a 
 * single instance of an object of the
 * specified type. 
 * @param query the query class that specifies the criteria 
 * @param entityClass the parametrized type of the returned {@link Mono}.
 * @return the converted object
 */
 Mono findOne(Query query, Class entityClass);

Slide 23

Slide 23 text

Reactive Repository 23 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Mono save(S entity); Mono save(Mono entity); Flux saveAll(Iterable entities); Flux saveAll(Publisher entities); Mono existsById(Mono id); Flux findAll(); Mono count(); Mono deleteById(ID id);

Slide 24

Slide 24 text

Spring Data Reactive 24 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ interface Repo extends ReactiveCrudRepository { } Flux findAllByLastname(String lastname); Flux findAllByLastname(Mono lastname); Flux customQuery(String lastname); @Query("{lastname : ?0}"); Flux findAllByLastname(String ln, Pageable page);

Slide 25

Slide 25 text

Spring WebFlux 25 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ @RestController
 static class PersonController {
 
 PersonRepository repository;
 
 
 
 
 
 
 } @GetMapping("/")
 Flux fluxPersons(String name) {
 return repository.findAllByName(name);
 }


Slide 26

Slide 26 text

Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ It’s Demo Time https://github.com/christophstrobl/going-reactive-with-spring-data

Slide 27

Slide 27 text

Spring Data - Reactive Repository 27 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ interface PersonRepository extends ReactiveCrudRepository { } Flux.interval(Duration.ofSeconds(1))
 .zipWith(starks)
 .map(Tuple2!::getT2)
 .flatMap(repository!::save)
 .subscribe(); String[] names = { "Eddard", "Catelyn", "Jon", "Rob", "Sansa", "Aria", "Bran", "Rickon" };
 Flux starks = Flux
 .fromStream(Stream.generate(() !-> 
 names[ramdom.nextInt(names.length)])
 .map(Person!::new));

Slide 28

Slide 28 text

Spring Data - Reactive Repository 28 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ interface PersonRepository extends ReactiveCrudRepository { } Flux.interval(Duration.ofSeconds(1))
 .zipWith(starks)
 .map(Tuple2!::getT2)
 .flatMap(repository!::save)
 .subscribe(); String[] names = { "Eddard", "Catelyn", "Jon", "Rob", "Sansa", "Aria", "Bran", "Rickon" };
 Flux starks = Flux
 .fromStream(Stream.generate(() !-> 
 names[ramdom.nextInt(names.length-1)])
 .map(Person!::new)); > cstrobl $ ./bin/mongo --port 52291 > use test switched to db test { "_id" : ObjectId("591009c5ed68a820fb9956a5"), "name" : "Sansa", "_class" : "com.example.DemoApplication$Person" } { "_id" : ObjectId("591009c6ed68a820fb9956a6"), "name" : "Rob", "_class" : "com.example.DemoApplication$Person" } { "_id" : ObjectId("591009c7ed68a820fb9956a7"), "name" : "Sansa", "_class" : "com.example.DemoApplication$Person" } { "_id" : ObjectId("591009c8ed68a820fb9956a8"), "name" : "Rob", "_class" : "com.example.DemoApplication$Person" } { "_id" : ObjectId("591009c9ed68a820fb9956a9"), "name" : "Jon", "_class" : "com.example.DemoApplication$Person" } { "_id" : ObjectId("591009caed68a820fb9956aa"), "name" : "Aria", "_class" : "com.example.DemoApplication$Person" } { "_id" : ObjectId("591009cbed68a820fb9956ab"), "name" : "Rob", "_class" : "com.example.DemoApplication$Person" } { "_id" : ObjectId("591009cced68a820fb9956ac"), "name" : "Jon", "_class" : "com.example.DemoApplication$Person" } { "_id" : ObjectId("591009cded68a820fb9956ad"), "name" : "Sansa", "_class" : "com.example.DemoApplication$Person" } > db.person.find();

Slide 29

Slide 29 text

Spring - WebFlux 29 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ interface PersonRepository extends ReactiveCrudRepository { Flux findAllByName(String name); } @RestController
 static class PersonController {
 
 PersonRepository repository;
 
 
 
 
 
 
 } @GetMapping("/")
 Flux fluxPersons(String name) {
 return repository.findAllByName(name);
 }


Slide 30

Slide 30 text

Spring - WebFlux 30 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ interface PersonRepository extends ReactiveCrudRepository { Flux findAllByName(String name); } @RestController
 static class PersonController {
 
 PersonRepository repository;
 
 
 
 
 
 
 } @GetMapping("/")
 Flux fluxPersons(String name) {
 return repository.findAllByName(name);
 }
 > cstrobl $ curl localhost:8080/?name=Eddard | jq [ { "name": "Eddard", "id": "591014f2756bac231a23f3a0" }, { "name": "Eddard", "id": "591014f7756bac231a23f3a5" } ] >

Slide 31

Slide 31 text

RxJava types 31 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ interface PersonRepository extends ReactiveCrudRepository { Observable findByName(String name); } @RestController
 static class PersonController {
 
 PersonRepository repository;
 
 @GetMapping("/rx")
 Observable rxPersons(String name) {
 return repository.findByName(name);
 }
 }

Slide 32

Slide 32 text

RxJava types 32 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ interface PersonRepository extends ReactiveCrudRepository { Observable findByName(String name); } @RestController
 static class PersonController {
 
 PersonRepository repository;
 
 @GetMapping("/rx")
 Observable rxPersons(String name) {
 return repository.findByName(name);
 }
 } > cstrobl $ curl localhost:8080/rx?name=Rob | jq [ { "name": "Rob", "id": "590f6e99756bac18a8d62bfe" }, { "name": "Rob", "id": "590f6e9d756bac18a8d62c02" } { "name": "Rob", "id": "590f6e9e756bac18a8d62c03" } ] >

Slide 33

Slide 33 text

Tailable Cursors & Event Stream 33 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ interface PersonRepository extends ReactiveCrudRepository { @Tailable Flux findBy(); } @RestController
 static class PersonController {
 
 PersonRepository repository;
 
 @GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) Flux streamPersons() {
 return repository.findBy();
 }
 }

Slide 34

Slide 34 text

Tailable Cursors & Event Stream 34 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ interface PersonRepository extends ReactiveCrudRepository { @Tailable Flux findBy(); } @RestController
 static class PersonController {
 
 PersonRepository repository;
 
 @GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) Flux streamPersons() {
 return repository.findBy();
 }
 } > cstrobl $ curl localhost:8080/stream data:{"name":"Sansa","id":"5910192e756bac26079dd623"} data:{"name":"Jon","id":"5910192f756bac26079dd624"} data:{"name":"Catelyn","id":"59101930756bac26079dd625"} data:{"name":"Eddard","id":"59101931756bac26079dd626"} data:{"name":"Jon","id":"59101932756bac26079dd627"} data:{"name":"Eddard","id":"59101933756bac26079dd628"}

Slide 35

Slide 35 text

WebFlux - Router Functions 35 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ @Component
 static class PersonHandler { PersonRepository repository; Mono streamPersons(ServerRequest request) { return ServerResponse.ok()
 .contentType(MediaType.TEXT_EVENT_STREAM)
 .body(personRepository.findBy(), Person.class); } @Bean
 RouterFunction routes(PersonHandler requestHandler) { 
 return RouterFunctions
 .route(RequestPredicates.GET("/stream"), requestHandler!::streamPersons) }

Slide 36

Slide 36 text

Spring - WebClient 36 Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ @Bean
 WebClient client() {
 return WebClient.create("http:!//localhost:8080/");
 }
 
 @Bean
 CommandLineRunner run(WebClient client) {
 
 return (args) !-> {
 
 client.get()
 .uri("/stream")
 .retrieve()
 .bodyToFlux(Person.class)
 .subscribe(System.out!::println);
 };
 }

Slide 37

Slide 37 text

Unless otherwise indicated, these slides are © 2013-2017 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Reactive is about efficient resource usage. Even if backed with familiar concepts and framework support, 
 it is no free lunch. The price is complexity.