How to configure the jdbcUrl/username/password using properties from other tasks/buildservices
stackunderflow111 opened this issue · 0 comments
Hi,
I want to integrate this plugin with testcontainers so that our Jooq code is generated against a live testcontainers database. I think the best way to achieve it is to use Gradle build services. Currently, we have two build services ready.
- we have a
postgresContainer
buildservice which starts a postgres container using testcontainers. This build service provides the jdbcUrl, username and password of the started container. - We also have a
flywayMigratedDatabase
buildservice which runs flyway migration against a database. This build service is configured to use thepostgresContainer
build service and it also provides the jdbcUrl, username and password of the migrated database
My question is: how to configure the generateJooq
task to use the jdbcUrl, username and password from the flywayMigratedDatabase
build service? It might be easy if the jooqConfiguration
field is a Property
, but it's not. Is there any other approach that configures the generateJooq
task to use a data source from other tasks/build services?
We have tried to add a separate configuring task which looks like the following:
abstract public class ConfigureDatabaseTask extends DefaultTask {
@Internal
public abstract Property<String> getJdbcUrl();
@Internal
public abstract Property<String> getUsername();
@Internal
public abstract Property<String> getPassword();
}
Then, in build.gradle.kts
we configure the generateJooq
task in the doLast
block of the ConfigureDatabaseTask
and make genearteJooq
depends on it.
val configureGenerateJooq = tasks.register<ConfigureDatabaseTask>("configureGenerateJooq") {
jdbcUrl.set(flywayMigratedDatabase.map { it.jdbcUrl })
username.set(flywayMigratedDatabase.map { it.username })
password.set(flywayMigratedDatabase.map { it.password })
usesService(flywayMigratedDatabase)
doLast {
this as ConfigureDatabaseTask
val jdbcUrl = jdbcUrl.get()
val username = username.get()
val password = password.get()
tasks.named<JooqGenerate>("generateJooq") {
// this is the same as val jooqConfiguration = jooqGenerate.jooqConfiguration,
// but it's a private field, so I have to bypass the access restriction using reflection
val jooqConfigurationField = JooqGenerate::class.java.getDeclaredField("jooqConfiguration")
jooqConfigurationField.isAccessible = true
val jooqConfiguration = jooqConfigurationField.get(this) as Configuration
jooqConfiguration.jdbc.apply {
this.url = jdbcUrl
this.user = username
this.password = password
}
}
}
}
tasks.named<JooqGenerate>("generateJooq") {
// Make the generateJooq task dependent on the migration scripts so we get proper build caching
// (trigger a clean rebuild only when the files change)
inputs.files(fileTree(migrationFilesLocation))
.withPropertyName("migrations")
.withPathSensitivity(PathSensitivity.RELATIVE)
// Let the task participate in incremental builds and build caching
allInputsDeclared.set(true)
outputs.cacheIf {
true
}
dependsOn(configureGenerateJooq)
}
The problem is that this approach doesn't work well with incremental build. generateJooq
is never up-to-date even when the migration files in migrationFilesLocation
do not change. The reason seems to be that configureGenerateJooq
make modifications to it.