88import org .slf4j .LoggerFactory ;
99import org .springframework .beans .factory .annotation .Value ;
1010import org .springframework .boot .autoconfigure .condition .ConditionalOnProperty ;
11- import org .springframework .boot .jdbc .DataSourceBuilder ;
11+ import org .springframework .boot .autoconfigure .jdbc .JdbcConnectionDetails ;
12+ import org .springframework .boot .testcontainers .service .connection .ServiceConnection ;
1213import org .springframework .context .annotation .Bean ;
1314import org .springframework .context .annotation .Configuration ;
14- import org .springframework .context .annotation .Primary ;
1515import org .testcontainers .containers .PostgreSQLContainer ;
1616import org .testcontainers .containers .output .Slf4jLogConsumer ;
1717import org .testcontainers .utility .DockerImageName ;
1818
19- import javax .sql .DataSource ;
2019import java .text .MessageFormat ;
2120import java .util .Optional ;
2221
3130 * @author Quinn Andrews
3231 */
3332@ ConditionalOnProperty (name ="spring.local.postgresql.engaged" ,
34- havingValue ="true" )
33+ havingValue ="true" ,
34+ matchIfMissing = true )
3535@ Configuration
3636public class PostgreSQLContainerConfig {
3737
@@ -48,8 +48,6 @@ public class PostgreSQLContainerConfig {
4848 private final String databaseName ;
4949 private final String username ;
5050 private final String password ;
51- private final String applicationUsername ;
52- private final String applicationPassword ;
5351 private final String initScript ;
5452
5553 /**
@@ -61,10 +59,6 @@ public class PostgreSQLContainerConfig {
6159 * @param databaseName The name for the database (optional).
6260 * @param username The username of the database super/admin user (optional).
6361 * @param password The password for the database super/admin user (optional).
64- * @param applicationUsername The username of the database user the Application should connect with,
65- * if different from the super/admin user (optional).
66- * @param applicationPassword The password for the database user the Application should connect with,
67- * if different from the super/admin user (optional).
6862 * @param initScript The path to an SQL script that should be executed when the Container
6963 * starts (optional).
7064 */
@@ -80,10 +74,6 @@ public PostgreSQLContainerConfig(@Value("${spring.local.postgresql.container.ima
8074 final String username ,
8175 @ Value ("${spring.local.postgresql.database.password:#{null}}" )
8276 final String password ,
83- @ Value ("${spring.local.postgresql.database.application.username:#{null}}" )
84- final String applicationUsername ,
85- @ Value ("${spring.local.postgresql.database.application.password:#{null}}" )
86- final String applicationPassword ,
8777 @ Value ("${spring.local.postgresql.database.init.script:#{null}}" )
8878 final String initScript ) {
8979 this .containerImage = containerImage ;
@@ -92,8 +82,6 @@ public PostgreSQLContainerConfig(@Value("${spring.local.postgresql.container.ima
9282 this .databaseName = databaseName ;
9383 this .username = username ;
9484 this .password = password ;
95- this .applicationUsername = applicationUsername ;
96- this .applicationPassword = applicationPassword ;
9785 this .initScript = initScript ;
9886 }
9987
@@ -104,6 +92,7 @@ public PostgreSQLContainerConfig(@Value("${spring.local.postgresql.container.ima
10492 * @return PostgreSQLContainer
10593 */
10694 @ Bean
95+ @ ServiceConnection
10796 public PostgreSQLContainer <?> postgreSQLContainer () {
10897 final var container = new PostgreSQLContainer <>(
10998 DockerImageName .parse (Optional .ofNullable (containerImage )
@@ -157,17 +146,57 @@ Use the credentials below to connect your client of choice (DBeaver,
157146 /**
158147 * Initializes a Spring Bean connecting the Application to the PostgreSQLContainer.
159148 *
149+ * @param applicationUsername The username of the database user the Application should connect with,
150+ * if different from the super/admin user (optional).
151+ * @param applicationPassword The password for the database user the Application should connect with,
152+ * if different from the super/admin user (optional).
160153 * @param container The instance of PostgreSQLContainer to build the DataSource with.
161154 * @return DataSource
162155 */
163- @ Primary
164156 @ Bean
165- public DataSource dataSource (final PostgreSQLContainer <?> container ) {
166- return DataSourceBuilder .create ()
167- .url (container .getJdbcUrl ())
168- .username (Optional .ofNullable (applicationUsername ).orElse (container .getUsername ()))
169- .password (Optional .ofNullable (applicationPassword ).orElse (container .getPassword ()))
170- .driverClassName (container .getDriverClassName ())
171- .build ();
157+ public JdbcConnectionDetails jdbcConnectionDetails (@ Value ("${spring.local.postgresql.database.application.username:#{null}}" )
158+ final String applicationUsername ,
159+ @ Value ("${spring.local.postgresql.database.application.password:#{null}}" )
160+ final String applicationPassword ,
161+ final PostgreSQLContainer <?> container ) {
162+ return new LocalPostgreSQLConnectionDetails (applicationUsername , applicationPassword , container );
163+ }
164+
165+
166+ public static class LocalPostgreSQLConnectionDetails implements JdbcConnectionDetails {
167+
168+ private final String applicationUsername ;
169+ private final String applicationPassword ;
170+ private final PostgreSQLContainer <?> container ;
171+
172+ public LocalPostgreSQLConnectionDetails (final String applicationUsername ,
173+ final String applicationPassword ,
174+ final PostgreSQLContainer <?> container ) {
175+ this .applicationUsername = applicationUsername ;
176+ this .applicationPassword = applicationPassword ;
177+ this .container = container ;
178+ }
179+
180+ @ Override
181+ public String getUsername () {
182+ return Optional .ofNullable (applicationUsername )
183+ .orElse (container .getUsername ());
184+ }
185+
186+ @ Override
187+ public String getPassword () {
188+ return Optional .ofNullable (applicationPassword )
189+ .orElse (container .getPassword ());
190+ }
191+
192+ @ Override
193+ public String getJdbcUrl () {
194+ return container .getJdbcUrl ();
195+ }
196+
197+ @ Override
198+ public String getDriverClassName () {
199+ return container .getDriverClassName ();
200+ }
172201 }
173202}
0 commit comments