I\'ve used Vert.x toolkit for creating reactive applications with support for relational DBs like MySQL and Postgres. I know Spring provides reactive support for some NoSQL DBs
Spring Framework is a library to improve developer productivity, and so are Spring's portfolio projects such as Spring Data, Spring Security, Spring Cloud.
These projects build on top of existing APIs which are either standardized through a JSR or a JEP or on top of libraries that have proved to be useful and widely used. The Spring team does not build drivers for databases or other integrations, that's up to the database/driver vendors.
Spring WebFlux is an good example for a typical Spring module. It builds on top of existing non-blocking servers (Project Reactor via netty, Undertow, and Jetty). WebFlux provides a runtime container for non-blocking, reactive applications leveraging Spring components to assist in developing and running such applications.
Vert.x is an excellent example of an integrated environment that provides its own low-level implementations. Vert.x is heavily optimized and such an eco-system requires optimized integrations. Vert.x came up with own implementations for various databases and provides APIs that work well in a Vert.x context but these APIs are not JDBC.
As M-Razavi already mentioned, Java uses JDBC to integrate with relational databases and JDBC is of a blocking nature – there's nothing sensible one could do about to mitigate the blocking nature of JDBC. Offloading JDBC calls to an Executor
(typically Thread
pool) is limited in its usefulness as the pool eventually saturates with requests). TL;DR, there's no API available on top of which we could provide a reactive relational database integration.
M-Razavi already mentioned ADBA that is an initiative from Oracle to provide a standardized API for asynchronous database access in Java using futures. Everything in ADBA is still work in progress and the team behind ADBA is happy to get feedback. A bunch of Postgres folks is working on a Postgres ADBA driver that can be used for first experiments.
However, ADBA is a future goal and I expect that we don't see ADBA released with Java 12.
There are a couple of independent drivers such as Reactiverse's reactive-pg-client. These drivers come with a vendor-specific API and aren't really suited for a broader integration in Spring. We would need to provide additional layers to expose a common API, and new drivers couldn't be just plugged into your application so it works-out-of-the-box™. Having a standard API allows pluggability, so there's huge value in having a standard API.
Lacking a standard API and the non-availability of drivers, a team at Pivotal started to investigate on a reactive relational API that would be an ideal fit for reactive programming purposes. They came up with R2DBC which stands for Reactive Relational Database Connectivity. As of now, R2DBC is an incubator project to evaluate the feasibility and to start discussions whether driver vendors are interested at all in supporting reactive/non-blocking/asynchronous drivers.
As of now, there are three driver implementations:
R2DBC comes with an API specification (r2dbc-spi
) and a client (r2dbc-client
) that makes the SPI usable for applications. We started exploring on a Spring Data R2DBC integration that provides reactive APIs through a database client and by supporting reactive repositories.
R2DBC and its eco-system are still young and ask for experiments and feedback to collect use cases and to see whether a reactive relational database integration would make sense.
Right now, you can consume R2DBC through Spring Data and the following snippet shows DatabaseClient
usage:
PostgresqlConnectionFactory connectionFactory = new PostgresqlConnectionFactory(…);
DatabaseClient databaseClient = DatabaseClient.create(connectionFactory);
Mono<Integer> count = databaseClient.execute()
.sql("INSERT INTO legoset (id, name, manual) VALUES($1, $2, $3)")
.bind("$1", 42055)
.bind("$2", "Description")
.bindNull("$3", Integer.class)
.fetch()
.rowsUpdated();
Flux<Map<String, Object>> rows = databaseClient.execute()
.sql("SELECT id, name, manual FROM legoset")
.fetch()
.all();
Spring WebFlux is a great way to create a non-blocking REST application. One issue that you run into when start working with WebFlux is JDBC, because JDBC is blocking. New school databases like Cassandra or Couchbase have non-blocking drivers. In Couchbase’s case its driver uses RXJava. There is some effort going into creating asynchronous drivers for databases, as well as Oracle’s effort to create ADBA. Unfortunately, these are early days, and if you want to talk to a SQL database on the JVM you’re stuck with a blocking driver.
Actually, Spring is not responsible for providing a none blocking driver for relational databases.