SlideShare une entreprise Scribd logo
1  sur  36
Télécharger pour lire hors ligne
R2DBC = R2D2 + JDBC
(enfin presque…)
Bruno Bonnin
#DevoxxMA
Rejoignez-nous: https://www.kereis.com/nous-rejoindre/
UN SYSTEME REACTIF…
UN PEU D’HISTOIRE…
Reactive
Manifesto
2009 2011 2013
Reactive
Streams
2015 2018
2017
ReactiveX
Spring
Webflux
JDK 9
RxJava
Project Reactor
(v2 avec Reactive Streams)
Driver Java v2
2019
Spring Data
R2DBC
R2DBC
2022
R2DBC v1.0
REACTIVE
STREAMS
The purpose of Reactive Streams is to provide a standard for
asynchronous stream processing with non-blocking backpressure.
“
”
REACTIVE STREAMS
REACTIVE STREAMS
Des principes
Reactive Manifesto
Des API
Subscriber, Publisher
Des implémentations
Reactor, RxJava, …
Publisher
Subscriber
1. subscribe
3. request(n) / cancel
2. onSubscribe (subscription)
4. onNext(data 1)
5. onComplete / onError
REACTIVE STREAMS API
Subscription
4. onNext(data …)
4. onNext(data n)
La source des
données
Le
consommateur
des données
IMPLÉMENTATION AVEC PROJET REACTOR
// Publisher de 0 à 1 élément
public abstract class Mono<T>
implements CorePublisher<T> {}
Flux.just("Hello", "How", "Are", "You?")
.doOnNext(System.out::println) // Data consumer
.doOnError(exc -> System.err.println("😭" + exc)) // Error consumer
.doOnComplete(() -> System.out.println("🎉")) // Complete consumer
.subscribe();
// Publisher de 0 à n éléments
public abstract class Flux<T>
implements CorePublisher<T> {}
Base de
données
Application
1. subscribe
3. request(n) / cancel
2. onSubscribe (subscription)
4. onNext(“R2D2”)
5. onComplete / onError
ET SI C’ETAIT UNE REQUETE…
Subscription
4. onNext(“C3PO”)
4. onNext(“BB-8”)
SELECT name FROM robot
REACTIVE API ET BASE DE DONNÉES
Driver Java v2
X DevAPI
(CompletableFuture)
SqlClient
ADBA
JDBC Reactive Extension
Reactive Driver
R2DBC
Reactive Relational
Database Connectivity
Définit une interface standard de
programmation réactive basée
sur les Reactive Streams,
destinée aux interactions avec
les bases de données
relationnelles. Reactive Streams
R2DBC SPI
R2DBC Driver X
ConnectionFactory connectionFactory =
ConnectionFactories.get("r2dbc:h2:mem:///robot_db");
R2DBC + REACTIVE STREAMS + PROJECT REACTOR = ❤
Publisher<? extends Connection> connectionPublisher = connectionFactory.create();
Mono.from(connectionPublisher)
.flatMapMany(connection -> connection
.createStatement("SELECT * FROM robot WHERE name = $1")
.bind("$1", "R2-D2")
.execute())
.flatMap(result -> result.map((row, metadata) -> /* … */))
.doOnNext(data -> …) // Traitement donnée
.doOnError(exc -> …) // Traitement erreur
.doOnComplete(() -> …) // Traitement fin
.subscribe(); // Lancement du traitement
SPRING DATA R2DBC
UN PEU DE DÉPENDANCES POUR
COMMENCER…
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
</dependency>
spring:
r2dbc:
url: r2dbc:postgresql://localhost:15432/robot_db
username: king_of_salsa
password: un_truc_hyper_compliqué_noté_sur_un_postit
…ET UN PEU DE
CONFIGURATION…
DatabaseClient databaseClient =
DatabaseClient.create(connectionFactory);
Flux<Robot> robots = databaseClient
.sql("SELECT * FROM robot WHERE name = :name")
.bind("name", name)
.map(row -> …)
.all();
CLASSE DatabaseClient
Flux<Robot> robots = r2dbcEntityTemplate
.select(Robot.class)
.from("robot")
.matching(query(where("name").is(name)))
.all();
Flux<Robot> robots = r2dbcEntityTemplate
.select(
query(where("name").is(name)),
Robot.class);
CLASSE R2dbcEntityTemplate
public interface RobotRepository
extends ReactiveCrudRepository<Robot, Long> {
Flux<Robot> findByName(String name);
@Query("select distinct movie from robot")
Flux<String> getMovies();
}
CLASSE Reactive***Repository
@Transactional
public Mono<Void> create(Robot robot, Movie movie) {
return robotRepository.save(robot)
.then(movieRepository.save(movie))
.then();
}
ET AVEC UN ZESTE DE TRANSACTION!
public Mono<Void> create(Robot robot, Movie movie) {
TransactionalOperator rxtx = TransactionalOperator.create(reactiveTxManager );
return robotRepository.save(robot)
.then(movieRepository.save(movie))
.then()
.as(rxtx::transactional);
}
ECO-SYSTEME
ÉCOSYSTÈME - DRIVERS
ÉCOSYSTÈME - CLIENTS
R2DBC PROXY
Librairie fournissant des callbacks
permettant d’accéder à l’exécution
des requêtes, pour:
- logging,
- métriques,
- traçage distribué,
- … R2DBC Driver
R2DBC Proxy
Application
R2DBC ET MULTI-TENANCY
Comment gérer plusieurs connexions selon un
contexte d’exécution ?
- AbstractR2dbcRouting : configuration des
différentes connexions
- AbstractRoutingConnectionFactory : fournit la
clé de sélection de la connexion
PROJET LOOM
JAVA ET LES THREADS
1996
Java 1
Thread, Runnable
2004
Java 5
java.util.concurrent
Callable, Future
Lock, Semaphore
2011
Java 7
ForkJoinTask
2014
Java 8
CompletableFuture
CompletionStage
2023
Java 21
Virtual threads
(preview depuis
v19)
LOOM VA TUER LA PROGRAMMATION
REACTIVE ?
Movie getRobotFirstMovie(String robotName) {
Robot robot = repository.findRobotByName(robotName);
Movie movie = repository.findMovieById(robot.firstMovie);
return movie;
}
Movie getRobotFirstMovie(String robotName) {
CompletableFuture<Robot> robotFuture = CompletableFuture
.supplyAsync(() -> repository.findRobotByName(robotName));
CompletableFuture<Movie> movieFuture = robotFuture
.thenApplyAsync(robot -> repository.findMovieById(robot.firstMovie));
return movieFuture.get();
}
Mono<Movie> getFirstMovie(String robotName) {
return repository.findRobotByName(robotName)
.flatMap(robot -> repository.findMovieById(robot.firstMovie))
…. // Pleins de traitement: log, zip, map, …
.onErrorReturn(new Movie("Star Wars IV"));
}
?
@RunOnVirtualThread
LOOM VA TUER LA PROGRAMMATION
REACTIVE ?
Peut-être… ou pas
EN RÉSUMÉ …
Qu’a-t-on vu ?
- Initiative plus qu’intéressante pour standardiser l’accès aux bases de
données relationnelles en mode réactif
- Il y a aussi des transactions, du batch, des entity callbacks, de
l’observability, …
- Support de la communauté (clients, drivers, …)
- On peut faire du R2DBC sans aucun autre framework, mais ça va être
un peu roots :)
Mais il reste du boulot !
- Des frameworks en cours de mises à jour (Liquibase, …)
- Spring : pas de support des relations dans les entités :(
MERCI !
Démos: https://github.com/bbonnin/intro-r2dbc
Images: https://duotone.shapefactory.co/
BACKUP SLIDES
AVEC CONTENU
D’UN SYSTÈME SYNCHRONE ET
BLOQUANT…
Thread de traitement Thread bloqué !
Worker
thread
Hyper simplifié :)
Poursuite du traitement
… À UN SYSTÈME ASYNCHRONE ET
NON BLOQUANT !
Traitement d’une requête
Événement (tâche à réaliser avec
callback)
Invocation callback
Event loop
Traitement tâche
Modèle “Event Loop”
Événement
(résultat traitement tâche)
Worker
threads

Contenu connexe

Similaire à [Devoxx MA 2023] R2DBC = R2D2 + JDBC (enfin presque...)

ACRA - Présentation PAUG Avril 2011
ACRA - Présentation PAUG Avril 2011ACRA - Présentation PAUG Avril 2011
ACRA - Présentation PAUG Avril 2011Kevin Gaudin
 
ASP.NET Futures
ASP.NET FuturesASP.NET Futures
ASP.NET Futuresloicbar
 
Asp.Net Futures
Asp.Net FuturesAsp.Net Futures
Asp.Net Futuresloicbar
 
Flex, une techno RIA incontournable pour les futures app web ?
Flex, une techno RIA incontournable pour les futures app web ?Flex, une techno RIA incontournable pour les futures app web ?
Flex, une techno RIA incontournable pour les futures app web ?GreenIvory
 
GWT : under the hood
GWT : under the hoodGWT : under the hood
GWT : under the hoodsvuillet
 
Introduction à Angularjs
Introduction à AngularjsIntroduction à Angularjs
Introduction à AngularjsRossi Oddet
 
Cours PHP PDO intégrale afin de mieux appréhender la nouvelle librairie
Cours PHP PDO intégrale afin de mieux appréhender la nouvelle librairieCours PHP PDO intégrale afin de mieux appréhender la nouvelle librairie
Cours PHP PDO intégrale afin de mieux appréhender la nouvelle librairieafdoumbia
 
Ou sont mes beans, contrats et workflows ? WOA et REST: Un changement de ment...
Ou sont mes beans, contrats et workflows ? WOA et REST: Un changement de ment...Ou sont mes beans, contrats et workflows ? WOA et REST: Un changement de ment...
Ou sont mes beans, contrats et workflows ? WOA et REST: Un changement de ment...Jean-Laurent de Morlhon
 
Linq et Entity framework
Linq et Entity frameworkLinq et Entity framework
Linq et Entity frameworkDNG Consulting
 
Tableau de bord Yammer sous SharePoint 2013
Tableau de bord Yammer sous SharePoint 2013Tableau de bord Yammer sous SharePoint 2013
Tableau de bord Yammer sous SharePoint 2013Philippe Sfeir
 
Au secours, mon chef m'a demandé de passer au DevOps
Au secours, mon chef m'a demandé de passer au DevOpsAu secours, mon chef m'a demandé de passer au DevOps
Au secours, mon chef m'a demandé de passer au DevOpsantony_guilloteau
 
Des mises à jour? Emmenez votre application Stitch encore plus loin grâce aux...
Des mises à jour? Emmenez votre application Stitch encore plus loin grâce aux...Des mises à jour? Emmenez votre application Stitch encore plus loin grâce aux...
Des mises à jour? Emmenez votre application Stitch encore plus loin grâce aux...MongoDB
 
Quelle place pour le framework Rails dans le développement d'application web
Quelle place pour le framework Rails dans le développement d'application webQuelle place pour le framework Rails dans le développement d'application web
Quelle place pour le framework Rails dans le développement d'application web5pidou
 
react-slides.ppx (2) (1).pptx react presentation basic
react-slides.ppx (2) (1).pptx react presentation basicreact-slides.ppx (2) (1).pptx react presentation basic
react-slides.ppx (2) (1).pptx react presentation basiczineblahib2
 

Similaire à [Devoxx MA 2023] R2DBC = R2D2 + JDBC (enfin presque...) (20)

ACRA - Présentation PAUG Avril 2011
ACRA - Présentation PAUG Avril 2011ACRA - Présentation PAUG Avril 2011
ACRA - Présentation PAUG Avril 2011
 
ASP.NET Futures
ASP.NET FuturesASP.NET Futures
ASP.NET Futures
 
Asp.Net Futures
Asp.Net FuturesAsp.Net Futures
Asp.Net Futures
 
react-fr.pdf
react-fr.pdfreact-fr.pdf
react-fr.pdf
 
Flex, une techno RIA incontournable pour les futures app web ?
Flex, une techno RIA incontournable pour les futures app web ?Flex, une techno RIA incontournable pour les futures app web ?
Flex, une techno RIA incontournable pour les futures app web ?
 
GWT : under the hood
GWT : under the hoodGWT : under the hood
GWT : under the hood
 
HTML5 en projet
HTML5 en projetHTML5 en projet
HTML5 en projet
 
Introduction à Angularjs
Introduction à AngularjsIntroduction à Angularjs
Introduction à Angularjs
 
Cours PHP PDO intégrale afin de mieux appréhender la nouvelle librairie
Cours PHP PDO intégrale afin de mieux appréhender la nouvelle librairieCours PHP PDO intégrale afin de mieux appréhender la nouvelle librairie
Cours PHP PDO intégrale afin de mieux appréhender la nouvelle librairie
 
2016_js_react.pdf
2016_js_react.pdf2016_js_react.pdf
2016_js_react.pdf
 
Ou sont mes beans, contrats et workflows ? WOA et REST: Un changement de ment...
Ou sont mes beans, contrats et workflows ? WOA et REST: Un changement de ment...Ou sont mes beans, contrats et workflows ? WOA et REST: Un changement de ment...
Ou sont mes beans, contrats et workflows ? WOA et REST: Un changement de ment...
 
Linq et Entity framework
Linq et Entity frameworkLinq et Entity framework
Linq et Entity framework
 
iTunes Stats
iTunes StatsiTunes Stats
iTunes Stats
 
Support Java Avancé Troisième Partie
Support Java Avancé Troisième PartieSupport Java Avancé Troisième Partie
Support Java Avancé Troisième Partie
 
Tableau de bord Yammer sous SharePoint 2013
Tableau de bord Yammer sous SharePoint 2013Tableau de bord Yammer sous SharePoint 2013
Tableau de bord Yammer sous SharePoint 2013
 
Au secours, mon chef m'a demandé de passer au DevOps
Au secours, mon chef m'a demandé de passer au DevOpsAu secours, mon chef m'a demandé de passer au DevOps
Au secours, mon chef m'a demandé de passer au DevOps
 
Des mises à jour? Emmenez votre application Stitch encore plus loin grâce aux...
Des mises à jour? Emmenez votre application Stitch encore plus loin grâce aux...Des mises à jour? Emmenez votre application Stitch encore plus loin grâce aux...
Des mises à jour? Emmenez votre application Stitch encore plus loin grâce aux...
 
Quelle place pour le framework Rails dans le développement d'application web
Quelle place pour le framework Rails dans le développement d'application webQuelle place pour le framework Rails dans le développement d'application web
Quelle place pour le framework Rails dans le développement d'application web
 
react-slides.ppx (2) (1).pptx react presentation basic
react-slides.ppx (2) (1).pptx react presentation basicreact-slides.ppx (2) (1).pptx react presentation basic
react-slides.ppx (2) (1).pptx react presentation basic
 
1145709.ppt
1145709.ppt1145709.ppt
1145709.ppt
 

Plus de Bruno Bonnin

Stream processing avec Apache Pulsar
Stream processing avec Apache PulsarStream processing avec Apache Pulsar
Stream processing avec Apache PulsarBruno Bonnin
 
