diff --git a/buildSrc/src/main/java/org/springframework/boot/build/context/properties/DocumentConfigurationProperties.java b/buildSrc/src/main/java/org/springframework/boot/build/context/properties/DocumentConfigurationProperties.java index ac6e3b7b83..e63cf80b6c 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/context/properties/DocumentConfigurationProperties.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/context/properties/DocumentConfigurationProperties.java @@ -82,6 +82,8 @@ public class DocumentConfigurationProperties extends DefaultTask { .withKeyPrefixes("spring.couchbase", "spring.elasticsearch", "spring.h2", "spring.influx", "spring.mongodb", "spring.neo4j", "spring.redis", "spring.dao", "spring.data", "spring.datasource", "spring.jooq", "spring.jdbc", "spring.jpa", "spring.r2dbc") + .addOverride("spring.datasource.oracleucp", + "Oracle UCP specific settings bound to an instance of Oracle UCP's PoolDataSource") .addOverride("spring.datasource.dbcp2", "Commons DBCP2 specific settings bound to an instance of DBCP2's BasicDataSource") .addOverride("spring.datasource.tomcat", diff --git a/spring-boot-project/spring-boot-autoconfigure/build.gradle b/spring-boot-project/spring-boot-autoconfigure/build.gradle index bcbe04aead..b20e4d383e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-autoconfigure/build.gradle @@ -24,6 +24,8 @@ dependencies { optional("com.hazelcast:hazelcast-spring") optional("com.h2database:h2") optional("com.nimbusds:oauth2-oidc-sdk") + optional("com.oracle.database.jdbc:ojdbc8") + optional("com.oracle.database.jdbc:ucp") optional("com.samskivert:jmustache") optional("com.sun.mail:jakarta.mail") optional("de.flapdoodle.embed:de.flapdoodle.embed.mongo") @@ -64,7 +66,6 @@ dependencies { optional("org.codehaus.groovy:groovy-templates") optional("com.github.ben-manes.caffeine:caffeine") optional("com.github.mxab.thymeleaf.extras:thymeleaf-extras-data-attribute") - optional("com.oracle.database.jdbc:ucp") optional("com.sendgrid:sendgrid-java") optional("com.unboundid:unboundid-ldapsdk") optional("com.zaxxer:HikariCP") diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java index 53086b0ffb..d3cb0a138e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java @@ -48,7 +48,6 @@ import org.springframework.util.StringUtils; * @author Phillip Webb * @author Stephane Nicoll * @author Kazuki Shimizu - * @author Fabio Grassi * @since 1.0.0 */ @Configuration(proxyBeanMethods = false) @@ -70,7 +69,7 @@ public class DataSourceAutoConfiguration { @Conditional(PooledDataSourceCondition.class) @ConditionalOnMissingBean({ DataSource.class, XADataSource.class }) @Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class, - DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Ucp.class, + DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class, DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class }) protected static class PooledDataSourceConfiguration { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java index cbf96da469..6dc95e5820 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -21,7 +21,7 @@ import java.sql.SQLException; import javax.sql.DataSource; import com.zaxxer.hikari.HikariDataSource; -import oracle.ucp.jdbc.PoolDataSource; +import oracle.jdbc.OracleConnection; import oracle.ucp.jdbc.PoolDataSourceImpl; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -31,7 +31,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.util.StringUtils; /** @@ -116,26 +115,22 @@ abstract class DataSourceConfiguration { } /** - * UCP DataSource configuration. + * Oracle UCP DataSource configuration. */ @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(PoolDataSource.class) + @ConditionalOnClass({ PoolDataSourceImpl.class, OracleConnection.class }) @ConditionalOnMissingBean(DataSource.class) @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "oracle.ucp.jdbc.PoolDataSource", matchIfMissing = true) - static class Ucp { + static class OracleUcp { @Bean - @ConfigurationProperties(prefix = "spring.datasource.ucp") - PoolDataSource dataSource(DataSourceProperties properties) { - PoolDataSource dataSource = createDataSource(properties, PoolDataSourceImpl.class); + @ConfigurationProperties(prefix = "spring.datasource.oracleucp") + PoolDataSourceImpl dataSource(DataSourceProperties properties) throws SQLException { + PoolDataSourceImpl dataSource = createDataSource(properties, PoolDataSourceImpl.class); + dataSource.setValidateConnectionOnBorrow(true); if (StringUtils.hasText(properties.getName())) { - try { - dataSource.setConnectionPoolName(properties.getName()); - } - catch (SQLException se) { - throw new InvalidDataAccessApiUsageException("Error setting property connectionPoolName", se); - } + dataSource.setConnectionPoolName(properties.getName()); } return dataSource; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/metadata/DataSourcePoolMetadataProvidersConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/metadata/DataSourcePoolMetadataProvidersConfiguration.java index ca12b29c0e..44e73ad28a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/metadata/DataSourcePoolMetadataProvidersConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/metadata/DataSourcePoolMetadataProvidersConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -17,6 +17,7 @@ package org.springframework.boot.autoconfigure.jdbc.metadata; import com.zaxxer.hikari.HikariDataSource; +import oracle.jdbc.OracleConnection; import oracle.ucp.jdbc.PoolDataSource; import org.apache.commons.dbcp2.BasicDataSource; @@ -25,8 +26,8 @@ import org.springframework.boot.jdbc.DataSourceUnwrapper; import org.springframework.boot.jdbc.metadata.CommonsDbcp2DataSourcePoolMetadata; import org.springframework.boot.jdbc.metadata.DataSourcePoolMetadataProvider; import org.springframework.boot.jdbc.metadata.HikariDataSourcePoolMetadata; +import org.springframework.boot.jdbc.metadata.OracleUcpDataSourcePoolMetadata; import org.springframework.boot.jdbc.metadata.TomcatDataSourcePoolMetadata; -import org.springframework.boot.jdbc.metadata.UcpDataSourcePoolMetadata; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -94,15 +95,15 @@ public class DataSourcePoolMetadataProvidersConfiguration { } @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(PoolDataSource.class) - static class UcpPoolDataSourceMetadataProviderConfiguration { + @ConditionalOnClass({ PoolDataSource.class, OracleConnection.class }) + static class OracleUcpPoolDataSourceMetadataProviderConfiguration { @Bean - DataSourcePoolMetadataProvider UcpPoolDataSourceMetadataProvider() { + DataSourcePoolMetadataProvider oracleUcpPoolDataSourceMetadataProvider() { return (dataSource) -> { PoolDataSource ucpDataSource = DataSourceUnwrapper.unwrap(dataSource, PoolDataSource.class); if (ucpDataSource != null) { - return new UcpDataSourcePoolMetadata(ucpDataSource); + return new OracleUcpDataSourcePoolMetadata(ucpDataSource); } return null; }; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java index 8d4bf2945e..4c0fd37f75 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java @@ -34,6 +34,7 @@ import javax.sql.DataSource; import com.zaxxer.hikari.HikariDataSource; import io.r2dbc.spi.ConnectionFactory; +import oracle.ucp.jdbc.PoolDataSourceImpl; import org.apache.commons.dbcp2.BasicDataSource; import org.junit.jupiter.api.Test; @@ -135,8 +136,25 @@ class DataSourceAutoConfigurationTests { assertDataSource(org.apache.commons.dbcp2.BasicDataSource.class, Arrays.asList("com.zaxxer.hikari", "org.apache.tomcat"), (dataSource) -> { assertThat(dataSource.getTestOnBorrow()).isTrue(); - assertThat(dataSource.getValidationQuery()).isNull(); // Use - // Connection#isValid() + // Use Connection#isValid() + assertThat(dataSource.getValidationQuery()).isNull(); + }); + } + + @Test + void oracleUcpIsFallback() { + assertDataSource(PoolDataSourceImpl.class, + Arrays.asList("com.zaxxer.hikari", "org.apache.tomcat", "org.apache.commons.dbcp2"), + (dataSource) -> assertThat(dataSource.getURL()).startsWith("jdbc:hsqldb:mem:testdb")); + } + + @Test + void oracleUcpValidatesConnectionByDefault() { + assertDataSource(PoolDataSourceImpl.class, + Arrays.asList("com.zaxxer.hikari", "org.apache.tomcat", "org.apache.commons.dbcp2"), (dataSource) -> { + assertThat(dataSource.getValidateConnectionOnBorrow()).isTrue(); + // Use an internal ping when using an Oracle JDBC driver + assertThat(dataSource.getSQLForValidateConnection()).isNull(); }); } @@ -225,8 +243,8 @@ class DataSourceAutoConfigurationTests { } private static Function hideConnectionPools() { - return (runner) -> runner.withClassLoader( - new FilteredClassLoader("org.apache.tomcat", "com.zaxxer.hikari", "org.apache.commons.dbcp2")); + return (runner) -> runner.withClassLoader(new FilteredClassLoader("org.apache.tomcat", "com.zaxxer.hikari", + "org.apache.commons.dbcp2", "oracle.ucp.jdbc")); } private void assertDataSource(Class expectedType, List hiddenPackages, diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/UcpDataSourceConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/OracleUcpDataSourceConfigurationTests.java similarity index 78% rename from spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/UcpDataSourceConfigurationTests.java rename to spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/OracleUcpDataSourceConfigurationTests.java index a329908d7f..93df579d57 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/UcpDataSourceConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/OracleUcpDataSourceConfigurationTests.java @@ -16,25 +16,26 @@ package org.springframework.boot.autoconfigure.jdbc; -import static org.assertj.core.api.Assertions.assertThat; +import java.sql.Connection; import javax.sql.DataSource; +import oracle.ucp.jdbc.PoolDataSource; +import oracle.ucp.jdbc.PoolDataSourceImpl; import org.junit.jupiter.api.Test; + import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import oracle.ucp.jdbc.PoolDataSource; -import oracle.ucp.jdbc.PoolDataSourceImpl; +import static org.assertj.core.api.Assertions.assertThat; /** * Tests for {@link DataSourceAutoConfiguration} with Oracle UCP. * * @author Fabio Grassi + * @author Stephane Nicoll */ -class UcpDataSourceConfigurationTests { - - private static final String PREFIX = "spring.datasource.ucp."; +class OracleUcpDataSourceConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class)) @@ -46,13 +47,16 @@ class UcpDataSourceConfigurationTests { this.contextRunner.run((context) -> { assertThat(context.getBeansOfType(DataSource.class)).hasSize(1); assertThat(context.getBeansOfType(PoolDataSourceImpl.class)).hasSize(1); + try (Connection connection = context.getBean(DataSource.class).getConnection()) { + assertThat(connection.isValid(1000)).isTrue(); + } }); } @Test void testDataSourcePropertiesOverridden() { - this.contextRunner.withPropertyValues(PREFIX + "URL=jdbc:foo//bar/spam", PREFIX + "maxIdleTime=1234") - .run((context) -> { + this.contextRunner.withPropertyValues("spring.datasource.oracleucp.url=jdbc:foo//bar/spam", + "spring.datasource.oracleucp.max-idle-time=1234").run((context) -> { PoolDataSourceImpl ds = context.getBean(PoolDataSourceImpl.class); assertThat(ds.getURL()).isEqualTo("jdbc:foo//bar/spam"); assertThat(ds.getMaxIdleTime()).isEqualTo(1234); @@ -61,11 +65,11 @@ class UcpDataSourceConfigurationTests { @Test void testDataSourceConnectionPropertiesOverridden() { - this.contextRunner.withPropertyValues(PREFIX + "connectionProperties.autoCommit=false").run((context) -> { - PoolDataSourceImpl ds = context.getBean(PoolDataSourceImpl.class); - assertThat(ds.getConnectionProperty("autoCommit")).isEqualTo("false"); - - }); + this.contextRunner.withPropertyValues("spring.datasource.oracleucp.connection-properties.autoCommit=false") + .run((context) -> { + PoolDataSourceImpl ds = context.getBean(PoolDataSourceImpl.class); + assertThat(ds.getConnectionProperty("autoCommit")).isEqualTo("false"); + }); } @Test @@ -89,16 +93,15 @@ class UcpDataSourceConfigurationTests { this.contextRunner.withPropertyValues("spring.datasource.name=myDS").run((context) -> { PoolDataSourceImpl ds = context.getBean(PoolDataSourceImpl.class); assertThat(ds.getConnectionPoolName()).isEqualTo("myDS"); - }); } @Test - void connectionPoolNameTakesPrecedenceOverName() { - this.contextRunner.withPropertyValues("spring.datasource.name=myDS", PREFIX + "connectionPoolName=myUcpDS") - .run((context) -> { + void poolNameTakesPrecedenceOverName() { + this.contextRunner.withPropertyValues("spring.datasource.name=myDS", + "spring.datasource.oracleucp.connection-pool-name=myOracleUcpDS").run((context) -> { PoolDataSourceImpl ds = context.getBean(PoolDataSourceImpl.class); - assertThat(ds.getConnectionPoolName()).isEqualTo("myUcpDS"); + assertThat(ds.getConnectionPoolName()).isEqualTo("myOracleUcpDS"); }); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java index b4596651e9..d8190d03c9 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java @@ -105,8 +105,8 @@ class LiquibaseAutoConfigurationTests { @Test void createsDataSourceWhenSpringJdbcOnlyAvailableWithNoDataSourceBeanAndLiquibaseUrl() { this.contextRunner.withPropertyValues("spring.liquibase.url:jdbc:hsqldb:mem:liquibase") - .withClassLoader( - new FilteredClassLoader("org.apache.tomcat", "com.zaxxer.hikari", "org.apache.commons.dbcp2")) + .withClassLoader(new FilteredClassLoader("org.apache.tomcat", "com.zaxxer.hikari", + "org.apache.commons.dbcp2", "oracle.ucp.jdbc")) .run(assertLiquibase((liquibase) -> { DataSource dataSource = liquibase.getDataSource(); assertThat(dataSource).isInstanceOf(SimpleDriverDataSource.class); diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc index fa248d61d2..384f227bc6 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc @@ -3826,7 +3826,8 @@ Spring Boot uses the following algorithm for choosing a specific implementation: . We prefer https://github.com/brettwooldridge/HikariCP[HikariCP] for its performance and concurrency. If HikariCP is available, we always choose it. . Otherwise, if the Tomcat pooling `DataSource` is available, we use it. -. If neither HikariCP nor the Tomcat pooling datasource are available and if https://commons.apache.org/proper/commons-dbcp/[Commons DBCP2] is available, we use it. +. Otherwise, if https://commons.apache.org/proper/commons-dbcp/[Commons DBCP2] is available, we use it. +. If none of HikariCP, Tomcat, and DBCP2 are available and if Oracle UCP is available, we use it. If you use the `spring-boot-starter-jdbc` or `spring-boot-starter-data-jpa` "`starters`", you automatically get a dependency to `HikariCP`. @@ -3857,7 +3858,7 @@ In other words, if you set `spring.datasource.driver-class-name=com.mysql.jdbc.D See {spring-boot-autoconfigure-module-code}/jdbc/DataSourceProperties.java[`DataSourceProperties`] for more of the supported options. These are the standard options that work regardless of the actual implementation. -It is also possible to fine-tune implementation-specific settings by using their respective prefix (`+spring.datasource.hikari.*+`, `+spring.datasource.tomcat.*+`, and `+spring.datasource.dbcp2.*+`). +It is also possible to fine-tune implementation-specific settings by using their respective prefix (`+spring.datasource.hikari.*+`, `+spring.datasource.tomcat.*+`, `+spring.datasource.dbcp2.*+`, and `+spring.datasource.oracleucp.*+`). Refer to the documentation of the connection pool implementation you are using for more details. For instance, if you use the {tomcat-docs}/jdbc-pool.html#Common_Attributes[Tomcat connection pool], you could customize many additional settings, as shown in the following example: diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java index 9bf1a3b388..6120db18df 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java @@ -206,8 +206,16 @@ public final class DataSourceBuilder { create(classLoader, "org.apache.tomcat.jdbc.pool.DataSource", DataSourceSettings::new)); addIfAvailable(providers, create(classLoader, "org.apache.commons.dbcp2.BasicDataSource", DataSourceSettings::new)); - addIfAvailable(providers, - create(classLoader, "oracle.ucp.jdbc.PoolDataSourceImpl", DataSourceSettings::new)); + addIfAvailable(providers, create(classLoader, "oracle.ucp.jdbc.PoolDataSourceImpl", (type) -> { + // Unfortunately Oracle UCP has an import on the Oracle driver itself + if (ClassUtils.isPresent("oracle.jdbc.OracleConnection", classLoader)) { + return new DataSourceSettings(type, (aliases) -> { + aliases.addAliases("username", "user"); + aliases.addAliases("driver-class-name", "connection-factory-class-name"); + }); + } + return null; + })); return providers; } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/UcpDataSourcePoolMetadata.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/OracleUcpDataSourcePoolMetadata.java similarity index 64% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/UcpDataSourcePoolMetadata.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/OracleUcpDataSourcePoolMetadata.java index d2f24bd185..65d9921213 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/UcpDataSourcePoolMetadata.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/metadata/OracleUcpDataSourcePoolMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -20,20 +20,19 @@ import java.sql.SQLException; import javax.sql.DataSource; -import org.springframework.dao.InvalidDataAccessApiUsageException; -import org.springframework.util.StringUtils; - import oracle.ucp.jdbc.PoolDataSource; +import org.springframework.util.StringUtils; + /** - * {@link DataSourcePoolMetadata} for a Oracle UCP {@link DataSource}. + * {@link DataSourcePoolMetadata} for an Oracle UCP {@link DataSource}. * * @author Fabio Grassi - * @since 2.3.4 + * @since 2.4.0 */ -public class UcpDataSourcePoolMetadata extends AbstractDataSourcePoolMetadata { +public class OracleUcpDataSourcePoolMetadata extends AbstractDataSourcePoolMetadata { - public UcpDataSourcePoolMetadata(PoolDataSource dataSource) { + public OracleUcpDataSourcePoolMetadata(PoolDataSource dataSource) { super(dataSource); } @@ -42,8 +41,8 @@ public class UcpDataSourcePoolMetadata extends AbstractDataSourcePoolMetadata initializeBuilder() { return DataSourceBuilder.create().driverClassName("org.hsqldb.jdbc.JDBCDriver").url("jdbc:hsqldb:mem:test") diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/OracleUcpDataSourcePoolMetadataTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/OracleUcpDataSourcePoolMetadataTests.java new file mode 100644 index 0000000000..b8379948c0 --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/OracleUcpDataSourcePoolMetadataTests.java @@ -0,0 +1,70 @@ +/* + * Copyright 2012-2020 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.jdbc.metadata; + +import java.sql.SQLException; + +import oracle.ucp.jdbc.PoolDataSource; +import oracle.ucp.jdbc.PoolDataSourceImpl; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link OracleUcpDataSourcePoolMetadata}. + * + * @author Fabio Grassi + */ +class OracleUcpDataSourcePoolMetadataTests + extends AbstractDataSourcePoolMetadataTests { + + private final OracleUcpDataSourcePoolMetadata dataSourceMetadata = new OracleUcpDataSourcePoolMetadata( + createDataSource(0, 2)); + + @Override + protected OracleUcpDataSourcePoolMetadata getDataSourceMetadata() { + return this.dataSourceMetadata; + } + + @Override + void getValidationQuery() throws SQLException { + PoolDataSource dataSource = createDataSource(0, 4); + dataSource.setSQLForValidateConnection("SELECT NULL FROM DUAL"); + assertThat(new OracleUcpDataSourcePoolMetadata(dataSource).getValidationQuery()) + .isEqualTo("SELECT NULL FROM DUAL"); + } + + @Override + void getDefaultAutoCommit() throws SQLException { + PoolDataSource dataSource = createDataSource(0, 4); + dataSource.setConnectionProperty("autoCommit", "false"); + assertThat(new OracleUcpDataSourcePoolMetadata(dataSource).getDefaultAutoCommit()).isFalse(); + } + + private PoolDataSource createDataSource(int minSize, int maxSize) { + try { + PoolDataSource dataSource = initializeBuilder().type(PoolDataSourceImpl.class).build(); + dataSource.setInitialPoolSize(minSize); + dataSource.setMinPoolSize(minSize); + dataSource.setMaxPoolSize(maxSize); + return dataSource; + } + catch (SQLException ex) { + throw new IllegalStateException("Error while configuring PoolDataSource", ex); + } + } + +} diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/UcpDataSourcePoolMetadataTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/UcpDataSourcePoolMetadataTests.java deleted file mode 100644 index 5774427231..0000000000 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/metadata/UcpDataSourcePoolMetadataTests.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2012-2019 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.jdbc.metadata; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.sql.SQLException; - -import org.springframework.dao.InvalidDataAccessApiUsageException; - -import oracle.ucp.jdbc.PoolDataSource; -import oracle.ucp.jdbc.PoolDataSourceImpl; - -/** - * Tests for {@link UcpDataSourcePoolMetadata}. - * - * @author Fabio Grassi - */ -public class UcpDataSourcePoolMetadataTests extends AbstractDataSourcePoolMetadataTests { - - private final UcpDataSourcePoolMetadata dataSourceMetadata = new UcpDataSourcePoolMetadata(createDataSource(0, 2)); - - @Override - protected UcpDataSourcePoolMetadata getDataSourceMetadata() { - return this.dataSourceMetadata; - } - - @Override - public void getValidationQuery() { - PoolDataSource dataSource = createDataSource(0, 4); - try { - dataSource.setSQLForValidateConnection("SELECT NULL FROM DUAL"); - } catch (SQLException se) { - throw new InvalidDataAccessApiUsageException("Error while setting property SQLForValidateConnection", se); - } - assertThat(new UcpDataSourcePoolMetadata(dataSource).getValidationQuery()).isEqualTo("SELECT NULL FROM DUAL"); - } - - @Override - public void getDefaultAutoCommit() { - PoolDataSource dataSource = createDataSource(0, 4); - try { - dataSource.setConnectionProperty("autoCommit", "false"); - } catch (SQLException se) { - throw new InvalidDataAccessApiUsageException("Error while setting property connectionProperties.autoCommit", se); - } - assertThat(new UcpDataSourcePoolMetadata(dataSource).getDefaultAutoCommit()).isFalse(); - } - - private PoolDataSource createDataSource(int minSize, int maxSize) { - PoolDataSource dataSource = initializeBuilder().type(PoolDataSourceImpl.class).build(); - try { - dataSource.setInitialPoolSize(minSize); - dataSource.setMinPoolSize(minSize); - dataSource.setMaxPoolSize(maxSize); - } catch (SQLException se) { - throw new InvalidDataAccessApiUsageException("Error while setting a property", se); - } - return dataSource; - } - -}