Skip to content

Commit a8f70d2

Browse files
committed
Upgrade to Spring Boot 3.2. Refactor to use ServiceConnection and ConnectionDetails. Configuration now engaged by default.
1 parent a945975 commit a8f70d2

File tree

10 files changed

+78
-40
lines changed

10 files changed

+78
-40
lines changed

pom.xml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
<dependency>
4949
<groupId>org.springframework.boot</groupId>
5050
<artifactId>spring-boot-dependencies</artifactId>
51-
<version>3.1.2</version>
51+
<version>3.2.0</version>
5252
<type>pom</type>
5353
<scope>import</scope>
5454
</dependency>
@@ -65,14 +65,16 @@
6565
<artifactId>spring-boot-configuration-processor</artifactId>
6666
</dependency>
6767
<dependency>
68-
<groupId>org.testcontainers</groupId>
69-
<artifactId>postgresql</artifactId>
70-
<version>1.18.3</version>
68+
<groupId>org.springframework.boot</groupId>
69+
<artifactId>spring-boot-starter-test</artifactId>
7170
</dependency>
7271
<dependency>
7372
<groupId>org.springframework.boot</groupId>
74-
<artifactId>spring-boot-starter-test</artifactId>
75-
<scope>test</scope>
73+
<artifactId>spring-boot-testcontainers</artifactId>
74+
</dependency>
75+
<dependency>
76+
<groupId>org.testcontainers</groupId>
77+
<artifactId>postgresql</artifactId>
7678
</dependency>
7779
<dependency>
7880
<groupId>org.springframework.boot</groupId>

src/main/java/org/quinnandrews/spring/local/postgresql/config/PostgreSQLContainerConfig.java

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,14 @@
88
import org.slf4j.LoggerFactory;
99
import org.springframework.beans.factory.annotation.Value;
1010
import 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;
1213
import org.springframework.context.annotation.Bean;
1314
import org.springframework.context.annotation.Configuration;
14-
import org.springframework.context.annotation.Primary;
1515
import org.testcontainers.containers.PostgreSQLContainer;
1616
import org.testcontainers.containers.output.Slf4jLogConsumer;
1717
import org.testcontainers.utility.DockerImageName;
1818

19-
import javax.sql.DataSource;
2019
import java.text.MessageFormat;
2120
import java.util.Optional;
2221

@@ -31,7 +30,8 @@
3130
* @author Quinn Andrews
3231
*/
3332
@ConditionalOnProperty(name="spring.local.postgresql.engaged",
34-
havingValue="true")
33+
havingValue="true",
34+
matchIfMissing = true)
3535
@Configuration
3636
public 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
}

src/main/resources/META-INF/additional-spring-configuration-metadata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"name": "spring.local.postgresql.engaged",
55
"type": "java.lang.Boolean",
66
"description": "Whether the embedded, containerized PostgreSQL database should be configured to start when the Application starts.",
7-
"defaultValue": false
7+
"defaultValue": true
88
},
99
{
1010
"name": "spring.local.postgresql.container.image",
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
@ActiveProfiles("appuser")
2323
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
2424
@SpringBootTest(classes = Application.class)
25-
public class AppuserPostgreSQLContainerConfigTest {
25+
public class AppUserPostgreSQLContainerConfigTest {
2626

2727
@Autowired(required = false)
2828
private PostgreSQLContainer<?> postgreSQLContainer;

src/test/java/org/quinnandrews/spring/local/postgresql/CustomPostgreSQLContainerConfigTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package org.quinnandrews.spring.local.postgresql;
22

3-
import static org.junit.jupiter.api.Assertions.*;
4-
53
import com.zaxxer.hikari.HikariDataSource;
64
import org.junit.jupiter.api.MethodOrderer;
75
import org.junit.jupiter.api.Order;
@@ -18,6 +16,8 @@
1816

1917
import javax.sql.DataSource;
2018

19+
import static org.junit.jupiter.api.Assertions.*;
20+
2121
@DirtiesContext
2222
@ActiveProfiles("custom")
2323
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)

src/test/java/org/quinnandrews/spring/local/postgresql/DefaultPostgreSQLContainerConfigTest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
import org.junit.jupiter.api.Test;
77
import org.junit.jupiter.api.TestMethodOrder;
88
import org.quinnandrews.spring.local.postgresql.application.Application;
9-
import org.quinnandrews.spring.local.postgresql.config.PostgreSQLContainerConfig;
109
import org.quinnandrews.spring.local.postgresql.application.data.guitarpedals.repository.GuitarPedalRepository;
10+
import org.quinnandrews.spring.local.postgresql.config.PostgreSQLContainerConfig;
1111
import org.springframework.beans.factory.annotation.Autowired;
1212
import org.springframework.boot.test.context.SpringBootTest;
1313
import org.springframework.data.domain.Sort;
@@ -18,7 +18,6 @@
1818
import javax.sql.DataSource;
1919

2020
import static org.junit.jupiter.api.Assertions.*;
21-
import static org.junit.jupiter.api.Assertions.assertEquals;
2221

2322
@DirtiesContext
2423
@ActiveProfiles("default")

src/test/java/org/quinnandrews/spring/local/postgresql/application/data/guitarpedals/GuitarPedal.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package org.quinnandrews.spring.local.postgresql.application.data.guitarpedals;
22

3-
import jakarta.persistence.*;
3+
import jakarta.persistence.Column;
4+
import jakarta.persistence.Entity;
5+
import jakarta.persistence.Id;
6+
import jakarta.persistence.Table;
47

58
@Table(name = "guitar_pedal")
69
@Entity

src/test/resources/application-appuser.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11

2-
spring.local.postgresql.engaged=true
2+
# Engaged by default. No need to set this property to true
3+
#spring.local.postgresql.engaged=true
4+
35
spring.local.postgresql.container.image=postgres:15
46
spring.local.postgresql.container.port=15432
57
spring.local.postgresql.database.name=pedals

src/test/resources/application-custom.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11

2-
spring.local.postgresql.engaged=true
2+
# Engaged by default. No need to set this property to true
3+
#spring.local.postgresql.engaged=true
4+
35
spring.local.postgresql.container.image=postgres:15
46
spring.local.postgresql.container.port=15432
57
spring.local.postgresql.database.name=pedals
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11

2-
spring.local.postgresql.engaged=true
2+
# Engaged by default. No need to set this property to true
3+
# spring.local.postgresql.engaged=true

0 commit comments

Comments
 (0)