SlideShare a Scribd company logo
The Making of the Oracle R2DBC Driver
And How to Take Your Code from Synchronous to Reactive
Kuassi Mensah Michael McMahon
@kmensah
Agenda
ü Once Upon a Time
• The Making of Oracle R2DBC driver
• Taking Your Code from Synchronous to Reactive
Oracle Confidential
Once Upon a Time …
The Asynchronous Database Access API (ADBA)
• Started in 2017
• Goal
– A standard Java database access API that never blocks user threads
– No compatibility or complementarity with JDBC
• Motivations
– Asynchronous apps have better throughput
– Simultaneous access to multiple databases, e.g. map/reduce, sharded databases
– Fire and forget, e.g. DML, stored procedures
• The API is available from OpenJDK at https://bit.ly/3t3nkAd
3
1. Per the Java SE team: “the future of Java scalability is Virtual
Threads”
–ADBA would not be accepted as a Java standard as it was an
async solution to a problem that would be addressed by virtual
threads.
– Unless it became a standard ADBA would have very little
impact, certainly not enough to justify the effort.
2. There was very little support within the Java community.
-- Gravitating towards R2DBC
4
Why Did We Stop Working on ADBA?
We changed our focus towards
• JDBC Reactive Extensions
• An Oracle R2DBC Driver
• Instrumenting the JDBC driver to support Virtual Threads
5
Then What?
SQL Execution (OraclePreparedStatement):
Publisher<Boolean> executeAsyncOracle()
Publisher<Long> executeUpdateAsyncOracle()
Publisher<Long> executeBatchAsyncOracle()
Publisher<OracleResultSet> executeQueryAsyncOracle()
Row Fetching (OracleResultSet):
Publisher<T> publisherOracle(Function<OracleRow, T> f)
LOB I/O (OracleBlob):
Publisher<byte[]> publisherOracle(long position)
Subscriber<byte[]> subscriberOracle(long position)
LOB I/O (OracleClob):
Publisher<String> publisherOracle(long position)
Subscriber<String> subscriberOracle(long position)
Connection Closing (OracleConnection):
Publisher<Success> closeAsyncOracle()
Transaction Closing (OracleConnection):
Publisher<Success> commitAsyncOracle()
Publisher<Success> rollbackAsyncOracle()
Connection Creation (OracleConnectionBuilder):
Publisher<OracleConnection> buildConnectionPublisherOracle()
JDBC Reactive Extensions (built into the driver)
User
Java
Code
JDBC
Reactive
Extension Standard
JDBC
API
3rd party
Reactive
Streams
Libraries
Async call with non-blocking
backpressure
operators (map, reduce, filters),
concurrency modeling,
monitoring, tracing
Implements Java SE
reactive stream
interface (Flow)
Full Reactive
Streams
Sync/blocking JDBC calls
Java
Business
Logic
User Java code
Oracle
Database
Oracle JDBC
driver
Summary of Oracle DB Access with Java – Part 1
Agenda
• Once Upon a Time
ü The Making of Oracle R2DBC driver
• Taking Your Code from Synchronous to Reactive
Oracle Confidential
public boolean execute() throws SQLException {
// Check if this statement is closed
if (isClosed)
throw new SQLException("Closed Statement");
// Check if all bind values are set
for (Object bindValue : bindValues) {
if (bindValue == null)
throw new SQLException("Bind value not set");
}
// Close the current ResultSet
if (resultSet != null)
resultSet.close();
// Reset the current update count
updateCount = -1;
// Blocking database call
SqlResult sqlResult = jdbcConnection.executeSql(sql, bindValues);
// Handle the result
resultSet = sqlResult.getResultSet();
updateCount = sqlResult.getUpdateCount();
return resultSet != null;
}
public Publisher<Boolean> executeAsyncOracle() throws SQLException {
// Check if this statement is closed
if (isClosed)
throw new SQLException("Closed Statement");
// Check if all bind values are set
for (Object bindValue : bindValues) {
if (bindValue == null)
throw new SQLException("Bind value not set");
}
// Close the current ResultSet
if (resultSet != null)
resultSet.close();
// Reset the current update count
updateCount = -1;
// Non-blocking database call
return Flux.from(jdbcConnection.executeSqlAsync(sql, bindValues))
.map(sqlResult -> {
// Handle the result
resultSet = sqlResult.getResultSet();
updateCount = sqlResult.getUpdateCount();
return resultSet != null;
});
}
Developing JDBC Reactive Extensions
public boolean execute() throws SQLException {
// Check if this statement is closed
if (isClosed)
throw new SQLException("Closed Statement");
// Check if all bind values are set
for (Object bindValue : bindValues) {
if (bindValue == null)
throw new SQLException("Bind value not set");
}
// Close the current ResultSet
if (resultSet != null)
resultSet.close();
// Reset the current update count
updateCount = -1;
// Blocking database call
SqlResult sqlResult = jdbcConnection.executeSql(sql, bindValues);
// Handle the result
resultSet = sqlResult.getResultSet();
updateCount = sqlResult.getUpdateCount();
return resultSet != null;
}
public Publisher<Boolean> executeAsyncOracle() throws SQLException {
// Check if this statement is closed
if (isClosed)
throw new SQLException("Closed Statement");
// Check if all bind values are set
for (Object bindValue : bindValues) {
if (bindValue == null)
throw new SQLException("Bind value not set");
}
// Close the current ResultSet
if (resultSet != null)
resultSet.close();
// Reset the current update count
updateCount = -1;
// Non-blocking database call
return Flux.from(jdbcConnection.executeSqlAsync(sql, bindValues))
.map(sqlResult -> {
// Handle the result
resultSet = sqlResult.getResultSet();
updateCount = sqlResult.getUpdateCount();
return resultSet != null;
});
}
Developing JDBC Reactive Extensions
public boolean execute() throws SQLException {
prepareForExecute();
SqlResult result = jdbcConnection.executeSql(sql, bindValues);
return handleResult(result);
}
public Publisher<Boolean> executeAsyncOracle() throws SQLException {
prepareForExecute();
return Flux.from(jdbcConnection.executeSqlAsync(sql, bindValues))
.map(sqlResult -> handleResult(sqlResult));
}
private void prepareForExecute() throws SQLException {
// Check if this statement is closed
if (isClosed)
throw new SQLException("Closed Statement");
// Check if all bind values are set
for (Object bindValue : bindValues) {
if (bindValue == null)
throw new SQLException("Bind value not set");
}
// Close the current ResultSet
if (resultSet != null)
resultSet.close();
// Reset the current update count
updateCount = -1;
}
private boolean handleResult(SqlResult result) {
resultSet = result.getResultSet();
updateCount = result.getUpdateCount();
return resultSet != null;
}
Developing JDBC Reactive Extensions
Developing JDBC Reactive Extensions
Setup
Blocking
Handle Result
Setup
Non-Blocking
Handle Result
Synchronous JDBC Setup
Blocking
Handle Result
Setup
Non-Blocking
Handle Result
Setup
Non-Blocking
Handle Result
Reactive JDBC
Database
Setup
Blocking
Handle Result
Database
Adapting JDBC Reactive Extensions for Oracle
R2DBC
R2DBC SPI Reactive Extensions API
ConnectionFactory
create()
OracleConnectionBuilder
buildConnectionPublisherOracle()
Statement
execute()
OraclePreparedStatement
executeAsyncOracle()
Result
map(Function)
OracleResultSet
publisherOracle(Function)
https://github.com/oracle/oracle-r2dbc
Adapting JDBC Reactive Extensions for Oracle
R2DBC
R2DBC SPI Reactive Extensions API
Connection
commit()
OracleConnection
commitAsyncOracle()
Blob
stream()
OracleBlob
publisherOracle()
Clob
stream()
OracleClob
publisherOracle()
rollback()
close()
rollbackAsyncOracle()
closeAsyncOracle()
https://github.com/oracle/oracle-r2dbc
Agenda
• Once Upon a Time
• The Making of Oracle R2DBC driver
ü Taking Your Code from Synchronous to Reactive
Oracle Confidential
From Synchronous to Reactive: Configuration
static DataSource configureJdbc() throws SQLException {
OracleDataSource dataSource = new oracle.jdbc.pool.OracleDataSource();
dataSource.setDriverType("thin");
dataSource.setServerName(DatabaseConfig.HOST);
dataSource.setPortNumber(DatabaseConfig.PORT);
dataSource.setServiceName(DatabaseConfig.SERVICE_NAME);
dataSource.setUser(DatabaseConfig.USER);
dataSource.setPassword(DatabaseConfig.PASSWORD);
return dataSource;
}
static ConnectionFactory configureR2dbc() {
return ConnectionFactories.get(ConnectionFactoryOptions.builder()
.option(DRIVER, "oracle")
.option(HOST, DatabaseConfig.HOST)
.option(PORT, DatabaseConfig.PORT)
.option(DATABASE, DatabaseConfig.SERVICE_NAME)
.option(USER, DatabaseConfig.USER)
.option(PASSWORD, DatabaseConfig.PASSWORD)
.build());
}
From Synchronous to Reactive: Query
static String queryJdbc(java.sql.Connection connection) throws SQLException {
try (java.sql.Statement statement = connection.createStatement()) {
ResultSet resultSet =
statement.executeQuery("SELECT 'Hello, JDBC!' FROM sys.dual");
if (resultSet.next())
return resultSet.getString(1);
else
throw new NoSuchElementException("Query returned zero rows");
}
}
static Publisher<String> queryR2dbc(io.r2dbc.spi.Connection connection) {
return Flux.from(connection.createStatement(
"SELECT 'Hello, R2DBC!' FROM sys.dual")
.execute())
.flatMap(result ->
result.map(row -> row.get(0, String.class)))
.switchIfEmpty(Flux.error(
new NoSuchElementException("Query returned zero rows")));
}
Flat Map:
f(x) -> { y0, y1, …, yn }
{ x0, x1, …, xn } -> { f(x0), f(x1), … f(xn)}
{ y0-0, y0-1, …, y0-n, y1-0, y1-1, …, y1-n, …, yn-n}
From Synchronous to Reactive: Insert
static int insertJdbc(java.sql.Connection connection) throws SQLException {
try (PreparedStatement preparedStatement = connection.prepareStatement(
"INSERT INTO JdbcToR2dbcTable(id, value) VALUES (?, ?)")) {
preparedStatement.setInt(1, 0);
preparedStatement.setString(2, "JDBC");
return preparedStatement.executeUpdate();
}
}
static Publisher<Integer> insertR2dbc(io.r2dbc.spi.Connection connection) {
return Flux.from(connection.createStatement(
"INSERT INTO JdbcToR2dbcTable(id, value) VALUES (?, ?)")
.bind(0, 0)
.bind(1, "R2DBC")
.execute())
.flatMap(Result::getRowsUpdated);
}
From Synchronous to Reactive: Update
static int updateJdbc(java.sql.Connection connection) throws SQLException {
try (PreparedStatement preparedStatement = connection.prepareStatement(
"UPDATE JdbcToR2dbcTable SET value = ? WHERE id = ?")) {
preparedStatement.setString(1, "JDBC");
preparedStatement.setInt(2, 0);
return preparedStatement.executeUpdate();
}
}
static Publisher<Integer> updateR2dbc(io.r2dbc.spi.Connection connection) {
return Flux.from(connection.createStatement(
"UPDATE JdbcToR2dbcTable SET value = ? WHERE id = ?")
.bind(0, "R2DBC")
.bind(1, 0)
.execute())
.flatMap(Result::getRowsUpdated);
}
From Synchronous to Reactive: Conditional
Branch
static int tryUpdateJdbc(java.sql.Connection connection) throws SQLException
{
// Try to update the row
int updateCount = updateJdbc(connection);
// If the row does not exist, then insert it.
if (updateCount == 0)
return insertJdbc(connection);
else
return updateCount;
}
static Publisher<Integer> tryUpdateR2dbc(io.r2dbc.spi.Connection connection)
{
// Try to update the row
return Flux.from(updateR2dbc(connection))
.flatMap(updateCount -> {
// If the row does not exist, then insert it.
if (updateCount == 0)
return insertR2dbc(connection);
else
return Flux.just(updateCount);
});
}
From Synchronous to Reactive: Error Recovery
static int tryInsertJdbc(java.sql.Connection connection) throws SQLException
{
try {
// Try to insert the row
return insertJdbc(connection);
}
catch (SQLException sqlException) {
// If the row already exists, then update it.
if (sqlException.getErrorCode() == UNIQUE_CONSTRAINT_VIOLATION)
return updateJdbc(connection);
else
throw sqlException;
}
}
static Publisher<Integer> tryInsertR2dbc(io.r2dbc.spi.Connection connection)
{
// Try to insert the row
return Flux.from(insertR2dbc(connection))
.onErrorResume(R2dbcException.class, r2dbcException -> {
// If the row already exists, then update it.
if (r2dbcException.getErrorCode() == UNIQUE_CONSTRAINT_VIOLATION)
return updateR2dbc(connection);
else
return Flux.error(r2dbcException);
});
}
From Synchronous to Reactive: Loop
static int loopJdbc(java.sql.Connection connection) throws SQLException {
do {
try {
// Try to update the row, or insert it if it does not exist
return tryUpdateJdbc(connection);
}
catch (SQLException sqlException) {
// If another database session has inserted the row before this
// one did, then recover from failure by continuing the loop.
if (sqlException.getErrorCode() != UNIQUE_CONSTRAINT_VIOLATION)
throw sqlException;
}
} while (true);
}
static Publisher<Integer> loopR2dbc(io.r2dbc.spi.Connection connection) {
// Try to update the row, or insert it if it does not exist
return Flux.from(tryUpdateR2dbc(connection))
.onErrorResume(R2dbcException.class, r2dbcException -> {
// If another database session has inserted the row before this
// one did, then recover from failure by recursively invoking this
// method.
if (r2dbcException.getErrorCode() != UNIQUE_CONSTRAINT_VIOLATION)
return Flux.error(r2dbcException);
else
return loopR2dbc(connection);
});
}
User
Java
Code
JDBC
Reactive
Extension Standard
JDBC API
R2DBC
+
3rd party
Reactive
Streams
Libraries
Async call with non-blocking
backpressure
operators (map, reduce, filters),
concurrency modeling,
monitoring, tracing
Implements Java SE
reactive stream
interface (Flow)
Full Reactive
Streams
Sync/blocking JDBC calls
Java
Business
Logic
User Java code
Oracle
Database
Oracle JDBC
driver
Summary of Oracle DB Access with Java – Part 2

