parent
a19a565410
commit
a21ab392b6
|
@ -64,6 +64,7 @@ dependencies {
|
||||||
optional("org.codehaus.groovy:groovy-templates")
|
optional("org.codehaus.groovy:groovy-templates")
|
||||||
optional("com.github.ben-manes.caffeine:caffeine")
|
optional("com.github.ben-manes.caffeine:caffeine")
|
||||||
optional("com.github.mxab.thymeleaf.extras:thymeleaf-extras-data-attribute")
|
optional("com.github.mxab.thymeleaf.extras:thymeleaf-extras-data-attribute")
|
||||||
|
optional("com.oracle.database.jdbc:ucp")
|
||||||
optional("com.sendgrid:sendgrid-java")
|
optional("com.sendgrid:sendgrid-java")
|
||||||
optional("com.unboundid:unboundid-ldapsdk")
|
optional("com.unboundid:unboundid-ldapsdk")
|
||||||
optional("com.zaxxer:HikariCP")
|
optional("com.zaxxer:HikariCP")
|
||||||
|
|
|
@ -48,6 +48,7 @@ import org.springframework.util.StringUtils;
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Kazuki Shimizu
|
* @author Kazuki Shimizu
|
||||||
|
* @author Fabio Grassi
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ -69,8 +70,8 @@ public class DataSourceAutoConfiguration {
|
||||||
@Conditional(PooledDataSourceCondition.class)
|
@Conditional(PooledDataSourceCondition.class)
|
||||||
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
|
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
|
||||||
@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
|
@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
|
||||||
DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Generic.class,
|
DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Ucp.class,
|
||||||
DataSourceJmxConfiguration.class })
|
DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class })
|
||||||
protected static class PooledDataSourceConfiguration {
|
protected static class PooledDataSourceConfiguration {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,13 @@
|
||||||
|
|
||||||
package org.springframework.boot.autoconfigure.jdbc;
|
package org.springframework.boot.autoconfigure.jdbc;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import com.zaxxer.hikari.HikariDataSource;
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
import oracle.ucp.jdbc.PoolDataSource;
|
||||||
|
import oracle.ucp.jdbc.PoolDataSourceImpl;
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
@ -27,6 +31,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.boot.jdbc.DatabaseDriver;
|
import org.springframework.boot.jdbc.DatabaseDriver;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,6 +40,7 @@ import org.springframework.util.StringUtils;
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Fabio Grassi
|
||||||
*/
|
*/
|
||||||
abstract class DataSourceConfiguration {
|
abstract class DataSourceConfiguration {
|
||||||
|
|
||||||
|
@ -109,6 +115,33 @@ abstract class DataSourceConfiguration {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UCP DataSource configuration.
|
||||||
|
*/
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnClass(PoolDataSource.class)
|
||||||
|
@ConditionalOnMissingBean(DataSource.class)
|
||||||
|
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "oracle.ucp.jdbc.PoolDataSource",
|
||||||
|
matchIfMissing = true)
|
||||||
|
static class Ucp {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConfigurationProperties(prefix = "spring.datasource.ucp")
|
||||||
|
PoolDataSource dataSource(DataSourceProperties properties) {
|
||||||
|
PoolDataSource dataSource = createDataSource(properties, PoolDataSourceImpl.class);
|
||||||
|
if (StringUtils.hasText(properties.getName())) {
|
||||||
|
try {
|
||||||
|
dataSource.setConnectionPoolName(properties.getName());
|
||||||
|
}
|
||||||
|
catch (SQLException se) {
|
||||||
|
throw new InvalidDataAccessApiUsageException("Error setting property connectionPoolName", se);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic DataSource configuration.
|
* Generic DataSource configuration.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.boot.autoconfigure.jdbc.metadata;
|
package org.springframework.boot.autoconfigure.jdbc.metadata;
|
||||||
|
|
||||||
import com.zaxxer.hikari.HikariDataSource;
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
import oracle.ucp.jdbc.PoolDataSource;
|
||||||
import org.apache.commons.dbcp2.BasicDataSource;
|
import org.apache.commons.dbcp2.BasicDataSource;
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
@ -25,6 +26,7 @@ import org.springframework.boot.jdbc.metadata.CommonsDbcp2DataSourcePoolMetadata
|
||||||
import org.springframework.boot.jdbc.metadata.DataSourcePoolMetadataProvider;
|
import org.springframework.boot.jdbc.metadata.DataSourcePoolMetadataProvider;
|
||||||
import org.springframework.boot.jdbc.metadata.HikariDataSourcePoolMetadata;
|
import org.springframework.boot.jdbc.metadata.HikariDataSourcePoolMetadata;
|
||||||
import org.springframework.boot.jdbc.metadata.TomcatDataSourcePoolMetadata;
|
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.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@ -33,6 +35,7 @@ import org.springframework.context.annotation.Configuration;
|
||||||
* sources.
|
* sources.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Fabio Grassi
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ -90,4 +93,21 @@ public class DataSourcePoolMetadataProvidersConfiguration {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnClass(PoolDataSource.class)
|
||||||
|
static class UcpPoolDataSourceMetadataProviderConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
DataSourcePoolMetadataProvider UcpPoolDataSourceMetadataProvider() {
|
||||||
|
return (dataSource) -> {
|
||||||
|
PoolDataSource ucpDataSource = DataSourceUnwrapper.unwrap(dataSource, PoolDataSource.class);
|
||||||
|
if (ucpDataSource != null) {
|
||||||
|
return new UcpDataSourcePoolMetadata(ucpDataSource);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* 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.autoconfigure.jdbc;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link DataSourceAutoConfiguration} with Oracle UCP.
|
||||||
|
*
|
||||||
|
* @author Fabio Grassi
|
||||||
|
*/
|
||||||
|
class UcpDataSourceConfigurationTests {
|
||||||
|
|
||||||
|
private static final String PREFIX = "spring.datasource.ucp.";
|
||||||
|
|
||||||
|
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||||
|
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class))
|
||||||
|
.withPropertyValues("spring.datasource.initialization-mode=never",
|
||||||
|
"spring.datasource.type=" + PoolDataSource.class.getName());
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDataSourceExists() {
|
||||||
|
this.contextRunner.run((context) -> {
|
||||||
|
assertThat(context.getBeansOfType(DataSource.class)).hasSize(1);
|
||||||
|
assertThat(context.getBeansOfType(PoolDataSourceImpl.class)).hasSize(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDataSourcePropertiesOverridden() {
|
||||||
|
this.contextRunner.withPropertyValues(PREFIX + "URL=jdbc:foo//bar/spam", PREFIX + "maxIdleTime=1234")
|
||||||
|
.run((context) -> {
|
||||||
|
PoolDataSourceImpl ds = context.getBean(PoolDataSourceImpl.class);
|
||||||
|
assertThat(ds.getURL()).isEqualTo("jdbc:foo//bar/spam");
|
||||||
|
assertThat(ds.getMaxIdleTime()).isEqualTo(1234);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDataSourceConnectionPropertiesOverridden() {
|
||||||
|
this.contextRunner.withPropertyValues(PREFIX + "connectionProperties.autoCommit=false").run((context) -> {
|
||||||
|
PoolDataSourceImpl ds = context.getBean(PoolDataSourceImpl.class);
|
||||||
|
assertThat(ds.getConnectionProperty("autoCommit")).isEqualTo("false");
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDataSourceDefaultsPreserved() {
|
||||||
|
this.contextRunner.run((context) -> {
|
||||||
|
PoolDataSourceImpl ds = context.getBean(PoolDataSourceImpl.class);
|
||||||
|
assertThat(ds.getInitialPoolSize()).isEqualTo(0);
|
||||||
|
assertThat(ds.getMinPoolSize()).isEqualTo(0);
|
||||||
|
assertThat(ds.getMaxPoolSize()).isEqualTo(Integer.MAX_VALUE);
|
||||||
|
assertThat(ds.getInactiveConnectionTimeout()).isEqualTo(0);
|
||||||
|
assertThat(ds.getConnectionWaitTimeout()).isEqualTo(3);
|
||||||
|
assertThat(ds.getTimeToLiveConnectionTimeout()).isEqualTo(0);
|
||||||
|
assertThat(ds.getAbandonedConnectionTimeout()).isEqualTo(0);
|
||||||
|
assertThat(ds.getTimeoutCheckInterval()).isEqualTo(30);
|
||||||
|
assertThat(ds.getFastConnectionFailoverEnabled()).isFalse();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void nameIsAliasedToPoolName() {
|
||||||
|
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) -> {
|
||||||
|
PoolDataSourceImpl ds = context.getBean(PoolDataSourceImpl.class);
|
||||||
|
assertThat(ds.getConnectionPoolName()).isEqualTo("myUcpDS");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ dependencies {
|
||||||
optional("com.atomikos:transactions-jta")
|
optional("com.atomikos:transactions-jta")
|
||||||
optional("com.fasterxml.jackson.core:jackson-databind")
|
optional("com.fasterxml.jackson.core:jackson-databind")
|
||||||
optional("com.google.code.gson:gson")
|
optional("com.google.code.gson:gson")
|
||||||
|
optional("com.oracle.database.jdbc:ucp")
|
||||||
optional("com.samskivert:jmustache")
|
optional("com.samskivert:jmustache")
|
||||||
optional("com.zaxxer:HikariCP")
|
optional("com.zaxxer:HikariCP")
|
||||||
optional("io.netty:netty-tcnative-boringssl-static")
|
optional("io.netty:netty-tcnative-boringssl-static")
|
||||||
|
@ -77,7 +78,7 @@ dependencies {
|
||||||
testImplementation("com.ibm.db2:jcc")
|
testImplementation("com.ibm.db2:jcc")
|
||||||
testImplementation("com.jayway.jsonpath:json-path")
|
testImplementation("com.jayway.jsonpath:json-path")
|
||||||
testImplementation("com.microsoft.sqlserver:mssql-jdbc")
|
testImplementation("com.microsoft.sqlserver:mssql-jdbc")
|
||||||
testImplementation("com.oracle.ojdbc:ojdbc8")
|
testImplementation("com.oracle.database.jdbc:ojdbc8")
|
||||||
testImplementation("com.squareup.okhttp3:okhttp")
|
testImplementation("com.squareup.okhttp3:okhttp")
|
||||||
testImplementation("com.sun.xml.messaging.saaj:saaj-impl")
|
testImplementation("com.sun.xml.messaging.saaj:saaj-impl")
|
||||||
testImplementation("io.projectreactor:reactor-test")
|
testImplementation("io.projectreactor:reactor-test")
|
||||||
|
|
|
@ -37,16 +37,17 @@ import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience class for building a {@link DataSource} with common implementations and
|
* Convenience class for building a {@link DataSource} with common implementations and
|
||||||
* properties. If HikariCP, Tomcat or Commons DBCP are on the classpath one of them will
|
* properties. If HikariCP, Tomcat, Commons DBCP or Oracle UCP are on the classpath one of
|
||||||
* be selected (in that order with Hikari first). In the interest of a uniform interface,
|
* them will be selected (in that order with Hikari first). In the interest of a uniform
|
||||||
* and so that there can be a fallback to an embedded database if one can be detected on
|
* interface, and so that there can be a fallback to an embedded database if one can be
|
||||||
* the classpath, only a small set of common configuration properties are supported. To
|
* detected on the classpath, only a small set of common configuration properties are
|
||||||
* inject additional properties into the result you can downcast it, or use
|
* supported. To inject additional properties into the result you can downcast it, or use
|
||||||
* {@code @ConfigurationProperties}.
|
* {@code @ConfigurationProperties}.
|
||||||
*
|
*
|
||||||
* @param <T> type of DataSource produced by the builder
|
* @param <T> type of DataSource produced by the builder
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Madhura Bhave
|
* @author Madhura Bhave
|
||||||
|
* @author Fabio Grassi
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
public final class DataSourceBuilder<T extends DataSource> {
|
public final class DataSourceBuilder<T extends DataSource> {
|
||||||
|
@ -166,9 +167,9 @@ public final class DataSourceBuilder<T extends DataSource> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class OracleDataSourceSettings extends DataSourceSettings {
|
private static class OracleCommonDataSourceSettings extends DataSourceSettings {
|
||||||
|
|
||||||
OracleDataSourceSettings(Class<? extends DataSource> type) {
|
OracleCommonDataSourceSettings(Class<? extends DataSource> type) {
|
||||||
super(type, (aliases) -> aliases.addAliases("username", "user"));
|
super(type, (aliases) -> aliases.addAliases("username", "user"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +195,7 @@ public final class DataSourceBuilder<T extends DataSource> {
|
||||||
(type) -> new DataSourceSettings(type,
|
(type) -> new DataSourceSettings(type,
|
||||||
(aliases) -> aliases.addAliases("driver-class-name", "driver-class"))));
|
(aliases) -> aliases.addAliases("driver-class-name", "driver-class"))));
|
||||||
addIfAvailable(this.allDataSourceSettings, create(classLoader,
|
addIfAvailable(this.allDataSourceSettings, create(classLoader,
|
||||||
"oracle.jdbc.datasource.OracleCommonDataSource", OracleDataSourceSettings::new));
|
"oracle.jdbc.datasource.OracleCommonDataSource", OracleCommonDataSourceSettings::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<DataSourceSettings> resolveAvailableDataSourceSettings(ClassLoader classLoader) {
|
private static List<DataSourceSettings> resolveAvailableDataSourceSettings(ClassLoader classLoader) {
|
||||||
|
@ -205,6 +206,8 @@ public final class DataSourceBuilder<T extends DataSource> {
|
||||||
create(classLoader, "org.apache.tomcat.jdbc.pool.DataSource", DataSourceSettings::new));
|
create(classLoader, "org.apache.tomcat.jdbc.pool.DataSource", DataSourceSettings::new));
|
||||||
addIfAvailable(providers,
|
addIfAvailable(providers,
|
||||||
create(classLoader, "org.apache.commons.dbcp2.BasicDataSource", DataSourceSettings::new));
|
create(classLoader, "org.apache.commons.dbcp2.BasicDataSource", DataSourceSettings::new));
|
||||||
|
addIfAvailable(providers,
|
||||||
|
create(classLoader, "oracle.ucp.jdbc.PoolDataSourceImpl", DataSourceSettings::new));
|
||||||
return providers;
|
return providers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* 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 java.sql.SQLException;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import oracle.ucp.jdbc.PoolDataSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link DataSourcePoolMetadata} for a Oracle UCP {@link DataSource}.
|
||||||
|
*
|
||||||
|
* @author Fabio Grassi
|
||||||
|
* @since 2.3.4
|
||||||
|
*/
|
||||||
|
public class UcpDataSourcePoolMetadata extends AbstractDataSourcePoolMetadata<PoolDataSource> {
|
||||||
|
|
||||||
|
public UcpDataSourcePoolMetadata(PoolDataSource dataSource) {
|
||||||
|
super(dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getActive() {
|
||||||
|
try {
|
||||||
|
return getDataSource().getBorrowedConnectionsCount();
|
||||||
|
}
|
||||||
|
catch (SQLException se) {
|
||||||
|
throw new InvalidDataAccessApiUsageException("Error while reading property borrowedConnectionsCount", se);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getIdle() {
|
||||||
|
try {
|
||||||
|
return getDataSource().getAvailableConnectionsCount();
|
||||||
|
}
|
||||||
|
catch (SQLException se) {
|
||||||
|
throw new InvalidDataAccessApiUsageException("Error while reading property availableConnectionsCount", se);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getMax() {
|
||||||
|
return getDataSource().getMaxPoolSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getMin() {
|
||||||
|
return getDataSource().getMinPoolSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValidationQuery() {
|
||||||
|
return getDataSource().getSQLForValidateConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean getDefaultAutoCommit() {
|
||||||
|
String ac = getDataSource().getConnectionProperty("autoCommit");
|
||||||
|
return StringUtils.hasText(ac) ? Boolean.valueOf(ac) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
package org.springframework.boot.jdbc;
|
package org.springframework.boot.jdbc;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
@ -31,15 +33,17 @@ import org.apache.commons.dbcp2.BasicDataSource;
|
||||||
import org.h2.Driver;
|
import org.h2.Driver;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
|
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
|
||||||
|
import oracle.ucp.jdbc.PoolDataSourceImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link DataSourceBuilder}.
|
* Tests for {@link DataSourceBuilder}.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Fabio Grassi
|
||||||
*/
|
*/
|
||||||
class DataSourceBuilderTests {
|
class DataSourceBuilderTests {
|
||||||
|
|
||||||
|
@ -68,13 +72,20 @@ class DataSourceBuilderTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void defaultToCommonsDbcp2AsLastResort() {
|
void defaultToCommonsDbcp2IfNeitherHikariNorTomcatIsNotAvailable() {
|
||||||
this.dataSource = DataSourceBuilder
|
this.dataSource = DataSourceBuilder
|
||||||
.create(new HidePackagesClassLoader("com.zaxxer.hikari", "org.apache.tomcat.jdbc.pool"))
|
.create(new HidePackagesClassLoader("com.zaxxer.hikari", "org.apache.tomcat.jdbc.pool"))
|
||||||
.url("jdbc:h2:test").build();
|
.url("jdbc:h2:test").build();
|
||||||
assertThat(this.dataSource).isInstanceOf(BasicDataSource.class);
|
assertThat(this.dataSource).isInstanceOf(BasicDataSource.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void defaultToUcpAsLastResort() {
|
||||||
|
this.dataSource = DataSourceBuilder.create(new HidePackagesClassLoader("com.zaxxer.hikari",
|
||||||
|
"org.apache.tomcat.jdbc.pool", "org.apache.commons.dbcp2")).url("jdbc:h2:test").build();
|
||||||
|
assertThat(this.dataSource).isInstanceOf(PoolDataSourceImpl.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void specificTypeOfDataSource() {
|
void specificTypeOfDataSource() {
|
||||||
HikariDataSource hikariDataSource = DataSourceBuilder.create().type(HikariDataSource.class).build();
|
HikariDataSource hikariDataSource = DataSourceBuilder.create().type(HikariDataSource.class).build();
|
||||||
|
@ -114,6 +125,15 @@ class DataSourceBuilderTests {
|
||||||
assertThat(testDataSource.getDriverClass()).isNull();
|
assertThat(testDataSource.getDriverClass()).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void UcpCanBeCreatedByDriverClassNamee() {
|
||||||
|
this.dataSource = DataSourceBuilder.create().driverClassName("org.hsqldb.jdbc.JDBCDriver")
|
||||||
|
.type(PoolDataSourceImpl.class).build();
|
||||||
|
assertThat(this.dataSource).isInstanceOf(PoolDataSourceImpl.class);
|
||||||
|
assertThat(((PoolDataSourceImpl) this.dataSource).getConnectionFactoryClassName())
|
||||||
|
.isEqualTo("org.hsqldb.jdbc.JDBCDriver");
|
||||||
|
}
|
||||||
|
|
||||||
final class HidePackagesClassLoader extends URLClassLoader {
|
final class HidePackagesClassLoader extends URLClassLoader {
|
||||||
|
|
||||||
private final String[] hiddenPackages;
|
private final String[] hiddenPackages;
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* 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<UcpDataSourcePoolMetadata> {
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue