R2DBC is an initiative to establish a reactive API for relational database integration. It would be great to additionally consume a test container with a relational database through R2DBC by exposing the connection through a preconfigured ConnectionFactory.
ConnectionFactory is in R2DBC what a DataSource is in JDBC. R2DBC drivers are available for:
More to come eventually.
Right now I can think of the following consumption scenarios:
I took a look at how R2DBC could be implemented and found that a suitable implementation might be hard to achieve because of the way how containers are organized.
Here are my thoughts:
SQL databases are assumed to be JDBC containers and not Database containers. Adding a getR2dbcConnectionUrl() would provide a pre-constructed URL for R2DBC usage on specific containers. At the same time, it would make sense to have a common interface for database I/O. What would be the right place for such an interface?
Ideally, database containers are represented as subclass of DatabaseContainer or SqlDatabaseContainer where DatabaseContainer exposes several methods that are now defined on JdbcDatabaseContainer (such as getUsername, getPassword, getTestQueryString, withInitScript, withConnectTimeoutSeconds).
JdbcDatabaseContainer could potentially survive as a general-purpose container. The actual container implementations (MySQLContainer, PostgreSQLContainer) would extend DatabaseContainer and implement a JDBC-specific interface. Containers, which are also available with R2DBC access, would implement an R2DBC-specific interface.
This brings us ultimately to ContainerDatabaseDriver: ContainerDatabaseDriver holds references to started containers. Now, if we would like to provide a similar feature for R2DBC, then we would need to replicate what happens in ContainerDatabaseDriver.
If a test wants to use JDBC and R2DBC using URL-based container bootstrapping, then potentially, we would end up with two container instances. But what we rather want to achieve is a test setup where both integration technologies (JDBC and R2DBC) point to the same database (jdbc:tc:mysql:5.6.23://somehostname:someport/databasename and r2dbc:tc:mysql:5.6.23://somehostname:someport/databasename). This is because typical bootstrapping use-cases (schema and data setup) fully synchronous cases whereas running application code would use R2DBC technology.
That being said, a potential design could be:
This way, containers can be consumed without pulling R2DBC API and are appropriately segregated by access technology.
Let me know what you think, whether that is something worth pursuing.
Most helpful comment
I took a look at how R2DBC could be implemented and found that a suitable implementation might be hard to achieve because of the way how containers are organized.
Here are my thoughts:
SQL databases are assumed to be JDBC containers and not Database containers. Adding a
getR2dbcConnectionUrl()would provide a pre-constructed URL for R2DBC usage on specific containers. At the same time, it would make sense to have a common interface for database I/O. What would be the right place for such an interface?Ideally, database containers are represented as subclass of
DatabaseContainerorSqlDatabaseContainerwhereDatabaseContainerexposes several methods that are now defined onJdbcDatabaseContainer(such as getUsername, getPassword, getTestQueryString, withInitScript, withConnectTimeoutSeconds).JdbcDatabaseContainercould potentially survive as a general-purpose container. The actual container implementations (MySQLContainer,PostgreSQLContainer) would extendDatabaseContainerand implement a JDBC-specific interface. Containers, which are also available with R2DBC access, would implement an R2DBC-specific interface.This brings us ultimately to
ContainerDatabaseDriver:ContainerDatabaseDriverholds references to started containers. Now, if we would like to provide a similar feature for R2DBC, then we would need to replicate what happens inContainerDatabaseDriver.If a test wants to use JDBC and R2DBC using URL-based container bootstrapping, then potentially, we would end up with two container instances. But what we rather want to achieve is a test setup where both integration technologies (JDBC and R2DBC) point to the same database (
jdbc:tc:mysql:5.6.23://somehostname:someport/databasenameandr2dbc:tc:mysql:5.6.23://somehostname:someport/databasename). This is because typical bootstrapping use-cases (schema and data setup) fully synchronous cases whereas running application code would use R2DBC technology.That being said, a potential design could be:
This way, containers can be consumed without pulling R2DBC API and are appropriately segregated by access technology.
Let me know what you think, whether that is something worth pursuing.