More Related Content

What's hot

Building a REST Service in minutes with Spring Boot
Building a REST Service in minutes with Spring BootBuilding a REST Service in minutes with Spring Boot
Building a REST Service in minutes with Spring Boot
Omri Spector
 
Introduction to Kafka Streams
Introduction to Kafka StreamsIntroduction to Kafka Streams
Introduction to Kafka Streams
Guozhang Wang
 
Spring Boot and REST API
Spring Boot and REST APISpring Boot and REST API
Spring Boot and REST API
07.pallav
 
ksqlDB: A Stream-Relational Database System
ksqlDB: A Stream-Relational Database SystemksqlDB: A Stream-Relational Database System
ksqlDB: A Stream-Relational Database System
confluent
 
Transactions and Concurrency Control Patterns
Transactions and Concurrency Control PatternsTransactions and Concurrency Control Patterns
Transactions and Concurrency Control Patterns
J On The Beach
 
Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020
Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020
Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020
Matt Raible
 
Microservice With Spring Boot and Spring Cloud
Microservice With Spring Boot and Spring CloudMicroservice With Spring Boot and Spring Cloud
Microservice With Spring Boot and Spring Cloud
Eberhard Wolff
 
Quarkus tips, tricks, and techniques
Quarkus tips, tricks, and techniquesQuarkus tips, tricks, and techniques
Quarkus tips, tricks, and techniques
Red Hat Developers
 
