Reputation: 3601
I am using multipleDatasources in my spring boot application where we connect to postgres and mysql. it is working as expected but when I want to integrate it with TestContainers in dev mode . I have written code as below
@TestConfiguration(proxyBeanMethods = false)
public class TestMultipleDataSourcesApplication {
@ServiceConnection
@Bean
//@DependsOn("mySQLContainer")
PostgreSQLContainer<?> postgreSQLContainer(DynamicPropertyRegistry dynamicPropertyRegistry) {
PostgreSQLContainer<?> postgreSQLContainer =
new PostgreSQLContainer<>("postgres:16.0-alpine");
dynamicPropertyRegistry.add("app.datasource.member.url", postgreSQLContainer::getJdbcUrl);
dynamicPropertyRegistry.add(
"app.datasource.member.username", postgreSQLContainer::getUsername);
dynamicPropertyRegistry.add(
"app.datasource.member.password", postgreSQLContainer::getPassword);
return postgreSQLContainer;
}
@ServiceConnection
@Bean
MySQLContainer<?> mySQLContainer(DynamicPropertyRegistry dynamicPropertyRegistry) {
MySQLContainer<?> mySQLContainer = new MySQLContainer<>("mysql:8.1");
dynamicPropertyRegistry.add("app.datasource.cardholder.url", mySQLContainer::getJdbcUrl);
dynamicPropertyRegistry.add(
"app.datasource.cardholder.username", mySQLContainer::getUsername);
dynamicPropertyRegistry.add(
"app.datasource.cardholder.password", mySQLContainer::getPassword);
return mySQLContainer;
}
public static void main(String[] args) {
SpringApplication.from(MultipleDataSourcesApplication::main)
.with(TestMultipleDataSourcesApplication.class)
.run(args);
}
}
Only the postgresql Bean is getting started and mySQLContainer is getting discarded. to force start mySQLContainer I have added @DependsOn("mySQLContainer")
on PostgreSQLContainer then it is getting started. My application uses flyway for connecting to mysql and liquibase for connecting to postgres as below
## Flyway uses mysql database
spring.flyway.url=${app.datasource.cardholder.url}
spring.flyway.user=${app.datasource.cardholder.username}
spring.flyway.password=${app.datasource.cardholder.password}
## Liquibase used postgres Database
spring.liquibase.url=${app.datasource.member.url}
spring.liquibase.user=${app.datasource.member.username}
spring.liquibase.password=${app.datasource.member.password}
When starting databases using above method, even my flyway is connecting to postgresqlserver instead of mysqlserver.
What is the correct way to start more than one database related ServiceConnection and how to ensure that after setting the urls it is connecting to correct liquibase or flyway instances?
source code : https://github.com/rajadilipkolli-throwaway/boot-data-multipledatasources
Edit 1:
If you are using spring boot 3.4.0+ then above can be achieve by below code
@TestConfiguration(proxyBeanMethods = false)
public class ContainersConfiguration {
private MySQLContainer<?> mySQLContainer;
private PostgreSQLContainer<?> postgreSQLContainer;
@Bean
MySQLContainer<?> mySQLContainer() {
mySQLContainer = new MySQLContainer<>(DockerImageName.parse("mysql").withTag("9.1"));
mySQLContainer.start();
return mySQLContainer;
}
@Bean
PostgreSQLContainer<?> postgreSQLContainer() {
postgreSQLContainer =
new PostgreSQLContainer<>(DockerImageName.parse("postgres").withTag("17.0-alpine"));
postgreSQLContainer.start();
return postgreSQLContainer;
}
@Bean
public DynamicPropertyRegistrar databaseProperties(
MySQLContainer<?> mySQLContainer, PostgreSQLContainer<?> postgreSQLContainer) {
return (properties) -> {
// Connect our Spring application to our Testcontainers instances
properties.add("app.datasource.cardholder.url", mySQLContainer::getJdbcUrl);
properties.add("app.datasource.cardholder.username", mySQLContainer::getUsername);
properties.add("app.datasource.cardholder.password", mySQLContainer::getPassword);
properties.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl);
properties.add("spring.datasource.username", postgreSQLContainer::getUsername);
properties.add("spring.datasource.password", postgreSQLContainer::getPassword);
};
}
Working code here
Upvotes: 1
Views: 1003
Reputation: 336
Have you tried to define a spring test profile specifiying jdbc url like jdbc:tc:mysql:8.1:///cardholderdb
So Testcontainer's JDBC driver would automatically start the mysql container without your definition in TestMultipleDataSourcesApplication. I'd suggest to do the same for postgres using the jdbc:tc:postgresql:16.0-alpine:///memberdb
see https://java.testcontainers.org/modules/databases/jdbc/ for more details
Upvotes: 0