SlideShare a Scribd company logo
Reactive Programming in Java and Spring 5
Richard Langlois P. Eng., Solutions Architect
January 24th, 2018
>
• Introduction to Reactive Programming
• Reactive Manifesto
• Reactive Streams Specification
• Reactor
• Reactive Programming with Spring 5
• Reactive Spring Data
Agenda
>
• Is a programming paradigm.
• Is about:
• Non-blocking applications which are
• asynchronous
• even-driven
• require a small amount of threads to scale vertically (within the JVM).
Introduction to Reactive Programming
>
From Merriam Webster: “Readily responsive to a stimulus”
• React to events (event-driven)
• React to load (scalable)
• React to failures (resilient)
• React to users (responsive)
Key to understand reactive programming is to think about it as operating on a stream of data.
Steam of data meaning a sequence of events, where an event could be
• user input (like a tap on a button),
• a response from an API request (like a Facebook feed),
• data contained in a database,
• a single variable.
Reactive
>
Reactive Manifesto is a prescription for building modern, cloud scale architecture, which is well prepared to meet the increasing
demands that applications face today.
Homepage: http://reactivemanifesto.org/
Reactive Manifesto
>
The Four Reactive Traits:
• Responsive: Application provides rich, real-time interaction with its users even under load and in the presence of failures.
• Resilient: Application recover quickly from failure (e.g. software, hardware, connections).
• Scalable: Application is able to be expanded according to its usage
• scale up: make use of more powerful hardware (aka vertical scaling)
• scale out: make use of multiple server nodes (aka horizontal scaling)
• Event-Driven: Application is composed of loosely coupled event handlers. Events can be handled asynchronously, without
blocking.
Reactive Manifesto
Characteristics
>
Reactive Streams is a Standard and specification for Stream‐oriented libraries for the JVM that
• process a potentially unbounded number of elements in sequence
• asynchronously passing elements between components
• with mandatory non‐blocking backpressure.
Specification consists of the following parts:
• The API specifies the types to implement Reactive Streams and achieve interoperability between different implementations.
• The Technology Compatibility Kit (TCK): a standard test suite for conformance testing of implementations.
Reactive Streams are only concerned with mediating the stream of data between different API Components (so operators
are not specified).
Reactive Streams specification
>
Allows to control the amount of inflight data
Regulate the transfer between:
• Slow publisher and fast consumer
• Fast publisher and slow consumer
Back Pressure (a.k.a. Flow Control)
>
Reactive Streams Specification
API
>
Those interfaces are included in Java 9 (under java.util.concurrent):
• Flow.Publisher
• Flow.Subscriber
• Flow.Subscription
• Flow.Processor
Reactive Streams Specification
Java 9
>
API Explanation:
• Communication between publisher and subscriber is set up via the publisher’s subscribe(), through which the two parties
are introduced to each other.
• After successful initialization of the communication, the subscriber gets to know about a Subscription (which models the
established connection) via a call to its onSubscribe method.
• At the core of the Reactive Streams mechanism is the request method of the Subscription. Through the request() method,
the subscriber signals to the publisher how many elements it’s ready to process.
• The publisher communicates every element one by one to the subscriber via its onNext() method, as well as fatal stream
failures through the onError() method.
• Because the publisher knows exactly how many items it’s expected to publish at any time (it has been asked for a number of
elements in the Subscription’s request method), it’s able to produce as many elements as required without producing too
many for the subscriber to consume, eliminating the need to block while waiting for the subscriber.
• Additionally, the subscriber is called by the publisher for each published element through the onNext() method, meaning
that it does not explicitly need to block while waiting for new elements to be available.
Reactive Streams Specification
>
Some Reactive Libraries on the JVM:
• RxJava: Reactive Extensions implemented on the JVM.
• Akka Streams
• Reactor Core:
Reactive Stream Specification
>
Is a fourth-generation Reactive library for building non-blocking applications on the
JVM based on the Reactive Streams Specification.
• Targets Java 8.
• Extends a Reactive Streams Publisher with the Flux and Mono API types.
It adds the concept of operators, which are chained together to describe what processing to apply at
each stage to the data.
Applying an operator returns a new intermediate Publisher.
Reactor
Core 3
>
Reactor
Evolution
>
Flux:
• A Flux<T> is a standard Publisher<T> representing an asynchronous sequence of 0 to N emitted
items, optionally terminated by either a completion signal or an error.
• Possible values of a flux: a value, a completion signal, an error.
• Translates to calls to a downstream object’s onNext, onComplete, onError methods.
• Marble diagram:
Reactor
Core Features
>
Mono:
• A Mono is a standard Publisher<T> that emits at most one item and then optionally terminates with
an onComplete signal or an onError signal.
• It offers only a subset of the operators that are available for a Flux.
• Can represent no-value asynchronous processes which have the concept of completion
(Mono<void>).
Reactor
Core Features
>
Numerous factory methods:
• Flux<String> seq1 = Flux.just("foo", "bar", "foobar");
• private static List<String> iterable = Arrays.asList ("foo", "bar", "foobar");
Flux<String> fluxFromIterable = Flux.fromIterable(iterable);
• Mono<String> noData = Mono.empty();
• Mono<String> data = Mono.just("foo");
• Flux<Integer> numbersFromFiveToSeven = Flux.range(5, 3); // 1st parameter is start of the range, 2nd is number of items
Reactor
Flux or Mono Creation
>
.subscribe variants take lambdas for different combination of callbacks:
1. subscribe(); // subscribe and trigger the sequence
2. subscribe(Consumer<? super T> consumer); // consumer run when values
3. subscribe(Consumer<? super T> consumer, // deal with values
Consumer<? super Throwable> errorConsumer); // consumer run when error
4. subscribe(Consumer<? super T> consumer, // deal with values
Consumer<? super Throwable> errorConsumer, // Consumer run when error
Runnable completeConsumer); // consumer run when sequence successfully complete
5. subscribe(Consumer<? super T> consumer, // deal with values
Consumer<? super Throwable> errorConsumer, // consumer run when error
Runnable completeConsumer, // consumer run when the sequence successfully complete
Consumer<? super Subscription> subscriptionConsumer); // consumer run when subscription produced
Reactor - Subscribe
>
Example:
// Use the subscribe() method to collect all the elements in a stream
Flux<Integer> elementsFlux = Flux.just(1, 2, 3, 4);
// subscribe with a subscriber that will print the values, The data will not start flowing until we subscribe
elementsFlux().subscribe(System.out::println(i));
Logs:
[main] INFO reactor.Flux.Array.1 - | onSubscribe([Synchronous Fuseable] FluxArray.ArraySubscription)
20:25:19.553 [main] INFO reactor.Flux.Array.1 - | request(unbounded)
20:25:19.553 [main] INFO reactor.Flux.Array.1 - | onNext(1)
20:25:19.553 [main] INFO reactor.Flux.Array.1 - | onNext(2)
20:25:19.553 [main] INFO reactor.Flux.Array.1 - | onNext(3)
20:25:19.553 [main] INFO reactor.Flux.Array.1 - | onNext(4)
20:25:19.553 [main] INFO reactor.Flux.Array.1 - | onComplete()
Reactor - Subscribe
>
Example: Tell upstream to only send 2 elements at a time by using request().
Flux.just(1, 2, 3, 4)
.log()
.subscribe(new Subscriber<Integer>() {
private Subscription s;
int onNextAmount;
@Override
public void onSubscribe(Subscription s) {
this.s = s;
s.request(2);
}
…
Reactor – Back Pressure
Example (1 of 3)
>
…
@Override
public void onNext(Integer integer) {
elements.add(integer);
onNextAmount++;
if (onNextAmount % 2 == 0) {
s.request(2);
}
}
@Override
public void onError(Throwable t) {}
@Override
public void onComplete() {}
});
Reactor – Back Pressure
Example (2 of 3)
>
Logs:
23:31:15.395 [main] INFO reactor.Flux.Array.1 - | onSubscribe([Synchronous Fuseable] FluxArray.ArraySubscription)
23:31:15.397 [main] INFO reactor.Flux.Array.1 - | request(2)
23:31:15.397 [main] INFO reactor.Flux.Array.1 - | onNext(1)
23:31:15.398 [main] INFO reactor.Flux.Array.1 - | onNext(2)
23:31:15.398 [main] INFO reactor.Flux.Array.1 - | request(2)
23:31:15.398 [main] INFO reactor.Flux.Array.1 - | onNext(3)
23:31:15.398 [main] INFO reactor.Flux.Array.1 - | onNext(4)
23:31:15.398 [main] INFO reactor.Flux.Array.1 - | request(2)
23:31:15.398 [main] INFO reactor.Flux.Array.1 - | onComplete()
Notice:
The request(2) is called (when Subscribing), followed by two onNext() calls, then request(2) again, then on Complete().
Reactor – Back Pressure
Example (3 of 3)
>
Reactive Operators applies a wide range of transformations to the sequence of data (e.g. Map, Flatmap, Filter, Concat, Merge,
buffer, split, transform, delay …)
Special diagrams called Marble Diagrams efficiently explains what an operator does, for example:
Reactor - Reactive Operators
>
Map: Transform every item of the emitted sequence with a specified function.
Reactor – Reactive Operators
Map()
>
Concat:
concatenates 2 or more emissions, generating one emission where all the items from the 1st source emission appear before the
items of the 2nd source emission.
Reactor - Reactive Operators
Concat()
>
flatMap():
performs 2 types of actions:
1. the “map” action that transforms the emitted item into Flux
2. The “flatten” action that converts those Flux into one Flux.
Reactor - Reactive Operators
flatMap
>
Merge:
When we want to get feeds from multiple sources as one stream.
Reactor - Reactive Operators
merge()
>
Zip:
takes multiple observables as inputs and combines each emission via a specified function
and emits the results of this function as a new sequence.
Reactor - Reactive Operators
zip()
>
StepVerifier API:
• Builder API allowing to test how a Flux or Mono behave when subscribed to.
Some methods:
• expectNext()
• expectError()
• expectErrorMessage()
• expectComplete()
• Verify(), VerifyComplete(), VerifyError(), VerifyErrorMessage()
Reactor - Testing
StepVerifier
>
Example:
// empty Flux
Flux<String> emptyFlux = Flux.empty();
StepVerifier.create(emptyFlux).verifyComplete();
// non-empty Flux
Flux<String> nonEmptyFlux = Flux.just("John", "Mike", "Sarah");
StepVerifier.create(nonEmptyFlux).expectNext("John", "Mike", "Sarah").verify();
Call to verify():
• triggers the verification by subscribing to the Flux/Mono under test.
• Plays the sequence, comparing each new signal with the next step in the scenario
• As long as these match, the test is considered a success, else, an AssertionError is thrown.
Reactor - Testing
StepVerifier
>
• New spring-webflux module to support reactive HTTP client-side and server-side.
• Uses Reactor internally for its own reactive support.
Spring Framework 5
Reactive Support
>
Spring 5
Reactive and Servlet Stack
>
Add Dependency to pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
Spring 5
WebFlux
>
• Supports 2 distinct programming models:
• Annotation-based with @Controller and the other annotations of Spring MVC
• Functional Style routing and handling with Java 8 lambda.
Spring 5
Server Side
>
Example:
@RestController
@RequestMapping(value="/api/customer")
public class RestControllerAPIs {
@GetMapping("/")
public Flux<Customer> getAll() {
...
}
@GetMapping("/{id}")
public Mono<Customer> getCustomer(@PathVariable Long id) {
...
}
}
Spring 5 - WebFlux
Server Side - Annotation-based - Example
>
Get all customers test case:
Map<Long, Customer> custStores = new HashMap<Long, Customer>();
…
@GetMapping
public Flux<Customer> getAll() {
return Flux.fromIterable(custStores.entrySet().stream()
.map(entry -> entry.getValue())
.collect(Collectors.toList()));
}
Spring 5 - WebFlux
Server Side - Annotation-based - Example
>
Get a customer test case:
@GetMapping("/{id}")
public Mono<Customer> getCustomer(@PathVariable Long id) {
return Mono.justOrEmpty(custStores.get(id));
}
Spring 5 - WebFlux
Server Side - Annotation-based - Example
>
Create a customer test case:
@PostMapping("/post")
public Mono<ResponseEntity<String>> postCustomer(@RequestBody Customer customer) {
// do post
custStores.put(customer.getCustId(), customer);
return Mono.just(new ResponseEntity<>("Post Successfully!", HttpStatus.CREATED));
}
Spring 5 - WebFlux
Server Side - Annotation-based - Example
>
Framework introduces 2 fundamental components:
• Routes a given HTTP requests via a RouterFunction (alternative to using annotations like @RequestMapping)
• Handles the request via HandlerFunction (alternative to @Controller’s handler methods).
RouterFunction utility classes are used to create RouterFunction:
e.g.
RouterFunction.route(RequestPredicate, HandlerFunction):
• helper function to create routes.
• Allows to route requests by applying a RequestPredicate.
• When the predicate is matched, then the second argument is run.
Spring 5 - WebFlux
Server Side - Functional Style
>
Example:
RouterFunction router = route( GET("/test"),
request -> ok().build() ) ;
• GET("/test") is the RequestPredicate.
• req -> ok().build() is the handler producing the response.
Spring 5
Server Side – Functional Style
>
WebClient
• Is a reactive client for performing HTTP requests with Reactive Streams back
pressure.
• Is replacing the classic RestTemplate.
• Is an interface which has a single implementation – DefaultWebClient class.
Usage(similar to HttpClient):
1. Create an instance
2. Make a request
3. Handle the reponse
Spring 5
Client side
>
Create WebClient using one of the 3 options :
• With default settings:
• WebClient client1 = WebClient.create();
• With a given base URI:
• WebClient client2 = WebClient.create("http://localhost:8080 (http://localhost:8080)");
• Using the DefaultWebClientBuilder class:
• WebClient client3 = WebClient
.builder()
.baseUrl("http://localhost:8080 (http://localhost:8080)")
.defaultCookie("cookieKey", "cookieValue")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.defaultUriVariables(Collections.singletonMap("url", "http://localhost:8080 (http://localhost:8080)"))
.build();
Spring 5
Client side - WebClient
>
// Setting a request body
//where a Publisher is a reactive component that is in charge of providing a potentially unbounded number of sequenced
elements.
WebClient.RequestHeadersSpec requestSpec1
= WebClient.create()
.method(HttpMethod.POST)
.uri("/resource")
.body(BodyInserters.fromPublisher(Mono.just("data")), String.class);
WebClient.RequestHeadersSpec<?> requestSpec2
= WebClient.create("http://localhost:8080 (http://localhost:8080)")
.post()
.uri(URI.create("/resource"))
.body(BodyInserters.fromObject("data"));
Spring 5
Client side - WebClient
>
A Response is obtained with exchange() or retrieve():
• exchange(): provides a ClientResponse along with its status, headers
• retrieve(): fetches a body directly
Example:
String response2 = request1.exchange()
.block()
.bodyToMono(String.class)
.block();
String response3 = request2.retrieve()
.bodyToMono(String.class)
.block();
Note: The block method on Monos is used to subscribe and retrieve an actual data which was sent with the response.
Spring 5
Client side - WebClient
>
WebTestClient
• is a non-blocking, reactive client for Spring-webflux integration testing support.
• Offers an identical API as the WebClient.
• can connect to any server over an HTTP connection.
• provides a fluent API to verify responses.
• can also bind directly to WebFlux applications with mock request and response objects.
Spring 5
Spring WebFlux Testing
>
Add Test dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
Spring 5
Spring WebFlux Testing
>
@WebFluxTest:
• auto-configures WebTestClient to quickly test WebFlux controllers without starting
a full HTTP server
Example of an unit test:
@RunWith(SpringRunner.class)
@WebFluxTest
public class SpringWebFluxTestApplicationTests {
@Autowired
private WebTestClient webTestClient;
…
}
Spring 5 - WebFlux
Testing
>
Test without starting an actual server:
WebTestClient client
= WebTestClient.bindToRouterFunction(routingFunction())
.build();
client.get().uri("/").exchange()
.expectStatus().isOk(); // Assert
Test with a real server:
WebTestClient client
= WebTestClient.bindToServer()
.baseUrl("http://localhost:8080 (http://localhost:8080)")
.build();
client.get().uri("/").exchange()
.expectStatus().isOk(); // Assert
Spring 5 - WebFlux
WebTestClient
>
Get test case:
Using WebTestClient API:
webTestClient.get().uri("/api/customer/{id}", 2).accept(MediaType.APPLICATION_JSON).exchange()
.expectStatus().isOk().expectBody(Customer.class).isEqualTo(customerMap.get("Peter")); // Assert
Using RouterFunction:
// The Router Function
RouterFunction myRouterFunction = route(GET("/test"), // RouterFunction
request -> ok().body(fromObject("hello world"))); // HandlerFunction
// Register the RouterFunction
WebTestClient webTestClient = WebTestClient.bindToRouterFunction(myRouterFunction).build();
// Assert the response
webTestClient.get().uri("/test").exchange().expectStatus().isOk();
Spring 5
WebTestClient - Example
>
POST test case:
webTestClient
// Create a POST request
.post()
.uri("/api/customer/post")
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromObject(customerMap.get("Mary")))
.exchange()
// Assert the response
.expectStatus().isCreated()
.expectBody(String.class)
.isEqualTo("Post Successfully!");
Spring 5
WebTestClient - Example
>
PUT test case:
webTestClient
// Create a PUT request
.put().uri("/api/customer/put/{id}", 3)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromObject(customerMap.get("Amy")))
.exchange()
// Assert the response
.expectStatus().isCreated()
.expectBody(Customer.class)
isEqualTo(customerMap.get("Amy"));
Spring 5
WebTestClient - Example
>
DELETE test case:
webTestClient
// Create a DELETE request
.delete().uri("/api/customer/delete/{id}", 1)
.exchange()
// Assert the response
.expectStatus().isAccepted()
.expectBody(String.class)
.isEqualTo("Delete Succesfully!");
Spring 5
WebTestClient - Example
>
Spring WebFlux is supported on the following servers:
• Netty
• Undertow
• Tomcat
• Jetty
• Servlet 3.1+ containers
Spring Boot 2 uses Netty by default with WebFlux
Spring 5
Choosing a server
>
• Asynchronous
• Non Blocking
• Event Driven
• Data as stream
Reactive Data Access
>
Spring Data support Reactive Streams
Reactive Spring Data Modules:
• MongoDb
• Redis
• Cassandra
• CouchDB
Reactive Spring Data
>
Lets see an example based on Spring Data and MongoDB
Spring Data - MongoDB
>
Getting up a running Reactive Streams with Spring Data and MongoDB:
• Add the dependency (in pom.xml)
• Configuration (@EnableReactiveMongoRepositories)
• Repository interface (extends ReactiveMongoRepository, and use Flux and Mono
types)
Spring Data - MongoDB
>
Add Reactive MongoDB to our pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-libs-snapshot</id>
<name>Spring Snapshot Repository</name>
<url>http://repo.spring.io/libs-snapshot</url>
</repository>
</repositories>
Spring Data - MongoDB
Example
>
@Configuration
@EnableReactiveMongoRepositories(basePackageClasses = PersonRepository.class)
public class MongoConfig extends AbstractReactiveMongoConfiguration {
@Bean
public MongoClient mongoClient() {
return MongoClients.create();
}
@Override
protected String getDatabaseName() {
return "test";
}
@Bean
public ReactiveMongoTemplate reactiveMongoTemplate() {
return new ReactiveMongoTemplate(mongoClient(), getDatabaseName());
}
}
Spring Data – MongoDB
Example - Configuration
>
Configuration:
@EnableMongoRepositories enable the use of ReactiveCrudRepository.
For example:
• Mono<S> = save(S entity)
• Mono<T> = findById(ID id)
• Mono<T> = findById(Publisher<ID> id)
• Uses the first emitted element to perform the find-query
• Mono<void> = deleteById(ID id)
• Mono signaling when operation is completed
Spring Data – MongoDB
Example
>
Repository:
@EnableMongoRepositories enable the use of ReactiveCrudRepository.
public interface PersonRepository extends ReactiveMongoRepository<Person, String> {
Flux<Person> findByFirstName(final String firstName);
Mono<Person> findOneByFirstName(final String firstName);
Mono<void> = deleteById(ID id); //Mono signaling when operation is completed
}
Notice:
• Flux<Person> replaces the use of List
• Mono<Person> is used instead of Person.
This allows to perform functions on each element as they come from MongoDB database, instead of waiting until
all records are returned, and then do something with them.
Spring Data – MongoD
Example
>
Application:
@SpringBootApplication
public class Application implements CommandLineRunner {
…
@Override
public void run(String args[]) {
final Person johnAoe = new Person("john", "aoe", LocalDateTime.now(), "loser", 0);
final Person johnBoe = new Person("john", "boe", LocalDateTime.now(), "a bit of a lose
personRepository.saveAll(Flux.just(johnAoe, johnBoe)).subscribe();
personRepository.findByFirstName("john").log().map(Person::getSecondName)
.subscribe(System.out::println);
personRepository.findOneByFirstName("john").log().map(Person::getId)
.subscribe(System.out::println);
}
}
Spring Data – MongoD
Example
>
Associated Logs:
2017-07-16 16:44:09.201 INFO 13476 --- [ main] reactor.Flux.OnErrorResume.1 : onSubscribe(FluxOnErrorResume.ResumeSubscriber)
2017-07-16 16:44:09.208 INFO 13476 --- [ main] reactor.Flux.OnErrorResume.1 : request(unbounded)
2017-07-16 16:44:09.242 INFO 13476 --- [ Thread-4] reactor.Flux.OnErrorResume.1 : onNext(Person(firstName=john, secondName=aoe, profession=loser, salary=0))
aoe
2017-07-16 16:44:09.243 INFO 13476 --- [ Thread-4] reactor.Flux.OnErrorResume.1 : onNext(Person(firstName=john, secondName=boe, profession=a bit of a loser,
salary=10))
boe
2017-07-16 16:44:09.247 INFO 13476 --- [ Thread-4] reactor.Flux.OnErrorResume.1 : onComplete()
2017-07-16 16:44:09.254 INFO 13476 --- [ main] reactor.Mono.OnErrorResume.2 : onSubscribe(FluxOnErrorResume.ResumeSubscriber)
2017-07-16 16:44:09.255 INFO 13476 --- [ main] reactor.Mono.OnErrorResume.2 : request(unbounded)
2017-07-16 16:44:09.260 INFO 13476 --- [ Thread-4] reactor.Mono.OnErrorResume.2 : onNext(Person(firstName=john, secondName=aoe, profession=loser, salary=0))
596b89c97ab38934a404a80c
2017-07-16 16:44:09.260 INFO 13476 --- [ Thread-4] reactor.Mono.OnErrorResume.2 : onComplete()
Spring Data – MongoD
Example
>
• The Reactive Manifesto:
• https://www.reactivemanifesto.org/
• Reactor:
• https://projectreactor.io/
• Spring WebFlux:
• https://docs.spring.io/spring/docs/5.0.0.BUILD-SNAPSHOT/spring-framework-reference/html/web-reactive.html
• Going reactive with Spring Data:
• https://spring.io/blog/2016/11/28/going-reactive-with-spring-data
• Servlet vs Reactive Stacks in Five Use Cases:
• https://www.infoq.com/presentations/servlet-reactive-stack
References
>
Thank You!

More Related Content

What's hot (20)

Introduction to Spring WebFlux #jsug #sf_a1
Introduction to Spring WebFlux #jsug #sf_a1
Toshiaki Maki
 
Reactive Microservices with Spring 5: WebFlux
Reactive Microservices with Spring 5: WebFlux
Trayan Iliev
 
Reactive Spring 5
Reactive Spring 5
Corneil du Plessis
 
Project Reactor Now and Tomorrow
Project Reactor Now and Tomorrow
VMware Tanzu
 
Microservices with Java, Spring Boot and Spring Cloud
Microservices with Java, Spring Boot and Spring Cloud
Eberhard Wolff
 
Getting Started with Spring Authorization Server
Getting Started with Spring Authorization Server
VMware Tanzu
 
Reactive Programming In Java Using: Project Reactor
Reactive Programming In Java Using: Project Reactor
Knoldus Inc.
 
Test Design and Automation for REST API
Test Design and Automation for REST API
Ivan Katunou
 
Graphql presentation
Graphql presentation
Vibhor Grover
 
Designing APIs with OpenAPI Spec
Designing APIs with OpenAPI Spec
Adam Paxton
 
Spring Webflux
Spring Webflux
Carlos E. Salazar
 
Intro to Reactive Programming
Intro to Reactive Programming
Stéphane Maldini
 
How to go about testing in React?
How to go about testing in React?
Lisa Gagarina
 
Spring Framework - Data Access
Spring Framework - Data Access
Dzmitry Naskou
 
Introduction to RxJS
Introduction to RxJS
Brainhub
 
Design patterns for microservice architecture
Design patterns for microservice architecture
The Software House
 
Concurrent Programming in Java
Concurrent Programming in Java
Ruben Inoto Soto
 
Discover Quarkus and GraalVM
Discover Quarkus and GraalVM
Romain Schlick
 
Microservices architecture
Microservices architecture
Abdelghani Azri
 
Resilience4j with Spring Boot
Resilience4j with Spring Boot
Knoldus Inc.
 
Introduction to Spring WebFlux #jsug #sf_a1
Introduction to Spring WebFlux #jsug #sf_a1
Toshiaki Maki
 
Reactive Microservices with Spring 5: WebFlux
Reactive Microservices with Spring 5: WebFlux
Trayan Iliev
 
Project Reactor Now and Tomorrow
Project Reactor Now and Tomorrow
VMware Tanzu
 
Microservices with Java, Spring Boot and Spring Cloud
Microservices with Java, Spring Boot and Spring Cloud
Eberhard Wolff
 
Getting Started with Spring Authorization Server
Getting Started with Spring Authorization Server
VMware Tanzu
 
Reactive Programming In Java Using: Project Reactor
Reactive Programming In Java Using: Project Reactor
Knoldus Inc.
 
Test Design and Automation for REST API
Test Design and Automation for REST API
Ivan Katunou
 
Graphql presentation
Graphql presentation
Vibhor Grover
 
Designing APIs with OpenAPI Spec
Designing APIs with OpenAPI Spec
Adam Paxton
 
Intro to Reactive Programming
Intro to Reactive Programming
Stéphane Maldini
 
How to go about testing in React?
How to go about testing in React?
Lisa Gagarina
 
Spring Framework - Data Access
Spring Framework - Data Access
Dzmitry Naskou
 
Introduction to RxJS
Introduction to RxJS
Brainhub
 
Design patterns for microservice architecture
Design patterns for microservice architecture
The Software House
 
Concurrent Programming in Java
Concurrent Programming in Java
Ruben Inoto Soto
 
Discover Quarkus and GraalVM
Discover Quarkus and GraalVM
Romain Schlick
 
Microservices architecture
Microservices architecture
Abdelghani Azri
 
Resilience4j with Spring Boot
Resilience4j with Spring Boot
Knoldus Inc.
 

Similar to Reactive Programming in Java and Spring Framework 5 (20)

Functional reactive programming
Functional reactive programming
Araf Karsh Hamid
 
Journey into Reactive Streams and Akka Streams
Journey into Reactive Streams and Akka Streams
Kevin Webber
 
Microservices Part 4: Functional Reactive Programming
Microservices Part 4: Functional Reactive Programming
Araf Karsh Hamid
 
Guide to Spring Reactive Programming using WebFlux
Guide to Spring Reactive Programming using WebFlux
Inexture Solutions
 
Reactive Streams and RxJava2
Reactive Streams and RxJava2
Yakov Fain
 
Multi-service reactive streams using Spring, Reactor, RSocket
Multi-service reactive streams using Spring, Reactor, RSocket
Stéphane Maldini
 
Reactive solutions using java 9 and spring reactor
Reactive solutions using java 9 and spring reactor
OrenEzer1
 
Springone2gx 2014 Reactive Streams and Reactor
Springone2gx 2014 Reactive Streams and Reactor
Stéphane Maldini
 
Introduction to reactive programming
Introduction to reactive programming
Leapfrog Technology Inc.
 
Reactive mesh
Reactive mesh
Kalin Maldzhanski
 
Reactive Card Magic: Understanding Spring WebFlux and Project Reactor
Reactive Card Magic: Understanding Spring WebFlux and Project Reactor
VMware Tanzu
 
Spring 5 Webflux - Advances in Java 2018
Spring 5 Webflux - Advances in Java 2018
Trayan Iliev
 
Reactors.io
Reactors.io
Knoldus Inc.
 
Reactive Streams 1.0.0 and Why You Should Care (webinar)
Reactive Streams 1.0.0 and Why You Should Care (webinar)
Legacy Typesafe (now Lightbend)
 
Reactive Applications with Apache Pulsar and Spring Boot
Reactive Applications with Apache Pulsar and Spring Boot
VMware Tanzu
 
RxJava - introduction & design
RxJava - introduction & design
allegro.tech
 
Building Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJava
Rick Warren
 
Building a Reactive System with Akka - Workshop @ O'Reilly SAConf NYC
Building a Reactive System with Akka - Workshop @ O'Reilly SAConf NYC
Konrad Malawski
 
Android reactive programming using agera
Android reactive programming using agera
Mahmoud El-Naggar
 
Java 8 streams
Java 8 streams
Srinivasan Raghvan
 
Functional reactive programming
Functional reactive programming
Araf Karsh Hamid
 
Journey into Reactive Streams and Akka Streams
Journey into Reactive Streams and Akka Streams
Kevin Webber
 
Microservices Part 4: Functional Reactive Programming
Microservices Part 4: Functional Reactive Programming
Araf Karsh Hamid
 
Guide to Spring Reactive Programming using WebFlux
Guide to Spring Reactive Programming using WebFlux
Inexture Solutions
 
Reactive Streams and RxJava2
Reactive Streams and RxJava2
Yakov Fain
 
Multi-service reactive streams using Spring, Reactor, RSocket
Multi-service reactive streams using Spring, Reactor, RSocket
Stéphane Maldini
 
Reactive solutions using java 9 and spring reactor
Reactive solutions using java 9 and spring reactor
OrenEzer1
 
Springone2gx 2014 Reactive Streams and Reactor
Springone2gx 2014 Reactive Streams and Reactor
Stéphane Maldini
 
Reactive Card Magic: Understanding Spring WebFlux and Project Reactor
Reactive Card Magic: Understanding Spring WebFlux and Project Reactor
VMware Tanzu
 
Spring 5 Webflux - Advances in Java 2018
Spring 5 Webflux - Advances in Java 2018
Trayan Iliev
 
Reactive Streams 1.0.0 and Why You Should Care (webinar)
Reactive Streams 1.0.0 and Why You Should Care (webinar)
Legacy Typesafe (now Lightbend)
 
Reactive Applications with Apache Pulsar and Spring Boot
Reactive Applications with Apache Pulsar and Spring Boot
VMware Tanzu
 
RxJava - introduction & design
RxJava - introduction & design
allegro.tech
 
Building Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJava
Rick Warren
 
Building a Reactive System with Akka - Workshop @ O'Reilly SAConf NYC
Building a Reactive System with Akka - Workshop @ O'Reilly SAConf NYC
Konrad Malawski
 
Android reactive programming using agera
Android reactive programming using agera
Mahmoud El-Naggar
 
Ad

More from Richard Langlois P. Eng. (7)

Monitoring with Prometheus
Monitoring with Prometheus
Richard Langlois P. Eng.
 
Continuous Test Automation, by Richard Langlois P. Eng. and Yuri Pechenko.
Continuous Test Automation, by Richard Langlois P. Eng. and Yuri Pechenko.
Richard Langlois P. Eng.
 
Microservice Architecture Patterns, by Richard Langlois P. Eng.
Microservice Architecture Patterns, by Richard Langlois P. Eng.
Richard Langlois P. Eng.
 
What's New in Java 9
What's New in Java 9
Richard Langlois P. Eng.
 
DevOps, Yet Another IT Revolution
DevOps, Yet Another IT Revolution
Richard Langlois P. Eng.
 
What is new in JUnit5
What is new in JUnit5
Richard Langlois P. Eng.
 
Introduction to Reactive Microservices Architecture.
Introduction to Reactive Microservices Architecture.
Richard Langlois P. Eng.
 
Ad

Recently uploaded (20)

Milwaukee Marketo User Group June 2025 - Optimize and Enhance Efficiency - Sm...
Milwaukee Marketo User Group June 2025 - Optimize and Enhance Efficiency - Sm...
BradBedford3
 
SAP PM Module Level-IV Training Complete.ppt
SAP PM Module Level-IV Training Complete.ppt
MuhammadShaheryar36
 
IMAGE CLASSIFICATION USING CONVOLUTIONAL NEURAL NETWORK.P.pptx
IMAGE CLASSIFICATION USING CONVOLUTIONAL NEURAL NETWORK.P.pptx
usmanch7829
 
Integrating Survey123 and R&H Data Using FME
Integrating Survey123 and R&H Data Using FME
Safe Software
 
Advanced Token Development - Decentralized Innovation
Advanced Token Development - Decentralized Innovation
arohisinghas720
 
How Insurance Policy Management Software Streamlines Operations
How Insurance Policy Management Software Streamlines Operations
Insurance Tech Services
 
Step by step guide to install Flutter and Dart
Step by step guide to install Flutter and Dart
S Pranav (Deepu)
 
MOVIE RECOMMENDATION SYSTEM, UDUMULA GOPI REDDY, Y24MC13085.pptx
MOVIE RECOMMENDATION SYSTEM, UDUMULA GOPI REDDY, Y24MC13085.pptx
Maharshi Mallela
 
UPDASP a project coordination unit ......
UPDASP a project coordination unit ......
withrj1
 
What is data visualization and how data visualization tool can help.pdf
What is data visualization and how data visualization tool can help.pdf
Varsha Nayak
 
Async-ronizing Success at Wix - Patterns for Seamless Microservices - Devoxx ...
Async-ronizing Success at Wix - Patterns for Seamless Microservices - Devoxx ...
Natan Silnitsky
 
DevOps for AI: running LLMs in production with Kubernetes and KubeFlow
DevOps for AI: running LLMs in production with Kubernetes and KubeFlow
Aarno Aukia
 
Agile Software Engineering Methodologies
Agile Software Engineering Methodologies
Gaurav Sharma
 
Wondershare PDFelement Pro 11.4.20.3548 Crack Free Download
Wondershare PDFelement Pro 11.4.20.3548 Crack Free Download
Puppy jhon
 
Smadav Pro 2025 Rev 15.4 Crack Full Version With Registration Key
Smadav Pro 2025 Rev 15.4 Crack Full Version With Registration Key
joybepari360
 
AI-Powered Compliance Solutions for Global Regulations | Certivo
AI-Powered Compliance Solutions for Global Regulations | Certivo
certivoai
 
IBM Rational Unified Process For Software Engineering - Introduction
IBM Rational Unified Process For Software Engineering - Introduction
Gaurav Sharma
 
Meet You in the Middle: 1000x Performance for Parquet Queries on PB-Scale Dat...
Meet You in the Middle: 1000x Performance for Parquet Queries on PB-Scale Dat...
Alluxio, Inc.
 
FME as an Orchestration Tool - Peak of Data & AI 2025
FME as an Orchestration Tool - Peak of Data & AI 2025
Safe Software
 
Application Modernization with Choreo - The AI-Native Internal Developer Plat...
Application Modernization with Choreo - The AI-Native Internal Developer Plat...
WSO2
 
Milwaukee Marketo User Group June 2025 - Optimize and Enhance Efficiency - Sm...
Milwaukee Marketo User Group June 2025 - Optimize and Enhance Efficiency - Sm...
BradBedford3
 
SAP PM Module Level-IV Training Complete.ppt
SAP PM Module Level-IV Training Complete.ppt
MuhammadShaheryar36
 
IMAGE CLASSIFICATION USING CONVOLUTIONAL NEURAL NETWORK.P.pptx
IMAGE CLASSIFICATION USING CONVOLUTIONAL NEURAL NETWORK.P.pptx
usmanch7829
 
Integrating Survey123 and R&H Data Using FME
Integrating Survey123 and R&H Data Using FME
Safe Software
 
Advanced Token Development - Decentralized Innovation
Advanced Token Development - Decentralized Innovation
arohisinghas720
 
How Insurance Policy Management Software Streamlines Operations
How Insurance Policy Management Software Streamlines Operations
Insurance Tech Services
 
Step by step guide to install Flutter and Dart
Step by step guide to install Flutter and Dart
S Pranav (Deepu)
 
MOVIE RECOMMENDATION SYSTEM, UDUMULA GOPI REDDY, Y24MC13085.pptx
MOVIE RECOMMENDATION SYSTEM, UDUMULA GOPI REDDY, Y24MC13085.pptx
Maharshi Mallela
 
UPDASP a project coordination unit ......
UPDASP a project coordination unit ......
withrj1
 
What is data visualization and how data visualization tool can help.pdf
What is data visualization and how data visualization tool can help.pdf
Varsha Nayak
 
Async-ronizing Success at Wix - Patterns for Seamless Microservices - Devoxx ...
Async-ronizing Success at Wix - Patterns for Seamless Microservices - Devoxx ...
Natan Silnitsky
 
DevOps for AI: running LLMs in production with Kubernetes and KubeFlow
DevOps for AI: running LLMs in production with Kubernetes and KubeFlow
Aarno Aukia
 
Agile Software Engineering Methodologies
Agile Software Engineering Methodologies
Gaurav Sharma
 
Wondershare PDFelement Pro 11.4.20.3548 Crack Free Download
Wondershare PDFelement Pro 11.4.20.3548 Crack Free Download
Puppy jhon
 
Smadav Pro 2025 Rev 15.4 Crack Full Version With Registration Key
Smadav Pro 2025 Rev 15.4 Crack Full Version With Registration Key
joybepari360
 
AI-Powered Compliance Solutions for Global Regulations | Certivo
AI-Powered Compliance Solutions for Global Regulations | Certivo
certivoai
 
IBM Rational Unified Process For Software Engineering - Introduction
IBM Rational Unified Process For Software Engineering - Introduction
Gaurav Sharma
 
Meet You in the Middle: 1000x Performance for Parquet Queries on PB-Scale Dat...
Meet You in the Middle: 1000x Performance for Parquet Queries on PB-Scale Dat...
Alluxio, Inc.
 
FME as an Orchestration Tool - Peak of Data & AI 2025
FME as an Orchestration Tool - Peak of Data & AI 2025
Safe Software
 
Application Modernization with Choreo - The AI-Native Internal Developer Plat...
Application Modernization with Choreo - The AI-Native Internal Developer Plat...
WSO2
 

Reactive Programming in Java and Spring Framework 5

