From 8bbe894665050e43930988457c41122a8d47da40 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 27 Apr 2023 09:30:10 +0100 Subject: [PATCH] Add Docker Compose service connection support for Oracle using JDBC Closes gh-35145 --- ...DockerComposeConnectionDetailsFactory.java | 87 +++++++++++++++++++ .../main/resources/META-INF/spring.factories | 1 + ...nectionDetailsFactoryIntegrationTests.java | 61 +++++++++++++ .../asciidoc/features/docker-compose.adoc | 2 +- 4 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleJdbcDockerComposeConnectionDetailsFactory.java create mode 100644 spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleJdbcDockerComposeConnectionDetailsFactoryIntegrationTests.java diff --git a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleJdbcDockerComposeConnectionDetailsFactory.java b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleJdbcDockerComposeConnectionDetailsFactory.java new file mode 100644 index 00000000000..9104a9ff267 --- /dev/null +++ b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleJdbcDockerComposeConnectionDetailsFactory.java @@ -0,0 +1,87 @@ +/* + * Copyright 2012-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.docker.compose.service.connection.oracle; + +import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails; +import org.springframework.boot.docker.compose.core.RunningService; +import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionDetailsFactory; +import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionSource; +import org.springframework.util.StringUtils; + +/** + * {@link DockerComposeConnectionDetailsFactory} to create {@link JdbcConnectionDetails} + * for an {@code oracle-xe} service. + * + * @author Moritz Halbritter + * @author Andy Wilkinson + * @author Phillip Webb + */ +class OracleJdbcDockerComposeConnectionDetailsFactory + extends DockerComposeConnectionDetailsFactory { + + protected OracleJdbcDockerComposeConnectionDetailsFactory() { + super("gvenzl/oracle-xe"); + } + + @Override + protected JdbcConnectionDetails getDockerComposeConnectionDetails(DockerComposeConnectionSource source) { + return new OracleJdbcDockerComposeConnectionDetails(source.getRunningService()); + } + + /** + * {@link JdbcConnectionDetails} backed by an {@code oracle-xe} + * {@link RunningService}. + */ + static class OracleJdbcDockerComposeConnectionDetails extends DockerComposeConnectionDetails + implements JdbcConnectionDetails { + + private static final String PARAMETERS_LABEL = "org.springframework.boot.jdbc.parameters"; + + private final OracleEnvironment environment; + + private final String jdbcUrl; + + OracleJdbcDockerComposeConnectionDetails(RunningService service) { + super(service); + this.environment = new OracleEnvironment(service.env()); + this.jdbcUrl = "jdbc:oracle:thin:@" + service.host() + ":" + service.ports().get(1521) + "/" + + this.environment.getDatabase() + getParameters(service); + } + + private String getParameters(RunningService service) { + String parameters = service.labels().get(PARAMETERS_LABEL); + return (StringUtils.hasLength(parameters)) ? "?" + parameters : ""; + } + + @Override + public String getUsername() { + return this.environment.getUsername(); + } + + @Override + public String getPassword() { + return this.environment.getPassword(); + } + + @Override + public String getJdbcUrl() { + return this.jdbcUrl; + } + + } + +} diff --git a/spring-boot-project/spring-boot-docker-compose/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot-docker-compose/src/main/resources/META-INF/spring.factories index 0060464f917..8459f612d2a 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot-docker-compose/src/main/resources/META-INF/spring.factories @@ -12,6 +12,7 @@ org.springframework.boot.docker.compose.service.connection.mariadb.MariaDbR2dbcD org.springframework.boot.docker.compose.service.connection.mongo.MongoDockerComposeConnectionDetailsFactory,\ org.springframework.boot.docker.compose.service.connection.mysql.MySqlJdbcDockerComposeConnectionDetailsFactory,\ org.springframework.boot.docker.compose.service.connection.mysql.MySqlR2dbcDockerComposeConnectionDetailsFactory,\ +org.springframework.boot.docker.compose.service.connection.oracle.OracleJdbcDockerComposeConnectionDetailsFactory,\ org.springframework.boot.docker.compose.service.connection.oracle.OracleR2dbcDockerComposeConnectionDetailsFactory,\ org.springframework.boot.docker.compose.service.connection.postgres.PostgresJdbcDockerComposeConnectionDetailsFactory,\ org.springframework.boot.docker.compose.service.connection.postgres.PostgresR2dbcDockerComposeConnectionDetailsFactory,\ diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleJdbcDockerComposeConnectionDetailsFactoryIntegrationTests.java b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleJdbcDockerComposeConnectionDetailsFactoryIntegrationTests.java new file mode 100644 index 00000000000..ef45bbaabf5 --- /dev/null +++ b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleJdbcDockerComposeConnectionDetailsFactoryIntegrationTests.java @@ -0,0 +1,61 @@ +/* + * Copyright 2012-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.docker.compose.service.connection.oracle; + +import java.sql.Driver; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails; +import org.springframework.boot.docker.compose.service.connection.test.AbstractDockerComposeIntegrationTests; +import org.springframework.boot.jdbc.DatabaseDriver; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.SimpleDriverDataSource; +import org.springframework.util.ClassUtils; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Integration tests for {@link OracleJdbcDockerComposeConnectionDetailsFactory} + * + * @author Andy Wilkinson + */ +class OracleJdbcDockerComposeConnectionDetailsFactoryIntegrationTests extends AbstractDockerComposeIntegrationTests { + + OracleJdbcDockerComposeConnectionDetailsFactoryIntegrationTests() { + super("oracle-compose.yaml"); + } + + @Test + @SuppressWarnings("unchecked") + void runCreatesConnectionDetailsThatCanBeUsedToAccessDatabase() throws Exception { + JdbcConnectionDetails connectionDetails = run(JdbcConnectionDetails.class); + assertThat(connectionDetails.getUsername()).isEqualTo("system"); + assertThat(connectionDetails.getPassword()).isEqualTo("secret"); + assertThat(connectionDetails.getJdbcUrl()).startsWith("jdbc:oracle:thin:@").endsWith("/xepdb1"); + SimpleDriverDataSource dataSource = new SimpleDriverDataSource(); + dataSource.setUrl(connectionDetails.getJdbcUrl()); + dataSource.setUsername(connectionDetails.getUsername()); + dataSource.setPassword(connectionDetails.getPassword()); + dataSource.setDriverClass((Class) ClassUtils.forName(connectionDetails.getDriverClassName(), + getClass().getClassLoader())); + JdbcTemplate template = new JdbcTemplate(dataSource); + assertThat(template.queryForObject(DatabaseDriver.ORACLE.getValidationQuery(), String.class)) + .isEqualTo("Hello"); + } + +} diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/docker-compose.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/docker-compose.adoc index 0a449d34aa4..80bbac1a28e 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/docker-compose.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/docker-compose.adoc @@ -44,7 +44,7 @@ The following service connections are currently supported: | Containers named "elasticsearch" | `JdbcConnectionDetails` -| Containers named "mariadb", "mssql/server", "mysql", or "postgres" +| Containers named "gvenzl/oracle-xe", "mariadb", "mssql/server", "mysql", or "postgres" | `MongoConnectionDetails` | Containers named "mongo"