I have been trying to get Quartz to work while using R2DBC in spring boot. So far, I have not figured out how to do this. This is because when a JDBC DataSource is created, it tries to initialize my R2DBC repositories which it cannot do because R2DBC is inherently reactive while JDBC is inherently blocking.
Alternatives that I have considered
- Use an in-memory database for Quartz---This has the problem that Quartz no longer persists jobs. I could get around this by keeping track of jobs separately using R2DBC and then reregister all the jobs on startup, but this seems like I would be duplicating a lot of Quartz's functionality.
- Find an R2DBC based scheduler---There aren't any.
Relevant Gradle Dependencies
dependencies {
implementation("io.projectreactor.netty:reactor-netty:0.9.7.RELEASE")
implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
implementation("org.springframework.boot:spring-boot-starter-quartz")
implementation("org.springframework.boot:spring-boot-starter-data-jdbc")
runtimeOnly("com.h2database:h2")
implementation("io.r2dbc:r2dbc-h2:0.8.3.RELEASE")
}
My current Quartz configuration
@Configuration
class QuartzConfig {
@Bean
@QuartzDataSource
fun dataSource(props: DataSourceProperties): DataSource {
return props.initializeDataSourceBuilder().type(HikariDataSource::class.java).build()
}
}
Relevent R2DBC configutation:
abstract class R2DbcConfiguration : AbstractR2dbcConfiguration() {
override fun getCustomConverters(): MutableList<Any> {
return mutableListOf(
// some custom converters
)
}
@Bean
fun connectionFactoryInitializer(
factory: ConnectionFactory
): ConnectionFactoryInitializer {
val init = ConnectionFactoryInitializer()
init.setConnectionFactory(factory)
val populator = CompositeDatabasePopulator()
populator.addPopulators(ResourceDatabasePopulator(ClassPathResource("schema.sql")))
init.setDatabasePopulator(populator)
return init
}
}
@Configuration
class ReleaseR2DbcConfiguration : R2DbcConfiguration() {
@Bean
override fun connectionFactory(): ConnectionFactory {
val config = H2ConnectionConfiguration.builder().file("./state").build()
return H2ConnectionFactory(config)
}
}
application.properties:
logging.level.org.springframework.data.r2dbc=DEBUG
logging.level.org.springframework.data.jdbc=DEBUG
spring.quartz.job-store-type=jdbc
spring.quartz.jdbc.initialize-schema=always
spring.datasource.url=jdbc:h2:file:./state