0% found this document useful (0 votes)
2 views61 pages

Reactive Programming

The document provides an overview of Spring Reactive Programming, contrasting imperative and reactive code, and detailing the components of reactive streams including Publisher, Subscriber, Subscription, and Processor. It explains the advantages of reactive programming, such as asynchronous processing and backpressure, and introduces the Spring WebFlux framework for building non-blocking web applications. Additionally, it includes examples of creating reactive types using Flux and Mono, and demonstrates how to develop a reactive REST API with a MySQL database using Spring WebFlux.

Uploaded by

urcrush25
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views61 pages

Reactive Programming

The document provides an overview of Spring Reactive Programming, contrasting imperative and reactive code, and detailing the components of reactive streams including Publisher, Subscriber, Subscription, and Processor. It explains the advantages of reactive programming, such as asynchronous processing and backpressure, and introduces the Spring WebFlux framework for building non-blocking web applications. Additionally, it includes examples of creating reactive types using Flux and Mono, and demonstrates how to develop a reactive REST API with a MySQL database using Spring WebFlux.

Uploaded by

urcrush25
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 61

Spring Reactive Programming

Dr. Arul Xavier V M


Two Types of Application Development
 Imperative code
 It’s a serial set of tasks, each running one at a time, each after the previous task.

 Data is processed in bulk and can’t be handed over to the next task until the
previous task has completed its work on the bulk of data.
 Reactive code
 A set of tasks is defined to process data, but those tasks can run in parallel.

 Each task can process subsets of the data, handing it off to the next task in line
while it continues to work on another subset of the data.
Reactive Programming
 Reactive programming is functional and declarative in nature.
 Rather than describe a set of steps that are to be performed
sequentially, reactive programming involves describing a pipeline or
stream through which data flows.
 Rather than requiring the data be available to be processed as a
whole, a reactive stream processes data as it becomes available.
 Reactive Streams aims to provide a standard for asynchronous
stream processing with non-blocking backpressure.
Java Stream vs Reactive Streams
 Java Streams:-
 synchronous and work with a finite set of data
 Reactive Streams
 asynchronous processing of datasets of any size, including
infinite datasets.
 process data in real time, as it becomes available, with
backpressure to avoid overwhelming their consumers.
Data Flow in Reactive Stream

Publisher

Subscriber
Back Pressure on Data Streams
Problems:
Client application may not be able to handle huge data.
Client application may crash with out of memory error.

Reactive Program apply backpressure by which the client can request the amount of data it
can handle and the server limit the data depending on the client request
Building Blocks of Reactive Programming

 Publisher
 A Publisher produces data that it sends to a Subscriber per a
Subscription.
 Subscriber
 Consume the data from publisher through Subscription object.
 Subscription
 It represents the subscription details of a subscriber with the
publisher.
 Processor
 A Processor represents a processing stage contains both Publisher
and Subscriber.
Reactive Streams specification
Publisher
 Publisher is a data source which can always publish an event.

public interface Publisher<T> {


void subscribe(Subscriber<? super T> subscriber);
}

The Publisher interface declares a single method, subscribe(), through which


a Subscriber can subscribe to the Publisher:
Subscriber
 Subscriber will subscribe or consume the events from Publisher.
 Once a Subscriber has subscribed, it can receive events from the
Publisher.
 Those events are sent via methods on the Subscriber interface:

public interface Subscriber<T> {


void onSubscribe(Subscription sub);
void onNext(T item);
void onError(Throwable ex);
void onComplete();
}
Subscriber working principle
 The first event that the Subscriber will receive is through a call to onSubscribe().
 When the Publisher calls onSubscribe(), it passes a Subscription object to the
Subscriber.
 The Subscriber can call request() to request that data be sent, or it can call
cancel() to indicate that it’s no longer interested in receiving data and is canceling
the subscription.
 When calling request(), the Subscriber passes in a long value to indicate how
many data items it’s willing to accept.
 This is where backpressure comes in, preventing the Publisher from sending
more data than the Subscriber is able to handle.
 After the Publisher has sent as many items as were requested, the Subscriber
can call request() again to request more.
Subscription
 Subscription represents the unique relationship between
a Subscriber and a Publisher.

public interface Subscription {


void request(long n);
void cancel();
}

The Subscriber can call request() to request that data be sent, or it can call cancel() to indicate that
it’s no longer interested in receiving data and is canceling the subscription.
Processor
 A Processor represents a processing stage – which is
both a Subscriber and a Publisher and MUST obey the
contracts of both.
 The Processor interface, it’s a combination of Subscriber
