I have setup a gradle Spring boot application where I am trying to execute the build process using a testcontainer.
Here is what I wanted to achieve when I run .gradlew clean build
-
Start a MySql testcontainer
-
Use that testcontainer DB credentials and apply DB migrations using
Liquibase -
Execute generateJooq task connecting to the same testcontainer DB.
-
Execute the integrationTest gradle task against the same
testcontainer DB.
Now I am having issue on the 4th step where I wanted to use the testcontainer DB dbUrl, dbUsername, dbPassword and dbDriver to connect to the testcontainer DB while executing the integrationTest gradle task.
Basically I have a resource folder under intergationTest which has ‘application-dev.properties’ file where it loads the configurations from AWS secrets and param store for the service which includes spring.datasource.username, spring.datasource.password & spring.datasource.url as well.
I am looking for an option to override those threes values with the testcontainer DB credentials.
Here is what I have in the application-dev.properties
spring.config.import=aws-parameterstore:/dev/common/,aws-secretsmanager:dev/common,
aws-parameterstore:/dev/${spring.application.name}/,aws-secretsmanager:dev/${spring.application.name}
management.endpoints.web.exposure.include=info,health
Here is my build.gradle file
plugins {
id 'application'
id 'idea'
id 'jacoco'
id 'org.springframework.boot'
id 'io.spring.dependency-management'
id 'com.diffplug.spotless'
id 'de.undercouch.download'
id 'org.liquibase.gradle'
}
group = 'com.test'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
ext {
dbUrl = ''
dbUsername = ''
dbPassword = ''
dbDriver = ''
}
dependencyManagement {
imports {
mavenBom("io.awspring.cloud:spring-cloud-aws-dependencies:${springCloudAwsVersion}")
mavenBom("org.testcontainers:testcontainers-bom:${testcontainersVersion}")
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter'
implementation 'io.awspring.cloud:spring-cloud-aws-starter-parameter-store'
implementation 'io.awspring.cloud:spring-cloud-aws-starter-secrets-manager'
implementation 'org.apache.commons:commons-lang3'
implementation 'org.springframework.retry:spring-retry'
implementation 'commons-io:commons-io:2.+'
implementation 'com.google.guava:guava:+'
implementation 'com.mysql:mysql-connector-j'
integrationTestImplementation 'org.testcontainers:mysql'
}
apply from: "gradle/dbcontainer.gradle"
apply from: "gradle/liquibase.gradle"
apply from: "gradle/jooq.gradle"
apply from: 'project-build.gradle
Here is my dbcontainer.gradle
import org.testcontainers.containers.MySQLContainer;
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.testcontainers:testcontainers:${testcontainersVersion}"
classpath "org.testcontainers:mysql:${testcontainersVersion}"
classpath "com.mysql:mysql-connector-j:8.4.0"
}
}
def mysqlContainer = new MySQLContainer("mysql:8.0.36").withDatabaseName("lmsdb")
tasks.register('startMySQLContainer') {
doLast {
mysqlContainer.start()
project.ext.dbUrl = mysqlContainer.getJdbcUrl()
project.ext.dbUsername = mysqlContainer.getUsername()
project.ext.dbPassword = mysqlContainer.getPassword()
project.ext.dbDriver = mysqlContainer.getDriverClassName()
println("--- MySql Test container started successfully with URL : ${project.ext.dbUrl}")
}
}
tasks.register('stopMySqlContainer') {
doLast {
if (mysqlContainer) {
mysqlContainer.stop()
println("----MySql Test container stopped successfully")
}
}
}
// Ensure the integrationTest uses the same container and stops it after
tasks.named('integrationTest').configure {
dependsOn 'generateJooq'
finalizedBy 'stopMySqlContainer'
}
// Ensure stopMySqlContainer runs after integrationTest
tasks.named('integrationTest').configure {
finalizedBy 'stopMySqlContainer'
}
Here is my liquibase.gradle
configurations {
liquibaseRuntime.extendsFrom runtimeClasspath
}
dependencies {
liquibaseRuntime sourceSets.main.output
runtimeOnly 'org.liquibase:liquibase-core'
implementation 'info.picocli:picocli:4.7.6'
}
tasks.named('startMySQLContainer').configure {
doLast {
liquibase {
activities {
main {
changelogFile 'liquibase/db1/tc_changelog.yml'
url project.ext.dbUrl
username project.ext.dbUsername
password project.ext.dbPassword
}
}
runList = 'main'
}
}
}
tasks.named('update') {
dependsOn ':startMySQLContainer'
}
Here is my jooq.gradle
import nu.studer.gradle.jooq.JooqGenerate
buildscript {
repositories {
gradlePluginPortal()
}
dependencies {
classpath "nu.studer:gradle-jooq-plugin:${jooqPluginVersion}"
}
ext {
// use jOOQ version defined in Spring Boot
jooqVersion = dependencyManagement.importedProperties['jooq.version']
}
configurations.classpath {
// Enforce the jOOQ configuration XML schema version
resolutionStrategy.eachDependency {
if (requested.group == 'org.jooq' && requested.name.startsWith('jooq')) {
useVersion jooqVersion
}
}
}
}
apply plugin: nu.studer.gradle.jooq.JooqPlugin
// JOOQ dependencies
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-jooq'
jooqGenerator 'com.mysql:mysql-connector-j'
jooqGenerator 'org.slf4j:slf4j-simple'
jooqGenerator 'com.fasterxml.jackson.core:jackson-databind'
jooqGenerator "org.testcontainers:mysql"
jooqGenerator 'org.testcontainers:jdbc'
}
// Configure JOOQ
jooq {
version = jooqVersion
configurations {
main {
generationTool {
logging = org.jooq.meta.jaxb.Logging.WARN
jdbc {
driver = 'com.mysql.cj.jdbc.Driver'
}
generator {
name = 'org.jooq.codegen.DefaultGenerator'
database {
name = 'org.jooq.meta.mysql.MySQLDatabase'
inputSchema = 'lmsdb'
}
generate {
records = true
immutablePojos = true
fluentSetters = true
javaTimeTypes = false
}
target {
packageName = "com.test.sample.db"
}
= 'org.jooq.codegen.DefaultGeneratorStrategy'
}
}
}
}
}
tasks.register('configureJooq') {
dependsOn 'startMySQLContainer', 'update'
doLast {
jooq.configurations.main {
generationTool {
jdbc {
url = project.ext.dbUrl
user = project.ext.dbUsername
password = project.ext.dbPassword
driver = project.ext.dbDriver
}
}
}
}
}
// Configure the JVM used for the JOOQ code generation process
tasks.withType(JooqGenerate).configureEach {
javaExecSpec = { JavaExecSpec s ->
s.systemProperties
}
}
tasks.named('generateJooq') {
dependsOn 'configureJooq'
}
Thanks in advance. Please let me know how I can override and use those values to execute the integrationTest task.