Using a Persistent Quartz Scheduler while also using R2DBC in Spring Boot
Asked Answered
Z

0

6

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
Zora answered 19/5, 2020 at 7:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.