and Publisher

public interface Processor<T, R> extends Subscriber<T>, Publisher<R> {}


Reactive Stream Workflow
Reactive Programming Library
 Spring Boot uses Project Reactor library to implement
reactive programming model using the following
dependencies.
 Project Reactor: https://projectreactor.io/
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>

<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
Reactor Data Types
 In order for an application to be reactive, the first thing it must be able to
do is to produce a stream of data.
 Reactive Core gives us two data types that enable us to do this.
 Flux
 It's a stream that can emit 0 to N number of data items.
 Eg:
 Flux<Integer> just = Flux.just(1, 2, 3, 4);
 Mono
 It is a stream of 0 or 1 data items.
 Eg:-
 Mono<Integer> just = Mono.just(1);
Create Reactive Types
 When working with reactive types in Spring, you’ll be given a
Flux or a Mono from a repository or a service, so you won’t
need to create one yourself.
 But occasionally you’ll need to create a new reactive
publisher.
 Reactor provides several operations for creating Fluxes and
Monos.
Create Project
 Add Spring Reactive Web
as dependency
Add a New Java Class
Create Mono - Example
import reactor.core.publisher.Mono;

public class MonoFluxDemo {


public void testMono() {
//Publisher
Mono<String> monodata = Mono.just("Hello World").log();
//To subscribe
monodata.subscribe(System.out :: println);
}
}

@SpringBootApplication
public class ReactiveExampleApplication {
public static void main(String[] args) {
//call testMono()
new MonoFluxDemo().testMono();
SpringApplication.run(ReactiveExampleApplication.class, args);
}
}
Test Mono Example
Create Flux – Example

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public class MonoFluxDemo {


public void testMono() {
Mono<String> monodata = Mono.just("Hello World").log();
monodata.subscribe(System.out :: println);
}
public void testFlux() {
Flux<String> fluxdata = Flux.just("Apple","Orange", "Manago","Pineapple","Grapes");
fluxdata.subscribe(System.out :: println);
}

}
Test Flux
Log Info for Flux elements
public class MonoFluxDemo {
public void testFlux() {
Flux<String> fluxdata = Flux.just("Apple","Orange", "Manago","Pineapple","Grapes")
.log();
fluxdata.subscribe(System.out :: println);
}
}
Flux operations
 Flux also provides the option to create more complex
functional operations such as filter, map etc..
public class MonoFluxDemo {
public void testFlux() {
Flux<Double> fluxdata = Flux.just(1,10,67,23,22,89,100,50,65,24)
.filter(item -> item%2 == 0)
.map(item->Math.pow(item, 2));
fluxdata.subscribe(System.out :: println);
}
Filter only even and make square of it
}
Combining Reactive Types
 mergeWith() method used to combine two flux data
import reactor.core.publisher.Flux;
public class MonoFluxDemo {
public void testFlux() {
Flux<Integer> fluxdata1 = Flux.just(1,2,3,4,5);
Flux<Integer> fluxdata2 = Flux.just(10,20,30,40,50);

Flux<Integer> mergedflux = fluxdata1.mergeWith(fluxdata2);


mergedflux.subscribe(System.out :: println);
}
}
delayElements(Duration.ofMillis()) method
 delayElements(Duration.ofSeconds()) method used to delay the data
emitting from publisher.
import java.time.Duration;
import reactor.core.publisher.Flux;
public class MonoFluxDemo {
public void testFlux() {
Flux<Integer> fluxdata1 = Flux.just(1,2,3,4,5)
.delayElements(Duration.ofSeconds(1));
Flux<Integer> fluxdata2 = Flux.just(10,20,30,40,50);
Flux<Integer> mergedflux = fluxdata1.mergeWith(fluxdata2);
mergedflux.subscribe(System.out :: println); 10
} 20
} 30
40
50
1
2
3
4
5
delaySubscription(Duration.ofSeconds()) method
 delaySubscription() operation to the Flux helps to stop emitting any
data until specified millisecond have passed following a subscription.
import java.time.Duration;
import reactor.core.publisher.Flux;

public class MonoFluxDemo {


public void testFlux() {
Flux<Integer> fluxdata1 = Flux.just(1,2,3,4,5)
.delayElements(Duration.ofSeconds(1));
Flux<Integer> fluxdata2 = Flux.just(10,20,30,40,50) 1
.delaySubscription(Duration.ofSeconds(1)); 10
20
Flux<Integer> mergedflux = fluxdata1.mergeWith(fluxdata2); 30
mergedflux.subscribe(System.out :: println); 40
} 50
2
} 3
4
5
Transforming and filtering reactive streams
 skip(number_of_items)
 create a new Flux that skips over a specified number of items