Stream processing et SQL
Stream processing et SQLStream processing et SQL
Stream processing et SQLBruno Bonnin
 
Stream processing et SQL
Stream processing et SQLStream processing et SQL
Stream processing et SQLBruno Bonnin
 
Guide (un tout petit peu) pratique (et totalement subjectif) du stream proces...
Guide (un tout petit peu) pratique (et totalement subjectif) du stream proces...Guide (un tout petit peu) pratique (et totalement subjectif) du stream proces...
Guide (un tout petit peu) pratique (et totalement subjectif) du stream proces...Bruno Bonnin
 
Stream processing et SQL
Stream processing et SQLStream processing et SQL
Stream processing et SQLBruno Bonnin
 
Stream processing et SQL
Stream processing et SQLStream processing et SQL
Stream processing et SQLBruno Bonnin
 
Jug summer camp 2017 - Vue.js, même un dev java peut en faire !
Jug summer camp 2017 - Vue.js, même un dev java peut en faire !Jug summer camp 2017 - Vue.js, même un dev java peut en faire !
Jug summer camp 2017 - Vue.js, même un dev java peut en faire !Bruno Bonnin
 
A la découverte de vue.js
A la découverte de vue.jsA la découverte de vue.js
A la découverte de vue.jsBruno Bonnin
 
Vue.js, même un dev java peut en faire !
Vue.js, même un dev java peut en faire !Vue.js, même un dev java peut en faire !
Vue.js, même un dev java peut en faire !Bruno Bonnin
 
Explorez vos données présentes dans MongoDB avec Apache Zeppelin
Explorez vos données présentes dans MongoDB avec Apache ZeppelinExplorez vos données présentes dans MongoDB avec Apache Zeppelin
Explorez vos données présentes dans MongoDB avec Apache ZeppelinBruno Bonnin
 
Vue, j’avais pas vu !
Vue, j’avais pas vu !Vue, j’avais pas vu !
Vue, j’avais pas vu !Bruno Bonnin
 
Apache Spark avec NodeJS ? Oui, c'est possible avec EclairJS !
Apache Spark avec NodeJS ? Oui, c'est possible avec EclairJS !Apache Spark avec NodeJS ? Oui, c'est possible avec EclairJS !
Apache Spark avec NodeJS ? Oui, c'est possible avec EclairJS !Bruno Bonnin
 
Big Data Viz (and much more!) with Apache Zeppelin
Big Data Viz (and much more!) with Apache ZeppelinBig Data Viz (and much more!) with Apache Zeppelin
Big Data Viz (and much more!) with Apache ZeppelinBruno Bonnin
 
Tout ce que le getting started mongodb ne vous dira pas
Tout ce que le getting started mongodb ne vous dira pasTout ce que le getting started mongodb ne vous dira pas
Tout ce que le getting started mongodb ne vous dira pasBruno Bonnin
 
Explorez vos données avec apache zeppelin
Explorez vos données avec apache zeppelinExplorez vos données avec apache zeppelin
Explorez vos données avec apache zeppelinBruno Bonnin
 
Tout ce que le getting started MongoDB ne vous dira pas
Tout ce que le getting started MongoDB ne vous dira pasTout ce que le getting started MongoDB ne vous dira pas
Tout ce que le getting started MongoDB ne vous dira pasBruno Bonnin
 
MUG Nantes - MongoDB et son connecteur pour hadoop
MUG Nantes - MongoDB et son connecteur pour hadoopMUG Nantes - MongoDB et son connecteur pour hadoop
MUG Nantes - MongoDB et son connecteur pour hadoopBruno Bonnin
 
Breizhcamp 2015 - Comment (ne pas réussir à) modéliser ses data dans elastics...
Breizhcamp 2015 - Comment (ne pas réussir à) modéliser ses data dans elastics...Breizhcamp 2015 - Comment (ne pas réussir à) modéliser ses data dans elastics...
Breizhcamp 2015 - Comment (ne pas réussir à) modéliser ses data dans elastics...Bruno Bonnin
 