Spring Boot
Spring BootSpring Boot
Spring Boot
Pei-Tang Huang
 
Apache Kafka® Security Overview
Apache Kafka® Security OverviewApache Kafka® Security Overview
Apache Kafka® Security Overview
confluent
 
Percona Live 2022 - The Evolution of a MySQL Database System
Percona Live 2022 - The Evolution of a MySQL Database SystemPercona Live 2022 - The Evolution of a MySQL Database System
Percona Live 2022 - The Evolution of a MySQL Database System
Frederic Descamps
 
Discover Quarkus and GraalVM
Discover Quarkus and GraalVMDiscover Quarkus and GraalVM
Discover Quarkus and GraalVM
Romain Schlick
 
Spring Boot Interview Questions | Edureka
Spring Boot Interview Questions | EdurekaSpring Boot Interview Questions | Edureka
Spring Boot Interview Questions | Edureka
Edureka!
 
Spring Framework - AOP
Spring Framework - AOPSpring Framework - AOP
Spring Framework - AOP
Dzmitry Naskou
 
Java11 New Features
Java11 New FeaturesJava11 New Features
Java11 New Features
Haim Michael
 
Understanding Reactive Programming
Understanding Reactive ProgrammingUnderstanding Reactive Programming
Understanding Reactive Programming
Andres Almiray
 
When NOT to use Apache Kafka?
When NOT to use Apache Kafka?When NOT to use Apache Kafka?
When NOT to use Apache Kafka?
Kai Wähner
 
Zero-Copy Event-Driven Servers with Netty
Zero-Copy Event-Driven Servers with NettyZero-Copy Event-Driven Servers with Netty
Zero-Copy Event-Driven Servers with NettyDaniel Bimschas
 
Reactive Applications with Apache Pulsar and Spring Boot
Reactive Applications with Apache Pulsar and Spring BootReactive Applications with Apache Pulsar and Spring Boot
Reactive Applications with Apache Pulsar and Spring Boot
VMware Tanzu
 