before emitting the remaining items from the source Flux.
 take()
 only emits the first so many items
 filter()
 operation lets you selectively publish based on criteria you want.
 distinct()
 emits the data without duplicate elements
filter() example
public class MonoFluxDemo {

public void testFlux() {


Flux<Integer> fluxdata = Flux.just(1,2,3,4,5,6,7,8,9,10)
.filter(item -> item%2==0);
fluxdata.subscribe(System.out :: println);
}

}
Transforming and filtering reactive streams
 map()
 creates a Flux that simply performs a transformation as
prescribed by a given Function on each object it receives before
republishing it.
 flatMap()
 to perform the mapping asynchronously, you should consider the
flatMap() operation.
map() transformation example

public class MonoFluxDemo {

public void testFlux() {


Flux<String> fluxdata = Flux.just("apple","orange","pineapple","mango")
.map(item -> item.toUpperCase());
fluxdata.subscribe(System.out :: println);
}

}
Developing Reactive APIs
Traditional Web MVC Framework
 Spring MVC, are blocking and multithreaded in nature, using
a single thread per connection.
 The request thread is blocked until it’s notified by the worker thread
that it’s finished.
 Consequently, blocking web frameworks won’t scale effectively
under heavy request volume.
 Latency in slow worker threads makes things even worse because
it’ll take longer for the worker thread to be returned to the pool,
ready to handle another request.
 With an increasing number of clients consuming web applications,
scalability is more important than ever.
Asynchronous web frameworks
 Achieve higher scalability with fewer threads—generally one per CPU
core.
 By applying a technique known as event looping these frameworks are
able to handle many requests per thread, making the per-connection
cost more economical.
Working with Spring WebFlux
 Spring 5 has introduced a non-blocking, asynchronous web
framework based largely on its Project Reactor to address
the need for greater scalability in web applications and APIs.
 Spring WebFlux
 a reactive web framework for Spring.
 sibling to Spring MVC and shares many of its core components.
Spring WebFlux

On the left side, you see the Spring MVC stack that was introduced in version 2.5 of the Spring
Framework. Spring MVC sits atop the Java Servlet API, which requires a servlet container (such as
Tomcat) to execute on.
By contrast, Spring WebFlux (on the right side) doesn’t have ties to the Servlet API, so it builds on top
of a Reactive HTTP API, which is a reactive approximation of the same functionality provided by the
Servlet API. And because Spring WebFlux isn’t coupled to the Servlet API, it doesn’t require a servlet
container to run on. Instead, it can run on any non-blocking web container including Netty, Undertow,
Tomcat, Jetty
Spring WebFlux
 Dependency required

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
Spring Reactive WebFlux Application with MySQL
Database

 This example demonstrate Reactive Rest APIs development


using Spring WebFlux for the following database tasks
 Get all Employee details
 Find one Employee by id
 Create new Employee data
 Delete Employee details
Database

Consider employee table in


mysql database called “karunya”
Create Spring WebFlux Project
 Dependencies Required
 Spring Reactive Web
 reactor-core
 spring-webflux
 spring-MVC
 Spring Data R2DBC
 Reactive Database Driver
 MySQL Driver
 R2DBC-MySQL
 Need to add manually in pom.xml
<dependency>
<groupId>dev.miku</groupId>
<artifactId>r2dbc-mysql</artifactId>
<version>0.8.2.RELEASE</version>
</dependency>
Configuration R2DBC Database Connection

