Skip to content

Commit 6c3dec4

Browse files
committed
Add container support for Oracle Free which replaces Oracle XE
Update Docker Compose and Testcontainers support to work with `gvenzl/oracle-free` which replaces `gvenzl/oracle-xe`. Closes gh-38476
1 parent 0897d75 commit 6c3dec4

File tree

18 files changed

+343
-19
lines changed

18 files changed

+343
-19
lines changed

spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/ConnectionNamePredicate.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,33 @@
1616

1717
package org.springframework.boot.docker.compose.service.connection;
1818

19+
import java.util.Arrays;
20+
import java.util.Set;
1921
import java.util.function.Predicate;
22+
import java.util.stream.Collectors;
2023

2124
import org.springframework.boot.docker.compose.core.ImageReference;
2225
import org.springframework.boot.docker.compose.core.RunningService;
26+
import org.springframework.util.Assert;
2327

2428
/**
25-
* {@link Predicate} that matches against connection names.
29+
* {@link Predicate} that matches against connection name.
2630
*
2731
* @author Phillip Webb
2832
*/
2933
class ConnectionNamePredicate implements Predicate<DockerComposeConnectionSource> {
3034

31-
private final String required;
35+
private final Set<String> required;
3236

33-
ConnectionNamePredicate(String required) {
34-
this.required = asCanonicalName(required);
37+
ConnectionNamePredicate(String... required) {
38+
Assert.notEmpty(required, "Required must not be empty");
39+
this.required = Arrays.stream(required).map(this::asCanonicalName).collect(Collectors.toSet());
3540
}
3641

3742
@Override
3843
public boolean test(DockerComposeConnectionSource source) {
3944
String actual = getActual(source.getRunningService());
40-
return this.required.equals(actual);
45+
return this.required.contains(actual);
4146
}
4247

4348
private String getActual(RunningService service) {

spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/DockerComposeConnectionDetailsFactory.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,16 @@ protected DockerComposeConnectionDetailsFactory(String connectionName, String...
5454
this(new ConnectionNamePredicate(connectionName), requiredClassNames);
5555
}
5656

57+
/**
58+
* Create a new {@link DockerComposeConnectionDetailsFactory} instance.
59+
* @param connectionNames the required connection name
60+
* @param requiredClassNames the names of classes that must be present
61+
* @since 3.2.0
62+
*/
63+
protected DockerComposeConnectionDetailsFactory(String[] connectionNames, String... requiredClassNames) {
64+
this(new ConnectionNamePredicate(connectionNames), requiredClassNames);
65+
}
66+
5767
/**
5868
* Create a new {@link DockerComposeConnectionDetailsFactory} instance.
5969
* @param predicate a predicate used to check when a service is accepted

spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleEnvironment.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
*/
2929
class OracleEnvironment {
3030

31+
static final String[] CONTAINER_NAMES = { "gvenzl/oracle-xe", "gvenzl/oracle-free" };
32+
3133
private final String username;
3234

3335
private final String password;

spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleJdbcDockerComposeConnectionDetailsFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class OracleJdbcDockerComposeConnectionDetailsFactory
3434
extends DockerComposeConnectionDetailsFactory<JdbcConnectionDetails> {
3535

3636
protected OracleJdbcDockerComposeConnectionDetailsFactory() {
37-
super("gvenzl/oracle-xe");
37+
super(OracleEnvironment.CONTAINER_NAMES);
3838
}
3939

4040
@Override

spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleR2dbcDockerComposeConnectionDetailsFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class OracleR2dbcDockerComposeConnectionDetailsFactory
3636
extends DockerComposeConnectionDetailsFactory<R2dbcConnectionDetails> {
3737

3838
OracleR2dbcDockerComposeConnectionDetailsFactory() {
39-
super("gvenzl/oracle-xe", "io.r2dbc.spi.ConnectionFactoryOptions");
39+
super(OracleEnvironment.CONTAINER_NAMES, "io.r2dbc.spi.ConnectionFactoryOptions");
4040
}
4141

4242
@Override

spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/ConnectionNamePredicateTests.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,14 @@ void labeled() {
7474
.accepts(sourceOf("internalhost:8080/libs/libs/mzipkin", "openzipkin/zipkin"));
7575
}
7676

77-
private Predicate<DockerComposeConnectionSource> predicateOf(String required) {
77+
@Test
78+
void multiple() {
79+
assertThat(predicateOf("elasticsearch1", "elasticsearch2")).accepts(sourceOf("elasticsearch1"))
80+
.accepts(sourceOf("elasticsearch2"));
81+
82+
}
83+
84+
private Predicate<DockerComposeConnectionSource> predicateOf(String... required) {
7885
return new ConnectionNamePredicate(required);
7986
}
8087

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright 2012-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.docker.compose.service.connection.oracle;
18+
19+
import java.sql.Driver;
20+
import java.time.Duration;
21+
22+
import org.awaitility.Awaitility;
23+
import org.junit.jupiter.api.Test;
24+
import org.junit.jupiter.api.condition.OS;
25+
26+
import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
27+
import org.springframework.boot.docker.compose.service.connection.test.AbstractDockerComposeIntegrationTests;
28+
import org.springframework.boot.jdbc.DatabaseDriver;
29+
import org.springframework.boot.testsupport.junit.DisabledOnOs;
30+
import org.springframework.boot.testsupport.testcontainers.DockerImageNames;
31+
import org.springframework.jdbc.core.JdbcTemplate;
32+
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
33+
import org.springframework.util.ClassUtils;
34+
35+
import static org.assertj.core.api.Assertions.assertThat;
36+
37+
/**
38+
* Integration tests for {@link OracleJdbcDockerComposeConnectionDetailsFactory}
39+
*
40+
* @author Andy Wilkinson
41+
*/
42+
@DisabledOnOs(os = { OS.LINUX, OS.MAC }, architecture = "aarch64",
43+
disabledReason = "The Oracle image has no ARM support")
44+
class OracleFreeJdbcDockerComposeConnectionDetailsFactoryIntegrationTests
45+
extends AbstractDockerComposeIntegrationTests {
46+
47+
OracleFreeJdbcDockerComposeConnectionDetailsFactoryIntegrationTests() {
48+
super("oracle-compose.yaml", DockerImageNames.oracleFree());
49+
}
50+
51+
@Test
52+
@SuppressWarnings("unchecked")
53+
void runCreatesConnectionDetailsThatCanBeUsedToAccessDatabase() throws Exception {
54+
JdbcConnectionDetails connectionDetails = run(JdbcConnectionDetails.class);
55+
assertThat(connectionDetails.getUsername()).isEqualTo("app_user");
56+
assertThat(connectionDetails.getPassword()).isEqualTo("app_user_secret");
57+
assertThat(connectionDetails.getJdbcUrl()).startsWith("jdbc:oracle:thin:@").endsWith("/xepdb1");
58+
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
59+
dataSource.setUrl(connectionDetails.getJdbcUrl());
60+
dataSource.setUsername(connectionDetails.getUsername());
61+
dataSource.setPassword(connectionDetails.getPassword());
62+
dataSource.setDriverClass((Class<? extends Driver>) ClassUtils.forName(connectionDetails.getDriverClassName(),
63+
getClass().getClassLoader()));
64+
Awaitility.await().atMost(Duration.ofMinutes(1)).ignoreExceptions().untilAsserted(() -> {
65+
JdbcTemplate template = new JdbcTemplate(dataSource);
66+
assertThat(template.queryForObject(DatabaseDriver.ORACLE.getValidationQuery(), String.class))
67+
.isEqualTo("Hello");
68+
});
69+
}
70+
71+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright 2012-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.docker.compose.service.connection.oracle;
18+
19+
import java.time.Duration;
20+
21+
import io.r2dbc.spi.ConnectionFactories;
22+
import io.r2dbc.spi.ConnectionFactoryOptions;
23+
import org.awaitility.Awaitility;
24+
import org.junit.jupiter.api.Test;
25+
import org.junit.jupiter.api.condition.OS;
26+
27+
import org.springframework.boot.autoconfigure.r2dbc.R2dbcConnectionDetails;
28+
import org.springframework.boot.docker.compose.service.connection.test.AbstractDockerComposeIntegrationTests;
29+
import org.springframework.boot.jdbc.DatabaseDriver;
30+
import org.springframework.boot.testsupport.junit.DisabledOnOs;
31+
import org.springframework.boot.testsupport.testcontainers.DockerImageNames;
32+
import org.springframework.r2dbc.core.DatabaseClient;
33+
34+
import static org.assertj.core.api.Assertions.assertThat;
35+
36+
/**
37+
* Integration tests for {@link OracleR2dbcDockerComposeConnectionDetailsFactory}
38+
*
39+
* @author Andy Wilkinson
40+
*/
41+
@DisabledOnOs(os = { OS.LINUX, OS.MAC }, architecture = "aarch64",
42+
disabledReason = "The Oracle image has no ARM support")
43+
class OracleFreeR2dbcDockerComposeConnectionDetailsFactoryIntegrationTests
44+
extends AbstractDockerComposeIntegrationTests {
45+
46+
OracleFreeR2dbcDockerComposeConnectionDetailsFactoryIntegrationTests() {
47+
super("oracle-compose.yaml", DockerImageNames.oracleFree());
48+
}
49+
50+
@Test
51+
void runCreatesConnectionDetailsThatCanBeUsedToAccessDatabase() {
52+
R2dbcConnectionDetails connectionDetails = run(R2dbcConnectionDetails.class);
53+
ConnectionFactoryOptions connectionFactoryOptions = connectionDetails.getConnectionFactoryOptions();
54+
assertThat(connectionFactoryOptions.toString()).contains("database=xepdb1", "driver=oracle",
55+
"password=REDACTED", "user=app_user");
56+
assertThat(connectionFactoryOptions.getRequiredValue(ConnectionFactoryOptions.PASSWORD))
57+
.isEqualTo("app_user_secret");
58+
Awaitility.await().atMost(Duration.ofMinutes(1)).ignoreExceptions().untilAsserted(() -> {
59+
Object result = DatabaseClient.create(ConnectionFactories.get(connectionFactoryOptions))
60+
.sql(DatabaseDriver.ORACLE.getValidationQuery())
61+
.map((row, metadata) -> row.get(0))
62+
.first()
63+
.block(Duration.ofSeconds(30));
64+
assertThat(result).isEqualTo("Hello");
65+
});
66+
}
67+
68+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@
4141
*/
4242
@DisabledOnOs(os = { OS.LINUX, OS.MAC }, architecture = "aarch64",
4343
disabledReason = "The Oracle image has no ARM support")
44-
class OracleJdbcDockerComposeConnectionDetailsFactoryIntegrationTests extends AbstractDockerComposeIntegrationTests {
44+
class OracleXeJdbcDockerComposeConnectionDetailsFactoryIntegrationTests extends AbstractDockerComposeIntegrationTests {
4545

46-
OracleJdbcDockerComposeConnectionDetailsFactoryIntegrationTests() {
46+
OracleXeJdbcDockerComposeConnectionDetailsFactoryIntegrationTests() {
4747
super("oracle-compose.yaml", DockerImageNames.oracleXe());
4848
}
4949

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@
4040
*/
4141
@DisabledOnOs(os = { OS.LINUX, OS.MAC }, architecture = "aarch64",
4242
disabledReason = "The Oracle image has no ARM support")
43-
class OracleR2dbcDockerComposeConnectionDetailsFactoryIntegrationTests extends AbstractDockerComposeIntegrationTests {
43+
class OracleXeR2dbcDockerComposeConnectionDetailsFactoryIntegrationTests extends AbstractDockerComposeIntegrationTests {
4444

45-
OracleR2dbcDockerComposeConnectionDetailsFactoryIntegrationTests() {
45+
OracleXeR2dbcDockerComposeConnectionDetailsFactoryIntegrationTests() {
4646
super("oracle-compose.yaml", DockerImageNames.oracleXe());
4747
}
4848

0 commit comments

Comments
 (0)