What's hot (20)

Building a REST Service in minutes with Spring Boot
Building a REST Service in minutes with Spring BootBuilding a REST Service in minutes with Spring Boot
Building a REST Service in minutes with Spring Boot
 
Introduction to Kafka Streams
Introduction to Kafka StreamsIntroduction to Kafka Streams
Introduction to Kafka Streams
 
Spring Boot and REST API
Spring Boot and REST APISpring Boot and REST API
Spring Boot and REST API
 
ksqlDB: A Stream-Relational Database System
ksqlDB: A Stream-Relational Database SystemksqlDB: A Stream-Relational Database System
ksqlDB: A Stream-Relational Database System
 
Transactions and Concurrency Control Patterns
Transactions and Concurrency Control PatternsTransactions and Concurrency Control Patterns
Transactions and Concurrency Control Patterns
 
Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020
Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020
Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020
 
Microservice With Spring Boot and Spring Cloud
Microservice With Spring Boot and Spring CloudMicroservice With Spring Boot and Spring Cloud
Microservice With Spring Boot and Spring Cloud
 
Quarkus tips, tricks, and techniques
Quarkus tips, tricks, and techniquesQuarkus tips, tricks, and techniques
Quarkus tips, tricks, and techniques
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Apache Kafka® Security Overview
Apache Kafka® Security OverviewApache Kafka® Security Overview
Apache Kafka® Security Overview
 
Percona Live 2022 - The Evolution of a MySQL Database System
Percona Live 2022 - The Evolution of a MySQL Database SystemPercona Live 2022 - The Evolution of a MySQL Database System
Percona Live 2022 - The Evolution of a MySQL Database System
 
Discover Quarkus and GraalVM
Discover Quarkus and GraalVMDiscover Quarkus and GraalVM
Discover Quarkus and GraalVM
 
Spring Boot Interview Questions | Edureka
Spring Boot Interview Questions | EdurekaSpring Boot Interview Questions | Edureka
Spring Boot Interview Questions | Edureka
 
Spring Framework - AOP
Spring Framework - AOPSpring Framework - AOP
Spring Framework - AOP
 
Java11 New Features
Java11 New FeaturesJava11 New Features
Java11 New Features
 
Understanding Reactive Programming
Understanding Reactive ProgrammingUnderstanding Reactive Programming
Understanding Reactive Programming
 
When NOT to use Apache Kafka?
When NOT to use Apache Kafka?When NOT to use Apache Kafka?
When NOT to use Apache Kafka?
 
Zero-Copy Event-Driven Servers with Netty
Zero-Copy Event-Driven Servers with NettyZero-Copy Event-Driven Servers with Netty
Zero-Copy Event-Driven Servers with Netty
 
Reactive Applications with Apache Pulsar and Spring Boot
Reactive Applications with Apache Pulsar and Spring BootReactive Applications with Apache Pulsar and Spring Boot
Reactive Applications with Apache Pulsar and Spring Boot
 
Java basic
Java basicJava basic
Java basic
 

Similar to The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchronous to Reactive

TDC Connections 2023 - Revolutionize Java DB AppDev with Reactive Streams and...
TDC Connections 2023 - Revolutionize Java DB AppDev with Reactive Streams and...TDC Connections 2023 - Revolutionize Java DB AppDev with Reactive Streams and...
TDC Connections 2023 - Revolutionize Java DB AppDev with Reactive Streams and...
Juarez Junior
 
DeveloperWeek Europe 2023 - Revolutionize Java DB AppDev with Reactive Stream...
DeveloperWeek Europe 2023 - Revolutionize Java DB AppDev with Reactive Stream...DeveloperWeek Europe 2023 - Revolutionize Java DB AppDev with Reactive Stream...
DeveloperWeek Europe 2023 - Revolutionize Java DB AppDev with Reactive Stream...
Juarez Junior
 
Java DataBase Connectivity API (JDBC API)
Java DataBase Connectivity API (JDBC API)Java DataBase Connectivity API (JDBC API)
Java DataBase Connectivity API (JDBC API)
Luzan Baral
 
JDBC
JDBCJDBC
Melee Numerique 2022 - Revolutionize Java DB App Dev with Reactive Streams an...
Melee Numerique 2022 - Revolutionize Java DB App Dev with Reactive Streams an...Melee Numerique 2022 - Revolutionize Java DB App Dev with Reactive Streams an...
Melee Numerique 2022 - Revolutionize Java DB App Dev with Reactive Streams an...
Juarez Junior
 
Cloud Conference Day - Revolutionize Java Database App Development with React...
Cloud Conference Day - Revolutionize Java Database App Development with React...Cloud Conference Day - Revolutionize Java Database App Development with React...
Cloud Conference Day - Revolutionize Java Database App Development with React...
Juarez Junior
 
CloudTalks - Revolutionize Java DB AppDev with Reactive Streams and Virtual T...
CloudTalks - Revolutionize Java DB AppDev with Reactive Streams and Virtual T...CloudTalks - Revolutionize Java DB AppDev with Reactive Streams and Virtual T...
CloudTalks - Revolutionize Java DB AppDev with Reactive Streams and Virtual T...
Juarez Junior
 
jdbc_presentation.ppt
jdbc_presentation.pptjdbc_presentation.ppt
jdbc_presentation.ppt
DrMeenakshiS
 
Java Web Programming Using Cloud Platform: Module 3
Java Web Programming Using Cloud Platform: Module 3Java Web Programming Using Cloud Platform: Module 3
Java Web Programming Using Cloud Platform: Module 3
IMC Institute
 
Rollin onj Rubyv3
Rollin onj Rubyv3Rollin onj Rubyv3
Rollin onj Rubyv3
Oracle
 
JDBC java for learning java for learn.ppt
JDBC java for learning java for learn.pptJDBC java for learning java for learn.ppt
JDBC java for learning java for learn.ppt
kingkolju
 