Plus de Bruno Bonnin (18)

Stream processing avec Apache Pulsar
Stream processing avec Apache PulsarStream processing avec Apache Pulsar
Stream processing avec Apache Pulsar
 
Stream processing et SQL
Stream processing et SQLStream processing et SQL
Stream processing et SQL
 
Stream processing et SQL
Stream processing et SQLStream processing et SQL
Stream processing et SQL
 
Guide (un tout petit peu) pratique (et totalement subjectif) du stream proces...
Guide (un tout petit peu) pratique (et totalement subjectif) du stream proces...Guide (un tout petit peu) pratique (et totalement subjectif) du stream proces...
Guide (un tout petit peu) pratique (et totalement subjectif) du stream proces...
 
Stream processing et SQL
Stream processing et SQLStream processing et SQL
Stream processing et SQL
 
Stream processing et SQL
Stream processing et SQLStream processing et SQL
Stream processing et SQL
 
Jug summer camp 2017 - Vue.js, même un dev java peut en faire !
Jug summer camp 2017 - Vue.js, même un dev java peut en faire !Jug summer camp 2017 - Vue.js, même un dev java peut en faire !
Jug summer camp 2017 - Vue.js, même un dev java peut en faire !
 
A la découverte de vue.js
A la découverte de vue.jsA la découverte de vue.js
A la découverte de vue.js
 
Vue.js, même un dev java peut en faire !
Vue.js, même un dev java peut en faire !Vue.js, même un dev java peut en faire !
Vue.js, même un dev java peut en faire !
 
Explorez vos données présentes dans MongoDB avec Apache Zeppelin
Explorez vos données présentes dans MongoDB avec Apache ZeppelinExplorez vos données présentes dans MongoDB avec Apache Zeppelin
Explorez vos données présentes dans MongoDB avec Apache Zeppelin
 
Vue, j’avais pas vu !
Vue, j’avais pas vu !Vue, j’avais pas vu !
Vue, j’avais pas vu !
 
Apache Spark avec NodeJS ? Oui, c'est possible avec EclairJS !
Apache Spark avec NodeJS ? Oui, c'est possible avec EclairJS !Apache Spark avec NodeJS ? Oui, c'est possible avec EclairJS !
Apache Spark avec NodeJS ? Oui, c'est possible avec EclairJS !
 
Big Data Viz (and much more!) with Apache Zeppelin
Big Data Viz (and much more!) with Apache ZeppelinBig Data Viz (and much more!) with Apache Zeppelin
Big Data Viz (and much more!) with Apache Zeppelin
 
Tout ce que le getting started mongodb ne vous dira pas
Tout ce que le getting started mongodb ne vous dira pasTout ce que le getting started mongodb ne vous dira pas
Tout ce que le getting started mongodb ne vous dira pas
 
Explorez vos données avec apache zeppelin
Explorez vos données avec apache zeppelinExplorez vos données avec apache zeppelin
Explorez vos données avec apache zeppelin
 
Tout ce que le getting started MongoDB ne vous dira pas
Tout ce que le getting started MongoDB ne vous dira pasTout ce que le getting started MongoDB ne vous dira pas
Tout ce que le getting started MongoDB ne vous dira pas
 
MUG Nantes - MongoDB et son connecteur pour hadoop
MUG Nantes - MongoDB et son connecteur pour hadoopMUG Nantes - MongoDB et son connecteur pour hadoop
MUG Nantes - MongoDB et son connecteur pour hadoop
 
Breizhcamp 2015 - Comment (ne pas réussir à) modéliser ses data dans elastics...
Breizhcamp 2015 - Comment (ne pas réussir à) modéliser ses data dans elastics...Breizhcamp 2015 - Comment (ne pas réussir à) modéliser ses data dans elastics...
Breizhcamp 2015 - Comment (ne pas réussir à) modéliser ses data dans elastics...
 

