It’s time to R2DBC

Sigal Shaharabani
Israeli Tech Radar
Published in
3 min readFeb 6, 2021

In late 2018 I gave a workshop about Spring 5’s new features to Tikal’s full-stack community. The most talked-about feature in Spring 5 was Reactive Spring.

As I was preparing the code samples and lessons for the workshop, I realized I was quite limited with the options for a database example. I had two options:

  • Use MongoDB or Couchbase which had a reactive driver and I was proficient with
  • Wrap inputs and outputs of a JDBC repository with Mono and Flux

I chose to work with MongoDB, so I could present a fully reactive web application.

But now the struggle is over, we have R2DBC.

Photo by Artem Sapegin on Unsplash

R2DBC is a new SPI that can be used instead of JDBC in your JVM applications, to work reactively with databases, especially targeted to relational databases.

The reasons why I strongly believe it is time we all join the R2DBC wagon are:

  • It has joined the Reactive foundation
  • It is supported by both Spring Data and Jooq
  • R2DBC has drivers for Postgres, H2, MySQL, MsSQL, and more

To demonstrate how easy the transition from using JDBC Spring Repositories to R2DBC Spring Repositories is, I am including some sample code I wrote based on the original workshop’s code.

Disclaimer: The original workshop was written in Java 8, Spring Boot 2.2.4, and built with Maven 3, the new repository was written in Kotlin 1.4, Spring Boot 2.3.7, and built with Gradle 6.7. Though this makes the code, not 100% compatible, I believe it would give you a larger variety of code samples.

The project

dependencies {
testImplementation(kotlin("test-junit5"))
testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.6.0")
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
runtimeOnly ("com.h2database:h2")
runtimeOnly("io.r2dbc:r2dbc-h2")
}

The dependencies now also include starters to data-JPA and data-r2dbc.

Also, the project would run on an in-memory H2 database, which also required the R2DBC driver.

Spring Application

The Spring application class is now annotated with:

@SpringBootApplication
@ComponentScan("com.tikalk.workshop.controller", "com.tikalk.workshop.service")
@EnableR2dbcRepositories(basePackages = ["com.tikalk.workshop.repository"])
@EnableWebFlux

Adding the annotation for EnableR2dbcRepositories allows discovering R2DBC repositories and adding them to the application context.

Note: At the time of writing this post (January 2021), “IntelliJ IDEA 2020.3.1 (Ultimate Edition) Build #IU-203.6682.168, built on December 29, 2020”, was unable to show the discovered repositories, so I had to overcome the instinct to check every line IntelliJ marked as erroneous :-)

The Spring data repository

The last thing I needed to do is create an R2DBC repository:

@Repository
interface PersonRepository : R2dbcRepository<Person, BigInteger>

And that concluded all the code changes I had to do to work with R2DBC.

My “service” class is seamless, meaning it passes Flux as an argument and returned object:

@Service
class PersonService @Autowired constructor(val personRepository: PersonRepository) {

fun storePersonsFlux(persons: Flux<Person>):Flux<Person> {
return personRepository.saveAll(persons);
}

fun getAll(): Flux<Person>{
return personRepository.findAll();
}
}

To Conclude

With the inclusion of R2DBC, it is becoming easier to get started with reactive programming in JVM languages and popular frameworks. I believe that this SPI was the missing part therefore, I strongly encourage getting on this wagon.

Links

--

--