Introduction to JDBC and database access in web applications
Introduction to JDBC and database access in web applicationsIntroduction to JDBC and database access in web applications
Introduction to JDBC and database access in web applications
Fulvio Corno
 
Java Course 13: JDBC & Logging
Java Course 13: JDBC & LoggingJava Course 13: JDBC & Logging
Java Course 13: JDBC & Logging
Anton Keks
 
Java Web Programming [3/9] : Servlet Advanced
Java Web Programming [3/9] : Servlet AdvancedJava Web Programming [3/9] : Servlet Advanced
Java Web Programming [3/9] : Servlet Advanced
IMC Institute
 
JDBC: java DataBase connectivity
JDBC: java DataBase connectivityJDBC: java DataBase connectivity
JDBC: java DataBase connectivity
Tanmoy Barman
 
PROGRAMMING IN JAVA -unit 5 -part I
PROGRAMMING IN JAVA -unit 5 -part IPROGRAMMING IN JAVA -unit 5 -part I
PROGRAMMING IN JAVA -unit 5 -part I
SivaSankari36
 

Similar to The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchronous to Reactive (20)

TDC Connections 2023 - Revolutionize Java DB AppDev with Reactive Streams and...
TDC Connections 2023 - Revolutionize Java DB AppDev with Reactive Streams and...TDC Connections 2023 - Revolutionize Java DB AppDev with Reactive Streams and...
TDC Connections 2023 - Revolutionize Java DB AppDev with Reactive Streams and...
 
DeveloperWeek Europe 2023 - Revolutionize Java DB AppDev with Reactive Stream...
DeveloperWeek Europe 2023 - Revolutionize Java DB AppDev with Reactive Stream...DeveloperWeek Europe 2023 - Revolutionize Java DB AppDev with Reactive Stream...
DeveloperWeek Europe 2023 - Revolutionize Java DB AppDev with Reactive Stream...
 
Java DataBase Connectivity API (JDBC API)
Java DataBase Connectivity API (JDBC API)Java DataBase Connectivity API (JDBC API)
Java DataBase Connectivity API (JDBC API)
 
JDBC
JDBCJDBC
JDBC
 
Jdbc introduction
Jdbc introductionJdbc introduction
Jdbc introduction
 
Melee Numerique 2022 - Revolutionize Java DB App Dev with Reactive Streams an...
Melee Numerique 2022 - Revolutionize Java DB App Dev with Reactive Streams an...Melee Numerique 2022 - Revolutionize Java DB App Dev with Reactive Streams an...
Melee Numerique 2022 - Revolutionize Java DB App Dev with Reactive Streams an...
 
Cloud Conference Day - Revolutionize Java Database App Development with React...
Cloud Conference Day - Revolutionize Java Database App Development with React...Cloud Conference Day - Revolutionize Java Database App Development with React...
Cloud Conference Day - Revolutionize Java Database App Development with React...
 
CloudTalks - Revolutionize Java DB AppDev with Reactive Streams and Virtual T...
CloudTalks - Revolutionize Java DB AppDev with Reactive Streams and Virtual T...CloudTalks - Revolutionize Java DB AppDev with Reactive Streams and Virtual T...
CloudTalks - Revolutionize Java DB AppDev with Reactive Streams and Virtual T...
 
jdbc_presentation.ppt
jdbc_presentation.pptjdbc_presentation.ppt
jdbc_presentation.ppt
 
Java Web Programming Using Cloud Platform: Module 3
Java Web Programming Using Cloud Platform: Module 3Java Web Programming Using Cloud Platform: Module 3
Java Web Programming Using Cloud Platform: Module 3
 
Rollin onj Rubyv3
Rollin onj Rubyv3Rollin onj Rubyv3
Rollin onj Rubyv3
 
Jdbc
JdbcJdbc
Jdbc
 
Jdbc[1]
Jdbc[1]Jdbc[1]
Jdbc[1]
 
JDBC programming
JDBC programmingJDBC programming
JDBC programming
 
JDBC java for learning java for learn.ppt
JDBC java for learning java for learn.pptJDBC java for learning java for learn.ppt
JDBC java for learning java for learn.ppt
 
Introduction to JDBC and database access in web applications
Introduction to JDBC and database access in web applicationsIntroduction to JDBC and database access in web applications
Introduction to JDBC and database access in web applications
 
Java Course 13: JDBC & Logging
Java Course 13: JDBC & LoggingJava Course 13: JDBC & Logging
Java Course 13: JDBC & Logging
 
Java Web Programming [3/9] : Servlet Advanced
Java Web Programming [3/9] : Servlet AdvancedJava Web Programming [3/9] : Servlet Advanced
Java Web Programming [3/9] : Servlet Advanced
 
JDBC: java DataBase connectivity
JDBC: java DataBase connectivityJDBC: java DataBase connectivity
JDBC: java DataBase connectivity
 
PROGRAMMING IN JAVA -unit 5 -part I
PROGRAMMING IN JAVA -unit 5 -part IPROGRAMMING IN JAVA -unit 5 -part I
PROGRAMMING IN JAVA -unit 5 -part I
 

More from VMware Tanzu

Spring into AI presented by Dan Vega 5/14
Spring into AI presented by Dan Vega 5/14Spring into AI presented by Dan Vega 5/14
Spring into AI presented by Dan Vega 5/14
VMware Tanzu
 
What AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About ItWhat AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About It
VMware Tanzu
 
Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023
VMware Tanzu
 
Enhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at ScaleEnhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at Scale
VMware Tanzu
 
Spring Update | July 2023
Spring Update | July 2023Spring Update | July 2023
Spring Update | July 2023
VMware Tanzu
 
Platforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a ProductPlatforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a Product
VMware Tanzu
 
Building Cloud Ready Apps
Building Cloud Ready AppsBuilding Cloud Ready Apps
Building Cloud Ready Apps
VMware Tanzu
 
Spring Boot 3 And Beyond
Spring Boot 3 And BeyondSpring Boot 3 And Beyond
Spring Boot 3 And Beyond
VMware Tanzu
 
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdfSpring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
VMware Tanzu
 
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
VMware Tanzu
 
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
VMware Tanzu
 