[Devoxx MA 2023] R2DBC = R2D2 + JDBC (enfin presque...)

  • 1. R2DBC = R2D2 + JDBC (enfin presque…) Bruno Bonnin #DevoxxMA
  • 4. UN PEU D’HISTOIRE… Reactive Manifesto 2009 2011 2013 Reactive Streams 2015 2018 2017 ReactiveX Spring Webflux JDK 9 RxJava Project Reactor (v2 avec Reactive Streams) Driver Java v2 2019 Spring Data R2DBC R2DBC 2022 R2DBC v1.0
  • 6. The purpose of Reactive Streams is to provide a standard for asynchronous stream processing with non-blocking backpressure. “ ” REACTIVE STREAMS
  • 7. REACTIVE STREAMS Des principes Reactive Manifesto Des API Subscriber, Publisher Des implémentations Reactor, RxJava, …
  • 8. Publisher Subscriber 1. subscribe 3. request(n) / cancel 2. onSubscribe (subscription) 4. onNext(data 1) 5. onComplete / onError REACTIVE STREAMS API Subscription 4. onNext(data …) 4. onNext(data n) La source des données Le consommateur des données
  • 9. IMPLÉMENTATION AVEC PROJET REACTOR // Publisher de 0 à 1 élément public abstract class Mono<T> implements CorePublisher<T> {} Flux.just("Hello", "How", "Are", "You?") .doOnNext(System.out::println) // Data consumer .doOnError(exc -> System.err.println("😭" + exc)) // Error consumer .doOnComplete(() -> System.out.println("🎉")) // Complete consumer .subscribe(); // Publisher de 0 à n éléments public abstract class Flux<T> implements CorePublisher<T> {}
  • 10. Base de données Application 1. subscribe 3. request(n) / cancel 2. onSubscribe (subscription) 4. onNext(“R2D2”) 5. onComplete / onError ET SI C’ETAIT UNE REQUETE… Subscription 4. onNext(“C3PO”) 4. onNext(“BB-8”) SELECT name FROM robot
  • 11. REACTIVE API ET BASE DE DONNÉES Driver Java v2 X DevAPI (CompletableFuture) SqlClient ADBA JDBC Reactive Extension Reactive Driver
  • 13. Définit une interface standard de programmation réactive basée sur les Reactive Streams, destinée aux interactions avec les bases de données relationnelles. Reactive Streams R2DBC SPI R2DBC Driver X
  • 14. ConnectionFactory connectionFactory = ConnectionFactories.get("r2dbc:h2:mem:///robot_db"); R2DBC + REACTIVE STREAMS + PROJECT REACTOR = ❤ Publisher<? extends Connection> connectionPublisher = connectionFactory.create(); Mono.from(connectionPublisher) .flatMapMany(connection -> connection .createStatement("SELECT * FROM robot WHERE name = $1") .bind("$1", "R2-D2") .execute()) .flatMap(result -> result.map((row, metadata) -> /* … */)) .doOnNext(data -> …) // Traitement donnée .doOnError(exc -> …) // Traitement erreur .doOnComplete(() -> …) // Traitement fin .subscribe(); // Lancement du traitement
  • 16. UN PEU DE DÉPENDANCES POUR COMMENCER… <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-r2dbc</artifactId> </dependency>
  • 17. spring: r2dbc: url: r2dbc:postgresql://localhost:15432/robot_db username: king_of_salsa password: un_truc_hyper_compliqué_noté_sur_un_postit …ET UN PEU DE CONFIGURATION…
  • 18. DatabaseClient databaseClient = DatabaseClient.create(connectionFactory); Flux<Robot> robots = databaseClient .sql("SELECT * FROM robot WHERE name = :name") .bind("name", name) .map(row -> …) .all(); CLASSE DatabaseClient
  • 19. Flux<Robot> robots = r2dbcEntityTemplate .select(Robot.class) .from("robot") .matching(query(where("name").is(name))) .all(); Flux<Robot> robots = r2dbcEntityTemplate .select( query(where("name").is(name)), Robot.class); CLASSE R2dbcEntityTemplate
  • 20. public interface RobotRepository extends ReactiveCrudRepository<Robot, Long> { Flux<Robot> findByName(String name); @Query("select distinct movie from robot") Flux<String> getMovies(); } CLASSE Reactive***Repository
  • 21. @Transactional public Mono<Void> create(Robot robot, Movie movie) { return robotRepository.save(robot) .then(movieRepository.save(movie)) .then(); } ET AVEC UN ZESTE DE TRANSACTION! public Mono<Void> create(Robot robot, Movie movie) { TransactionalOperator rxtx = TransactionalOperator.create(reactiveTxManager ); return robotRepository.save(robot) .then(movieRepository.save(movie)) .then() .as(rxtx::transactional); }
  • 24.
  • 26. R2DBC PROXY Librairie fournissant des callbacks permettant d’accéder à l’exécution des requêtes, pour: - logging, - métriques, - traçage distribué, - … R2DBC Driver R2DBC Proxy Application
  • 27. R2DBC ET MULTI-TENANCY Comment gérer plusieurs connexions selon un contexte d’exécution ? - AbstractR2dbcRouting : configuration des différentes connexions - AbstractRoutingConnectionFactory : fournit la clé de sélection de la connexion
  • 29. JAVA ET LES THREADS 1996 Java 1 Thread, Runnable 2004 Java 5 java.util.concurrent Callable, Future Lock, Semaphore 2011 Java 7 ForkJoinTask 2014 Java 8 CompletableFuture CompletionStage 2023 Java 21 Virtual threads (preview depuis v19)
  • 30. LOOM VA TUER LA PROGRAMMATION REACTIVE ? Movie getRobotFirstMovie(String robotName) { Robot robot = repository.findRobotByName(robotName); Movie movie = repository.findMovieById(robot.firstMovie); return movie; } Movie getRobotFirstMovie(String robotName) { CompletableFuture<Robot> robotFuture = CompletableFuture .supplyAsync(() -> repository.findRobotByName(robotName)); CompletableFuture<Movie> movieFuture = robotFuture .thenApplyAsync(robot -> repository.findMovieById(robot.firstMovie)); return movieFuture.get(); } Mono<Movie> getFirstMovie(String robotName) { return repository.findRobotByName(robotName) .flatMap(robot -> repository.findMovieById(robot.firstMovie)) …. // Pleins de traitement: log, zip, map, … .onErrorReturn(new Movie("Star Wars IV")); } ? @RunOnVirtualThread
  • 31. LOOM VA TUER LA PROGRAMMATION REACTIVE ? Peut-être… ou pas
  • 32. EN RÉSUMÉ … Qu’a-t-on vu ? - Initiative plus qu’intéressante pour standardiser l’accès aux bases de données relationnelles en mode réactif - Il y a aussi des transactions, du batch, des entity callbacks, de l’observability, … - Support de la communauté (clients, drivers, …) - On peut faire du R2DBC sans aucun autre framework, mais ça va être un peu roots :) Mais il reste du boulot ! - Des frameworks en cours de mises à jour (Liquibase, …) - Spring : pas de support des relations dans les entités :(
  • 35. D’UN SYSTÈME SYNCHRONE ET BLOQUANT… Thread de traitement Thread bloqué ! Worker thread Hyper simplifié :) Poursuite du traitement
  • 36. … À UN SYSTÈME ASYNCHRONE ET NON BLOQUANT ! Traitement d’une requête Événement (tâche à réaliser avec callback) Invocation callback Event loop Traitement tâche Modèle “Event Loop” Événement (résultat traitement tâche) Worker threads