  • 1. Reactive Programming in Java and Spring 5 Richard Langlois P. Eng., Solutions Architect January 24th, 2018
  • 2. > • Introduction to Reactive Programming • Reactive Manifesto • Reactive Streams Specification • Reactor • Reactive Programming with Spring 5 • Reactive Spring Data Agenda
  • 3. > • Is a programming paradigm. • Is about: • Non-blocking applications which are • asynchronous • even-driven • require a small amount of threads to scale vertically (within the JVM). Introduction to Reactive Programming
  • 4. > From Merriam Webster: “Readily responsive to a stimulus” • React to events (event-driven) • React to load (scalable) • React to failures (resilient) • React to users (responsive) Key to understand reactive programming is to think about it as operating on a stream of data. Steam of data meaning a sequence of events, where an event could be • user input (like a tap on a button), • a response from an API request (like a Facebook feed), • data contained in a database, • a single variable. Reactive
  • 5. > Reactive Manifesto is a prescription for building modern, cloud scale architecture, which is well prepared to meet the increasing demands that applications face today. Homepage: http://reactivemanifesto.org/ Reactive Manifesto
  • 6. > The Four Reactive Traits: • Responsive: Application provides rich, real-time interaction with its users even under load and in the presence of failures. • Resilient: Application recover quickly from failure (e.g. software, hardware, connections). • Scalable: Application is able to be expanded according to its usage • scale up: make use of more powerful hardware (aka vertical scaling) • scale out: make use of multiple server nodes (aka horizontal scaling) • Event-Driven: Application is composed of loosely coupled event handlers. Events can be handled asynchronously, without blocking. Reactive Manifesto Characteristics
  • 7. > Reactive Streams is a Standard and specification for Stream‐oriented libraries for the JVM that • process a potentially unbounded number of elements in sequence • asynchronously passing elements between components • with mandatory non‐blocking backpressure. Specification consists of the following parts: • The API specifies the types to implement Reactive Streams and achieve interoperability between different implementations. • The Technology Compatibility Kit (TCK): a standard test suite for conformance testing of implementations. Reactive Streams are only concerned with mediating the stream of data between different API Components (so operators are not specified). Reactive Streams specification
  • 8. > Allows to control the amount of inflight data Regulate the transfer between: • Slow publisher and fast consumer • Fast publisher and slow consumer Back Pressure (a.k.a. Flow Control)
  • 10. > Those interfaces are included in Java 9 (under java.util.concurrent): • Flow.Publisher • Flow.Subscriber • Flow.Subscription • Flow.Processor Reactive Streams Specification Java 9
  • 11. > API Explanation: • Communication between publisher and subscriber is set up via the publisher’s subscribe(), through which the two parties are introduced to each other. • After successful initialization of the communication, the subscriber gets to know about a Subscription (which models the established connection) via a call to its onSubscribe method. • At the core of the Reactive Streams mechanism is the request method of the Subscription. Through the request() method, the subscriber signals to the publisher how many elements it’s ready to process. • The publisher communicates every element one by one to the subscriber via its onNext() method, as well as fatal stream failures through the onError() method. • Because the publisher knows exactly how many items it’s expected to publish at any time (it has been asked for a number of elements in the Subscription’s request method), it’s able to produce as many elements as required without producing too many for the subscriber to consume, eliminating the need to block while waiting for the subscriber. • Additionally, the subscriber is called by the publisher for each published element through the onNext() method, meaning that it does not explicitly need to block while waiting for new elements to be available. Reactive Streams Specification
  • 12. > Some Reactive Libraries on the JVM: • RxJava: Reactive Extensions implemented on the JVM. • Akka Streams • Reactor Core: Reactive Stream Specification
  • 13. > Is a fourth-generation Reactive library for building non-blocking applications on the JVM based on the Reactive Streams Specification. • Targets Java 8. • Extends a Reactive Streams Publisher with the Flux and Mono API types. It adds the concept of operators, which are chained together to describe what processing to apply at each stage to the data. Applying an operator returns a new intermediate Publisher. Reactor Core 3
  • 15. > Flux: • A Flux<T> is a standard Publisher<T> representing an asynchronous sequence of 0 to N emitted items, optionally terminated by either a completion signal or an error. • Possible values of a flux: a value, a completion signal, an error. • Translates to calls to a downstream object’s onNext, onComplete, onError methods. • Marble diagram: Reactor Core Features
  • 16. > Mono: • A Mono is a standard Publisher<T> that emits at most one item and then optionally terminates with an onComplete signal or an onError signal. • It offers only a subset of the operators that are available for a Flux. • Can represent no-value asynchronous processes which have the concept of completion (Mono<void>). Reactor Core Features
  • 17. > Numerous factory methods: • Flux<String> seq1 = Flux.just("foo", "bar", "foobar"); • private static List<String> iterable = Arrays.asList ("foo", "bar", "foobar"); Flux<String> fluxFromIterable = Flux.fromIterable(iterable); • Mono<String> noData = Mono.empty(); • Mono<String> data = Mono.just("foo"); • Flux<Integer> numbersFromFiveToSeven = Flux.range(5, 3); // 1st parameter is start of the range, 2nd is number of items Reactor Flux or Mono Creation
  • 18. > .subscribe variants take lambdas for different combination of callbacks: 1. subscribe(); // subscribe and trigger the sequence 2. subscribe(Consumer<? super T> consumer); // consumer run when values 3. subscribe(Consumer<? super T> consumer, // deal with values Consumer<? super Throwable> errorConsumer); // consumer run when error 4. subscribe(Consumer<? super T> consumer, // deal with values Consumer<? super Throwable> errorConsumer, // Consumer run when error Runnable completeConsumer); // consumer run when sequence successfully complete 5. subscribe(Consumer<? super T> consumer, // deal with values Consumer<? super Throwable> errorConsumer, // consumer run when error Runnable completeConsumer, // consumer run when the sequence successfully complete Consumer<? super Subscription> subscriptionConsumer); // consumer run when subscription produced Reactor - Subscribe
  • 19. > Example: // Use the subscribe() method to collect all the elements in a stream Flux<Integer> elementsFlux = Flux.just(1, 2, 3, 4); // subscribe with a subscriber that will print the values, The data will not start flowing until we subscribe elementsFlux().subscribe(System.out::println(i)); Logs: [main] INFO reactor.Flux.Array.1 - | onSubscribe([Synchronous Fuseable] FluxArray.ArraySubscription) 20:25:19.553 [main] INFO reactor.Flux.Array.1 - | request(unbounded) 20:25:19.553 [main] INFO reactor.Flux.Array.1 - | onNext(1) 20:25:19.553 [main] INFO reactor.Flux.Array.1 - | onNext(2) 20:25:19.553 [main] INFO reactor.Flux.Array.1 - | onNext(3) 20:25:19.553 [main] INFO reactor.Flux.Array.1 - | onNext(4) 20:25:19.553 [main] INFO reactor.Flux.Array.1 - | onComplete() Reactor - Subscribe
  • 20. > Example: Tell upstream to only send 2 elements at a time by using request(). Flux.just(1, 2, 3, 4) .log() .subscribe(new Subscriber<Integer>() { private Subscription s; int onNextAmount; @Override public void onSubscribe(Subscription s) { this.s = s; s.request(2); } … Reactor – Back Pressure Example (1 of 3)
  • 21. > … @Override public void onNext(Integer integer) { elements.add(integer); onNextAmount++; if (onNextAmount % 2 == 0) { s.request(2); } } @Override public void onError(Throwable t) {} @Override public void onComplete() {} }); Reactor – Back Pressure Example (2 of 3)
  • 22. > Logs: 23:31:15.395 [main] INFO reactor.Flux.Array.1 - | onSubscribe([Synchronous Fuseable] FluxArray.ArraySubscription) 23:31:15.397 [main] INFO reactor.Flux.Array.1 - | request(2) 23:31:15.397 [main] INFO reactor.Flux.Array.1 - | onNext(1) 23:31:15.398 [main] INFO reactor.Flux.Array.1 - | onNext(2) 23:31:15.398 [main] INFO reactor.Flux.Array.1 - | request(2) 23:31:15.398 [main] INFO reactor.Flux.Array.1 - | onNext(3) 23:31:15.398 [main] INFO reactor.Flux.Array.1 - | onNext(4) 23:31:15.398 [main] INFO reactor.Flux.Array.1 - | request(2) 23:31:15.398 [main] INFO reactor.Flux.Array.1 - | onComplete() Notice: The request(2) is called (when Subscribing), followed by two onNext() calls, then request(2) again, then on Complete(). Reactor – Back Pressure Example (3 of 3)
  • 23. > Reactive Operators applies a wide range of transformations to the sequence of data (e.g. Map, Flatmap, Filter, Concat, Merge, buffer, split, transform, delay …) Special diagrams called Marble Diagrams efficiently explains what an operator does, for example: Reactor - Reactive Operators
  • 24. > Map: Transform every item of the emitted sequence with a specified function. Reactor – Reactive Operators Map()
  • 25. > Concat: concatenates 2 or more emissions, generating one emission where all the items from the 1st source emission appear before the items of the 2nd source emission. Reactor - Reactive Operators Concat()
  • 26. > flatMap(): performs 2 types of actions: 1. the “map” action that transforms the emitted item into Flux 2. The “flatten” action that converts those Flux into one Flux. Reactor - Reactive Operators flatMap
  • 27. > Merge: When we want to get feeds from multiple sources as one stream. Reactor - Reactive Operators merge()
  • 28. > Zip: takes multiple observables as inputs and combines each emission via a specified function and emits the results of this function as a new sequence. Reactor - Reactive Operators zip()
  • 29. > StepVerifier API: • Builder API allowing to test how a Flux or Mono behave when subscribed to. Some methods: • expectNext() • expectError() • expectErrorMessage() • expectComplete() • Verify(), VerifyComplete(), VerifyError(), VerifyErrorMessage() Reactor - Testing StepVerifier
  • 30. > Example: // empty Flux Flux<String> emptyFlux = Flux.empty(); StepVerifier.create(emptyFlux).verifyComplete(); // non-empty Flux Flux<String> nonEmptyFlux = Flux.just("John", "Mike", "Sarah"); StepVerifier.create(nonEmptyFlux).expectNext("John", "Mike", "Sarah").verify(); Call to verify(): • triggers the verification by subscribing to the Flux/Mono under test. • Plays the sequence, comparing each new signal with the next step in the scenario • As long as these match, the test is considered a success, else, an AssertionError is thrown. Reactor - Testing StepVerifier
  • 31. > • New spring-webflux module to support reactive HTTP client-side and server-side. • Uses Reactor internally for its own reactive support. Spring Framework 5 Reactive Support
  • 32. > Spring 5 Reactive and Servlet Stack
  • 33. > Add Dependency to pom.xml: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> Spring 5 WebFlux
  • 34. > • Supports 2 distinct programming models: • Annotation-based with @Controller and the other annotations of Spring MVC • Functional Style routing and handling with Java 8 lambda. Spring 5 Server Side
  • 35. > Example: @RestController @RequestMapping(value="/api/customer") public class RestControllerAPIs { @GetMapping("/") public Flux<Customer> getAll() { ... } @GetMapping("/{id}") public Mono<Customer> getCustomer(@PathVariable Long id) { ... } } Spring 5 - WebFlux Server Side - Annotation-based - Example
  • 36. > Get all customers test case: Map<Long, Customer> custStores = new HashMap<Long, Customer>(); … @GetMapping public Flux<Customer> getAll() { return Flux.fromIterable(custStores.entrySet().stream() .map(entry -> entry.getValue()) .collect(Collectors.toList())); } Spring 5 - WebFlux Server Side - Annotation-based - Example
  • 37. > Get a customer test case: @GetMapping("/{id}") public Mono<Customer> getCustomer(@PathVariable Long id) { return Mono.justOrEmpty(custStores.get(id)); } Spring 5 - WebFlux Server Side - Annotation-based - Example
  • 38. > Create a customer test case: @PostMapping("/post") public Mono<ResponseEntity<String>> postCustomer(@RequestBody Customer customer) { // do post custStores.put(customer.getCustId(), customer); return Mono.just(new ResponseEntity<>("Post Successfully!", HttpStatus.CREATED)); } Spring 5 - WebFlux Server Side - Annotation-based - Example
  • 39. > Framework introduces 2 fundamental components: • Routes a given HTTP requests via a RouterFunction (alternative to using annotations like @RequestMapping) • Handles the request via HandlerFunction (alternative to @Controller’s handler methods). RouterFunction utility classes are used to create RouterFunction: e.g. RouterFunction.route(RequestPredicate, HandlerFunction): • helper function to create routes. • Allows to route requests by applying a RequestPredicate. • When the predicate is matched, then the second argument is run. Spring 5 - WebFlux Server Side - Functional Style
  • 40. > Example: RouterFunction router = route( GET("/test"), request -> ok().build() ) ; • GET("/test") is the RequestPredicate. • req -> ok().build() is the handler producing the response. Spring 5 Server Side – Functional Style
  • 41. > WebClient • Is a reactive client for performing HTTP requests with Reactive Streams back pressure. • Is replacing the classic RestTemplate. • Is an interface which has a single implementation – DefaultWebClient class. Usage(similar to HttpClient): 1. Create an instance 2. Make a request 3. Handle the reponse Spring 5 Client side
  • 42. > Create WebClient using one of the 3 options : • With default settings: • WebClient client1 = WebClient.create(); • With a given base URI: • WebClient client2 = WebClient.create("http://localhost:8080 (http://localhost:8080)"); • Using the DefaultWebClientBuilder class: • WebClient client3 = WebClient .builder() .baseUrl("http://localhost:8080 (http://localhost:8080)") .defaultCookie("cookieKey", "cookieValue") .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .defaultUriVariables(Collections.singletonMap("url", "http://localhost:8080 (http://localhost:8080)")) .build(); Spring 5 Client side - WebClient
  • 43. > // Setting a request body //where a Publisher is a reactive component that is in charge of providing a potentially unbounded number of sequenced elements. WebClient.RequestHeadersSpec requestSpec1 = WebClient.create() .method(HttpMethod.POST) .uri("/resource") .body(BodyInserters.fromPublisher(Mono.just("data")), String.class); WebClient.RequestHeadersSpec<?> requestSpec2 = WebClient.create("http://localhost:8080 (http://localhost:8080)") .post() .uri(URI.create("/resource")) .body(BodyInserters.fromObject("data")); Spring 5 Client side - WebClient
  • 44. > A Response is obtained with exchange() or retrieve(): • exchange(): provides a ClientResponse along with its status, headers • retrieve(): fetches a body directly Example: String response2 = request1.exchange() .block() .bodyToMono(String.class) .block(); String response3 = request2.retrieve() .bodyToMono(String.class) .block(); Note: The block method on Monos is used to subscribe and retrieve an actual data which was sent with the response. Spring 5 Client side - WebClient
  • 45. > WebTestClient • is a non-blocking, reactive client for Spring-webflux integration testing support. • Offers an identical API as the WebClient. • can connect to any server over an HTTP connection. • provides a fluent API to verify responses. • can also bind directly to WebFlux applications with mock request and response objects. Spring 5 Spring WebFlux Testing
  • 47. > @WebFluxTest: • auto-configures WebTestClient to quickly test WebFlux controllers without starting a full HTTP server Example of an unit test: @RunWith(SpringRunner.class) @WebFluxTest public class SpringWebFluxTestApplicationTests { @Autowired private WebTestClient webTestClient; … } Spring 5 - WebFlux Testing
  • 48. > Test without starting an actual server: WebTestClient client = WebTestClient.bindToRouterFunction(routingFunction()) .build(); client.get().uri("/").exchange() .expectStatus().isOk(); // Assert Test with a real server: WebTestClient client = WebTestClient.bindToServer() .baseUrl("http://localhost:8080 (http://localhost:8080)") .build(); client.get().uri("/").exchange() .expectStatus().isOk(); // Assert Spring 5 - WebFlux WebTestClient
  • 49. > Get test case: Using WebTestClient API: webTestClient.get().uri("/api/customer/{id}", 2).accept(MediaType.APPLICATION_JSON).exchange() .expectStatus().isOk().expectBody(Customer.class).isEqualTo(customerMap.get("Peter")); // Assert Using RouterFunction: // The Router Function RouterFunction myRouterFunction = route(GET("/test"), // RouterFunction request -> ok().body(fromObject("hello world"))); // HandlerFunction // Register the RouterFunction WebTestClient webTestClient = WebTestClient.bindToRouterFunction(myRouterFunction).build(); // Assert the response webTestClient.get().uri("/test").exchange().expectStatus().isOk(); Spring 5 WebTestClient - Example
  • 50. > POST test case: webTestClient // Create a POST request .post() .uri("/api/customer/post") .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromObject(customerMap.get("Mary"))) .exchange() // Assert the response .expectStatus().isCreated() .expectBody(String.class) .isEqualTo("Post Successfully!"); Spring 5 WebTestClient - Example
  • 51. > PUT test case: webTestClient // Create a PUT request .put().uri("/api/customer/put/{id}", 3) .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromObject(customerMap.get("Amy"))) .exchange() // Assert the response .expectStatus().isCreated() .expectBody(Customer.class) isEqualTo(customerMap.get("Amy")); Spring 5 WebTestClient - Example
  • 52. > DELETE test case: webTestClient // Create a DELETE request .delete().uri("/api/customer/delete/{id}", 1) .exchange() // Assert the response .expectStatus().isAccepted() .expectBody(String.class) .isEqualTo("Delete Succesfully!"); Spring 5 WebTestClient - Example
  • 53. > Spring WebFlux is supported on the following servers: • Netty • Undertow • Tomcat • Jetty • Servlet 3.1+ containers Spring Boot 2 uses Netty by default with WebFlux Spring 5 Choosing a server
  • 54. > • Asynchronous • Non Blocking • Event Driven • Data as stream Reactive Data Access
  • 55. > Spring Data support Reactive Streams Reactive Spring Data Modules: • MongoDb • Redis • Cassandra • CouchDB Reactive Spring Data
  • 56. > Lets see an example based on Spring Data and MongoDB Spring Data - MongoDB
  • 57. > Getting up a running Reactive Streams with Spring Data and MongoDB: • Add the dependency (in pom.xml) • Configuration (@EnableReactiveMongoRepositories) • Repository interface (extends ReactiveMongoRepository, and use Flux and Mono types) Spring Data - MongoDB
  • 58. > Add Reactive MongoDB to our pom.xml: <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.BUILD-SNAPSHOT</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId> </dependency> </dependencies> <repositories> <repository> <id>spring-libs-snapshot</id> <name>Spring Snapshot Repository</name> <url>http://repo.spring.io/libs-snapshot</url> </repository> </repositories> Spring Data - MongoDB Example
  • 59. > @Configuration @EnableReactiveMongoRepositories(basePackageClasses = PersonRepository.class) public class MongoConfig extends AbstractReactiveMongoConfiguration { @Bean public MongoClient mongoClient() { return MongoClients.create(); } @Override protected String getDatabaseName() { return "test"; } @Bean public ReactiveMongoTemplate reactiveMongoTemplate() { return new ReactiveMongoTemplate(mongoClient(), getDatabaseName()); } } Spring Data – MongoDB Example - Configuration
  • 60. > Configuration: @EnableMongoRepositories enable the use of ReactiveCrudRepository. For example: • Mono<S> = save(S entity) • Mono<T> = findById(ID id) • Mono<T> = findById(Publisher<ID> id) • Uses the first emitted element to perform the find-query • Mono<void> = deleteById(ID id) • Mono signaling when operation is completed Spring Data – MongoDB Example
  • 61. > Repository: @EnableMongoRepositories enable the use of ReactiveCrudRepository. public interface PersonRepository extends ReactiveMongoRepository<Person, String> { Flux<Person> findByFirstName(final String firstName); Mono<Person> findOneByFirstName(final String firstName); Mono<void> = deleteById(ID id); //Mono signaling when operation is completed } Notice: • Flux<Person> replaces the use of List • Mono<Person> is used instead of Person. This allows to perform functions on each element as they come from MongoDB database, instead of waiting until all records are returned, and then do something with them. Spring Data – MongoD Example
  • 62. > Application: @SpringBootApplication public class Application implements CommandLineRunner { … @Override public void run(String args[]) { final Person johnAoe = new Person("john", "aoe", LocalDateTime.now(), "loser", 0); final Person johnBoe = new Person("john", "boe", LocalDateTime.now(), "a bit of a lose personRepository.saveAll(Flux.just(johnAoe, johnBoe)).subscribe(); personRepository.findByFirstName("john").log().map(Person::getSecondName) .subscribe(System.out::println); personRepository.findOneByFirstName("john").log().map(Person::getId) .subscribe(System.out::println); } } Spring Data – MongoD Example
  • 63. > Associated Logs: 2017-07-16 16:44:09.201 INFO 13476 --- [ main] reactor.Flux.OnErrorResume.1 : onSubscribe(FluxOnErrorResume.ResumeSubscriber) 2017-07-16 16:44:09.208 INFO 13476 --- [ main] reactor.Flux.OnErrorResume.1 : request(unbounded) 2017-07-16 16:44:09.242 INFO 13476 --- [ Thread-4] reactor.Flux.OnErrorResume.1 : onNext(Person(firstName=john, secondName=aoe, profession=loser, salary=0)) aoe 2017-07-16 16:44:09.243 INFO 13476 --- [ Thread-4] reactor.Flux.OnErrorResume.1 : onNext(Person(firstName=john, secondName=boe, profession=a bit of a loser, salary=10)) boe 2017-07-16 16:44:09.247 INFO 13476 --- [ Thread-4] reactor.Flux.OnErrorResume.1 : onComplete() 2017-07-16 16:44:09.254 INFO 13476 --- [ main] reactor.Mono.OnErrorResume.2 : onSubscribe(FluxOnErrorResume.ResumeSubscriber) 2017-07-16 16:44:09.255 INFO 13476 --- [ main] reactor.Mono.OnErrorResume.2 : request(unbounded) 2017-07-16 16:44:09.260 INFO 13476 --- [ Thread-4] reactor.Mono.OnErrorResume.2 : onNext(Person(firstName=john, secondName=aoe, profession=loser, salary=0)) 596b89c97ab38934a404a80c 2017-07-16 16:44:09.260 INFO 13476 --- [ Thread-4] reactor.Mono.OnErrorResume.2 : onComplete() Spring Data – MongoD Example
  • 64. > • The Reactive Manifesto: • https://www.reactivemanifesto.org/ • Reactor: • https://projectreactor.io/ • Spring WebFlux: • https://docs.spring.io/spring/docs/5.0.0.BUILD-SNAPSHOT/spring-framework-reference/html/web-reactive.html • Going reactive with Spring Data: • https://spring.io/blog/2016/11/28/going-reactive-with-spring-data • Servlet vs Reactive Stacks in Five Use Cases: • https://www.infoq.com/presentations/servlet-reactive-stack References