tanzu_developer_connect.pptx
tanzu_developer_connect.pptxtanzu_developer_connect.pptx
tanzu_developer_connect.pptx
VMware Tanzu
 
Tanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - FrenchTanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - French
VMware Tanzu
 
Tanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - EnglishTanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - English
VMware Tanzu
 
Virtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - EnglishVirtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - English
VMware Tanzu
 
Tanzu Developer Connect - French
Tanzu Developer Connect - FrenchTanzu Developer Connect - French
Tanzu Developer Connect - French
VMware Tanzu
 
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
VMware Tanzu
 
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring BootSpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
VMware Tanzu
 
SpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software EngineerSpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software Engineer
VMware Tanzu
 
SpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs PracticeSpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs Practice
VMware Tanzu
 

More from VMware Tanzu (20)

Spring into AI presented by Dan Vega 5/14
Spring into AI presented by Dan Vega 5/14Spring into AI presented by Dan Vega 5/14
Spring into AI presented by Dan Vega 5/14
 
What AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About ItWhat AI Means For Your Product Strategy And What To Do About It
What AI Means For Your Product Strategy And What To Do About It
 
Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023Make the Right Thing the Obvious Thing at Cardinal Health 2023
Make the Right Thing the Obvious Thing at Cardinal Health 2023
 
Enhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at ScaleEnhancing DevEx and Simplifying Operations at Scale
Enhancing DevEx and Simplifying Operations at Scale
 
Spring Update | July 2023
Spring Update | July 2023Spring Update | July 2023
Spring Update | July 2023
 
Platforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a ProductPlatforms, Platform Engineering, & Platform as a Product
Platforms, Platform Engineering, & Platform as a Product
 
Building Cloud Ready Apps
Building Cloud Ready AppsBuilding Cloud Ready Apps
Building Cloud Ready Apps
 
Spring Boot 3 And Beyond
Spring Boot 3 And BeyondSpring Boot 3 And Beyond
Spring Boot 3 And Beyond
 
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdfSpring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
 
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
 
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
 
tanzu_developer_connect.pptx
tanzu_developer_connect.pptxtanzu_developer_connect.pptx
tanzu_developer_connect.pptx
 
Tanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - FrenchTanzu Virtual Developer Connect Workshop - French
Tanzu Virtual Developer Connect Workshop - French
 
Tanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - EnglishTanzu Developer Connect Workshop - English
Tanzu Developer Connect Workshop - English
 
Virtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - EnglishVirtual Developer Connect Workshop - English
Virtual Developer Connect Workshop - English
 
Tanzu Developer Connect - French
Tanzu Developer Connect - FrenchTanzu Developer Connect - French
Tanzu Developer Connect - French
 
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
 
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring BootSpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
 
SpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software EngineerSpringOne Tour: The Influential Software Engineer
SpringOne Tour: The Influential Software Engineer
 
SpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs PracticeSpringOne Tour: Domain-Driven Design: Theory vs Practice
SpringOne Tour: Domain-Driven Design: Theory vs Practice
 

Recently uploaded

A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
Philip Schwarz
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
WSO2
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Globus
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
Georgi Kodinov
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Globus
 
Graphic Design Crash Course for beginners
Graphic Design Crash Course for beginnersGraphic Design Crash Course for beginners
Graphic Design Crash Course for beginners
e20449
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
vrstrong314
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
Donna Lenk
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
takuyayamamoto1800
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
Globus
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
Globus
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
Juraj Vysvader
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Anthony Dahanne
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
Ortus Solutions, Corp
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
Globus
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
IES VE
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
AMB-Review
 

Recently uploaded (20)

A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 
Graphic Design Crash Course for beginners
Graphic Design Crash Course for beginnersGraphic Design Crash Course for beginners
Graphic Design Crash Course for beginners
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
 