spring.r2dbc.url=r2dbc:mysql://localhost:3306/karunya
spring.r2dbc.username=root
spring.r2dbc.password=
Create Employee class
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;
@Table
public class Employee {
@Id
private int id;
private String name;
private int salary;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
Create EmployeeRepository interface
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface EmployeeRepository extends ReactiveCrudRepository<Employee, Integer>
{

ReactiveCrudRepository<Employee, Integer>
• Interface for create, read, update, delete operations on a repository for a
specific table.
• This repository follows reactive paradigms and uses Project Reactor types
which are built on top of Reactive Streams.
Create Rest Controller
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RestController
public class EmployeeController {

@Autowired
private EmployeeRepository employeeRepository;

@GetMapping("/getAll")
public Flux<Employee> getAllEmployees(){
Flux<Employee> fluxdata = employeeRepository.findAll();
return fluxdata;
}

@GetMapping("/getEmployee/{id}")
public Mono<Employee> findEmployee(@PathVariable int id)
{
Mono<Employee> monodata = employeeRepository.findById(id);
return monodata;
}
@PostMapping("/addNewEmployee")
public Mono<Employee> createEmployee(@RequestBody Employee emp){
return employeeRepository.save(emp);
}

@DeleteMapping("/deleteEmployee/{id}")
public Mono<Void> removeEmployee(@PathVariable int id){
return employeeRepository.deleteById(id);
}
}
Test API http://localhost:8080/getAll
http://localhost:8080/getEmployee/103
http://localhost:8080/addNewEmployee
http://localhost:8080/deleteEmployee/221
Consuming REST APIs reactively
Using WebClient
WebClient
 Spring 5 offers WebClient as a reactive alternative to RestTemplate.
 WebClient lets you both send and receive reactive types when
making requests to external APIs asynchronously.
 How to use WebClient?
 Create an instance of WebClient (or inject a WebClient bean)
 Specify the HTTP method of the request to send
 Specify the URI and any headers that should be in the request
 Submit the request
 Consume the response
WebClient class Methods
 get()
 To fetch either collection of resources (Flux) or a singular resource
(Mono).
 post()
 Used for creating a new data (Mono) in a table
 put()
 Used for updating existing data (Mono) in a table
 delete()
 Used for deleting existing data (Mono) in a table
@Table
public class Employee {
@Id
private int id;
private String name;
private int salary;

public int getId() {


return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
Add toString() method to display the Employee details
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
@Override
public String toString() {
return "ID: "+id+",Name: " + name + ",Salary: " + salary;
}
}
Consume Reactive Rest API - GET
 To find a particular Employee with id
 Generally, we will use GET API to fetch either collection of resources or a singular resource.
 HTTP GET /employees/{id} : single employee by id as Mono

import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
public class ConsumeAPIDemo {
public void findEmployee() {
WebClient webclient = WebClient.create();
Mono<Employee> monoemp = webclient.get()
.uri("http://localhost:8080/getEmployee/{id}",222)
.retrieve()
.bodyToMono(Employee.class);
monoemp.subscribe(System.out :: println);
}
}
For Testing
 Call the function from main method

@SpringBootApplication
public class TestReactiveApplication {
public static void main(String[] args) {
new ConsumeAPIDemo().findEmployee();
SpringApplication.run(TestReactiveApplication.class, args);
}
}
Consume Reactive Rest API - GET
 To view all the Employees
 Generally, we will use GET API to fetch either collection of resources or a singular resource.
 HTTP GET /employees : collection of employees as Flux

import org.springframework.web.reactive.function.client.WebClient;

import reactor.core.publisher.Flux;

public class ConsumeAPIDemo {


public void viewAll() {
WebClient webclient = WebClient.create();
Flux<Employee> fluxemp = webclient.get()
.uri("http://localhost:8080/getAll")
.retrieve()
.bodyToFlux(Employee.class);
fluxemp.subscribe(System.out :: println);
}
}
To view all the Employees - output
 HTTP GET /employees : collection of employees as Flux
Consume Reactive Rest API - POST
 To store new Employee details
 POST API is commonly used for creating a resource.
 HTTP POST /employees : creates a new employee from request body and returns the created employee in
response. WebClient’s post() method is used for save new employee details
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
public class ConsumeAPIDemo {
public void save() {
WebClient webclient = WebClient.create();
Employee emp = new Employee();
//id is auto incremented
emp.setName("Tim");
emp.setSalary(80000);
Mono<Employee> monoemp = webclient.post()
.uri("http://localhost:8080/addNewEmployee")
.body(Mono.just(emp), Employee.class)
.retrieve()
.bodyToMono(Employee.class);
monoemp.subscribe(System.out :: println);
}
}
Consume Reactive Rest API - DELETE
 To delete an existing Employee details
 DELETE API is commonly used for deleting a resource.
 HTTP DELETE /employees/{id} : deletes an existing employee by its id. It does not accept any
request body as well as does not return any response body as well.
 WebClient’s delete() method is used for save new employee details

import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

public class ConsumeAPIDemo {


public void delete() {
WebClient webclient = WebClient.create();
Mono<Void> nothing = webclient.delete()
.uri("http://localhost:8080/deleteEmployee/{id}",253)
.retrieve()
.bodyToMono(Void.class);
Mono<String> status = Mono.just("Employee Details Deleted");
status.subscribe(System.out :: println);
}
}

You might also like