The Making of the Oracle R2DBC Driver and How to Take Your Code from Synchronous to Reactive

  • 1. The Making of the Oracle R2DBC Driver And How to Take Your Code from Synchronous to Reactive Kuassi Mensah Michael McMahon @kmensah
  • 2. Agenda ü Once Upon a Time • The Making of Oracle R2DBC driver • Taking Your Code from Synchronous to Reactive Oracle Confidential
  • 3. Once Upon a Time … The Asynchronous Database Access API (ADBA) • Started in 2017 • Goal – A standard Java database access API that never blocks user threads – No compatibility or complementarity with JDBC • Motivations – Asynchronous apps have better throughput – Simultaneous access to multiple databases, e.g. map/reduce, sharded databases – Fire and forget, e.g. DML, stored procedures • The API is available from OpenJDK at https://bit.ly/3t3nkAd 3
  • 4. 1. Per the Java SE team: “the future of Java scalability is Virtual Threads” –ADBA would not be accepted as a Java standard as it was an async solution to a problem that would be addressed by virtual threads. – Unless it became a standard ADBA would have very little impact, certainly not enough to justify the effort. 2. There was very little support within the Java community. -- Gravitating towards R2DBC 4 Why Did We Stop Working on ADBA?
  • 5. We changed our focus towards • JDBC Reactive Extensions • An Oracle R2DBC Driver • Instrumenting the JDBC driver to support Virtual Threads 5 Then What?
  • 6. SQL Execution (OraclePreparedStatement): Publisher<Boolean> executeAsyncOracle() Publisher<Long> executeUpdateAsyncOracle() Publisher<Long> executeBatchAsyncOracle() Publisher<OracleResultSet> executeQueryAsyncOracle() Row Fetching (OracleResultSet): Publisher<T> publisherOracle(Function<OracleRow, T> f) LOB I/O (OracleBlob): Publisher<byte[]> publisherOracle(long position) Subscriber<byte[]> subscriberOracle(long position) LOB I/O (OracleClob): Publisher<String> publisherOracle(long position) Subscriber<String> subscriberOracle(long position) Connection Closing (OracleConnection): Publisher<Success> closeAsyncOracle() Transaction Closing (OracleConnection): Publisher<Success> commitAsyncOracle() Publisher<Success> rollbackAsyncOracle() Connection Creation (OracleConnectionBuilder): Publisher<OracleConnection> buildConnectionPublisherOracle() JDBC Reactive Extensions (built into the driver)
  • 7. User Java Code JDBC Reactive Extension Standard JDBC API 3rd party Reactive Streams Libraries Async call with non-blocking backpressure operators (map, reduce, filters), concurrency modeling, monitoring, tracing Implements Java SE reactive stream interface (Flow) Full Reactive Streams Sync/blocking JDBC calls Java Business Logic User Java code Oracle Database Oracle JDBC driver Summary of Oracle DB Access with Java – Part 1
  • 8. Agenda • Once Upon a Time ü The Making of Oracle R2DBC driver • Taking Your Code from Synchronous to Reactive Oracle Confidential
  • 9. public boolean execute() throws SQLException { // Check if this statement is closed if (isClosed) throw new SQLException("Closed Statement"); // Check if all bind values are set for (Object bindValue : bindValues) { if (bindValue == null) throw new SQLException("Bind value not set"); } // Close the current ResultSet if (resultSet != null) resultSet.close(); // Reset the current update count updateCount = -1; // Blocking database call SqlResult sqlResult = jdbcConnection.executeSql(sql, bindValues); // Handle the result resultSet = sqlResult.getResultSet(); updateCount = sqlResult.getUpdateCount(); return resultSet != null; } public Publisher<Boolean> executeAsyncOracle() throws SQLException { // Check if this statement is closed if (isClosed) throw new SQLException("Closed Statement"); // Check if all bind values are set for (Object bindValue : bindValues) { if (bindValue == null) throw new SQLException("Bind value not set"); } // Close the current ResultSet if (resultSet != null) resultSet.close(); // Reset the current update count updateCount = -1; // Non-blocking database call return Flux.from(jdbcConnection.executeSqlAsync(sql, bindValues)) .map(sqlResult -> { // Handle the result resultSet = sqlResult.getResultSet(); updateCount = sqlResult.getUpdateCount(); return resultSet != null; }); } Developing JDBC Reactive Extensions
  • 10. public boolean execute() throws SQLException { // Check if this statement is closed if (isClosed) throw new SQLException("Closed Statement"); // Check if all bind values are set for (Object bindValue : bindValues) { if (bindValue == null) throw new SQLException("Bind value not set"); } // Close the current ResultSet if (resultSet != null) resultSet.close(); // Reset the current update count updateCount = -1; // Blocking database call SqlResult sqlResult = jdbcConnection.executeSql(sql, bindValues); // Handle the result resultSet = sqlResult.getResultSet(); updateCount = sqlResult.getUpdateCount(); return resultSet != null; } public Publisher<Boolean> executeAsyncOracle() throws SQLException { // Check if this statement is closed if (isClosed) throw new SQLException("Closed Statement"); // Check if all bind values are set for (Object bindValue : bindValues) { if (bindValue == null) throw new SQLException("Bind value not set"); } // Close the current ResultSet if (resultSet != null) resultSet.close(); // Reset the current update count updateCount = -1; // Non-blocking database call return Flux.from(jdbcConnection.executeSqlAsync(sql, bindValues)) .map(sqlResult -> { // Handle the result resultSet = sqlResult.getResultSet(); updateCount = sqlResult.getUpdateCount(); return resultSet != null; }); } Developing JDBC Reactive Extensions
  • 11. public boolean execute() throws SQLException { prepareForExecute(); SqlResult result = jdbcConnection.executeSql(sql, bindValues); return handleResult(result); } public Publisher<Boolean> executeAsyncOracle() throws SQLException { prepareForExecute(); return Flux.from(jdbcConnection.executeSqlAsync(sql, bindValues)) .map(sqlResult -> handleResult(sqlResult)); } private void prepareForExecute() throws SQLException { // Check if this statement is closed if (isClosed) throw new SQLException("Closed Statement"); // Check if all bind values are set for (Object bindValue : bindValues) { if (bindValue == null) throw new SQLException("Bind value not set"); } // Close the current ResultSet if (resultSet != null) resultSet.close(); // Reset the current update count updateCount = -1; } private boolean handleResult(SqlResult result) { resultSet = result.getResultSet(); updateCount = result.getUpdateCount(); return resultSet != null; } Developing JDBC Reactive Extensions
  • 12. Developing JDBC Reactive Extensions Setup Blocking Handle Result Setup Non-Blocking Handle Result Synchronous JDBC Setup Blocking Handle Result Setup Non-Blocking Handle Result Setup Non-Blocking Handle Result Reactive JDBC Database Setup Blocking Handle Result Database
  • 13. Adapting JDBC Reactive Extensions for Oracle R2DBC R2DBC SPI Reactive Extensions API ConnectionFactory create() OracleConnectionBuilder buildConnectionPublisherOracle() Statement execute() OraclePreparedStatement executeAsyncOracle() Result map(Function) OracleResultSet publisherOracle(Function) https://github.com/oracle/oracle-r2dbc
  • 14. Adapting JDBC Reactive Extensions for Oracle R2DBC R2DBC SPI Reactive Extensions API Connection commit() OracleConnection commitAsyncOracle() Blob stream() OracleBlob publisherOracle() Clob stream() OracleClob publisherOracle() rollback() close() rollbackAsyncOracle() closeAsyncOracle() https://github.com/oracle/oracle-r2dbc
  • 15. Agenda • Once Upon a Time • The Making of Oracle R2DBC driver ü Taking Your Code from Synchronous to Reactive Oracle Confidential
  • 16. From Synchronous to Reactive: Configuration static DataSource configureJdbc() throws SQLException { OracleDataSource dataSource = new oracle.jdbc.pool.OracleDataSource(); dataSource.setDriverType("thin"); dataSource.setServerName(DatabaseConfig.HOST); dataSource.setPortNumber(DatabaseConfig.PORT); dataSource.setServiceName(DatabaseConfig.SERVICE_NAME); dataSource.setUser(DatabaseConfig.USER); dataSource.setPassword(DatabaseConfig.PASSWORD); return dataSource; } static ConnectionFactory configureR2dbc() { return ConnectionFactories.get(ConnectionFactoryOptions.builder() .option(DRIVER, "oracle") .option(HOST, DatabaseConfig.HOST) .option(PORT, DatabaseConfig.PORT) .option(DATABASE, DatabaseConfig.SERVICE_NAME) .option(USER, DatabaseConfig.USER) .option(PASSWORD, DatabaseConfig.PASSWORD) .build()); }
  • 17. From Synchronous to Reactive: Query static String queryJdbc(java.sql.Connection connection) throws SQLException { try (java.sql.Statement statement = connection.createStatement()) { ResultSet resultSet = statement.executeQuery("SELECT 'Hello, JDBC!' FROM sys.dual"); if (resultSet.next()) return resultSet.getString(1); else throw new NoSuchElementException("Query returned zero rows"); } } static Publisher<String> queryR2dbc(io.r2dbc.spi.Connection connection) { return Flux.from(connection.createStatement( "SELECT 'Hello, R2DBC!' FROM sys.dual") .execute()) .flatMap(result -> result.map(row -> row.get(0, String.class))) .switchIfEmpty(Flux.error( new NoSuchElementException("Query returned zero rows"))); } Flat Map: f(x) -> { y0, y1, …, yn } { x0, x1, …, xn } -> { f(x0), f(x1), … f(xn)} { y0-0, y0-1, …, y0-n, y1-0, y1-1, …, y1-n, …, yn-n}
  • 18. From Synchronous to Reactive: Insert static int insertJdbc(java.sql.Connection connection) throws SQLException { try (PreparedStatement preparedStatement = connection.prepareStatement( "INSERT INTO JdbcToR2dbcTable(id, value) VALUES (?, ?)")) { preparedStatement.setInt(1, 0); preparedStatement.setString(2, "JDBC"); return preparedStatement.executeUpdate(); } } static Publisher<Integer> insertR2dbc(io.r2dbc.spi.Connection connection) { return Flux.from(connection.createStatement( "INSERT INTO JdbcToR2dbcTable(id, value) VALUES (?, ?)") .bind(0, 0) .bind(1, "R2DBC") .execute()) .flatMap(Result::getRowsUpdated); }
  • 19. From Synchronous to Reactive: Update static int updateJdbc(java.sql.Connection connection) throws SQLException { try (PreparedStatement preparedStatement = connection.prepareStatement( "UPDATE JdbcToR2dbcTable SET value = ? WHERE id = ?")) { preparedStatement.setString(1, "JDBC"); preparedStatement.setInt(2, 0); return preparedStatement.executeUpdate(); } } static Publisher<Integer> updateR2dbc(io.r2dbc.spi.Connection connection) { return Flux.from(connection.createStatement( "UPDATE JdbcToR2dbcTable SET value = ? WHERE id = ?") .bind(0, "R2DBC") .bind(1, 0) .execute()) .flatMap(Result::getRowsUpdated); }
  • 20. From Synchronous to Reactive: Conditional Branch static int tryUpdateJdbc(java.sql.Connection connection) throws SQLException { // Try to update the row int updateCount = updateJdbc(connection); // If the row does not exist, then insert it. if (updateCount == 0) return insertJdbc(connection); else return updateCount; } static Publisher<Integer> tryUpdateR2dbc(io.r2dbc.spi.Connection connection) { // Try to update the row return Flux.from(updateR2dbc(connection)) .flatMap(updateCount -> { // If the row does not exist, then insert it. if (updateCount == 0) return insertR2dbc(connection); else return Flux.just(updateCount); }); }
  • 21. From Synchronous to Reactive: Error Recovery static int tryInsertJdbc(java.sql.Connection connection) throws SQLException { try { // Try to insert the row return insertJdbc(connection); } catch (SQLException sqlException) { // If the row already exists, then update it. if (sqlException.getErrorCode() == UNIQUE_CONSTRAINT_VIOLATION) return updateJdbc(connection); else throw sqlException; } } static Publisher<Integer> tryInsertR2dbc(io.r2dbc.spi.Connection connection) { // Try to insert the row return Flux.from(insertR2dbc(connection)) .onErrorResume(R2dbcException.class, r2dbcException -> { // If the row already exists, then update it. if (r2dbcException.getErrorCode() == UNIQUE_CONSTRAINT_VIOLATION) return updateR2dbc(connection); else return Flux.error(r2dbcException); }); }
  • 22. From Synchronous to Reactive: Loop static int loopJdbc(java.sql.Connection connection) throws SQLException { do { try { // Try to update the row, or insert it if it does not exist return tryUpdateJdbc(connection); } catch (SQLException sqlException) { // If another database session has inserted the row before this // one did, then recover from failure by continuing the loop. if (sqlException.getErrorCode() != UNIQUE_CONSTRAINT_VIOLATION) throw sqlException; } } while (true); } static Publisher<Integer> loopR2dbc(io.r2dbc.spi.Connection connection) { // Try to update the row, or insert it if it does not exist return Flux.from(tryUpdateR2dbc(connection)) .onErrorResume(R2dbcException.class, r2dbcException -> { // If another database session has inserted the row before this // one did, then recover from failure by recursively invoking this // method. if (r2dbcException.getErrorCode() != UNIQUE_CONSTRAINT_VIOLATION) return Flux.error(r2dbcException); else return loopR2dbc(connection); }); }
  • 23. User Java Code JDBC Reactive Extension Standard JDBC API R2DBC + 3rd party Reactive Streams Libraries Async call with non-blocking backpressure operators (map, reduce, filters), concurrency modeling, monitoring, tracing Implements Java SE reactive stream interface (Flow) Full Reactive Streams Sync/blocking JDBC calls Java Business Logic User Java code Oracle Database Oracle JDBC driver Summary of Oracle DB Access with Java – Part 2