mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Add ConnectionDetail support to JDBC auto-configuration
Update JDBC auto-configuration so that `JdbcConnectionDetails` beans may be optionally used to provide connection details. See gh-34657 Co-Authored-By: Mortitz Halbritter <mkammerer@vmware.com> Co-Authored-By: Phillip Webb <pwebb@vmware.com>
This commit is contained in:
parent
aa91f2b8b6
commit
d09ac00824
@ -236,6 +236,7 @@ dependencies {
|
|||||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||||
testImplementation("org.mockito:mockito-core")
|
testImplementation("org.mockito:mockito-core")
|
||||||
testImplementation("org.mockito:mockito-junit-jupiter")
|
testImplementation("org.mockito:mockito-junit-jupiter")
|
||||||
|
testImplementation("org.postgresql:postgresql")
|
||||||
testImplementation("org.skyscreamer:jsonassert")
|
testImplementation("org.skyscreamer:jsonassert")
|
||||||
testImplementation("org.springframework:spring-test")
|
testImplementation("org.springframework:spring-test")
|
||||||
testImplementation("org.springframework:spring-core-test")
|
testImplementation("org.springframework:spring-core-test")
|
||||||
|
@ -47,6 +47,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|||||||
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayAutoConfigurationRuntimeHints;
|
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayAutoConfigurationRuntimeHints;
|
||||||
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayDataSourceCondition;
|
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayDataSourceCondition;
|
||||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
|
||||||
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
|
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
||||||
import org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
|
import org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
|
||||||
@ -86,6 +87,7 @@ import org.springframework.util.StringUtils;
|
|||||||
* @author Semyon Danilov
|
* @author Semyon Danilov
|
||||||
* @author Chris Bono
|
* @author Chris Bono
|
||||||
* @author Moritz Halbritter
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
@AutoConfiguration(after = { DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
|
@AutoConfiguration(after = { DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
|
||||||
@ -125,7 +127,7 @@ public class FlywayAutoConfiguration {
|
|||||||
ObjectProvider<FlywayConfigurationCustomizer> fluentConfigurationCustomizers,
|
ObjectProvider<FlywayConfigurationCustomizer> fluentConfigurationCustomizers,
|
||||||
ObjectProvider<JavaMigration> javaMigrations, ObjectProvider<Callback> callbacks) {
|
ObjectProvider<JavaMigration> javaMigrations, ObjectProvider<Callback> callbacks) {
|
||||||
return flyway(properties, resourceLoader, dataSource, flywayDataSource, fluentConfigurationCustomizers,
|
return flyway(properties, resourceLoader, dataSource, flywayDataSource, fluentConfigurationCustomizers,
|
||||||
javaMigrations, callbacks, new ResourceProviderCustomizer());
|
javaMigrations, callbacks, new ResourceProviderCustomizer(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ -133,9 +135,15 @@ public class FlywayAutoConfiguration {
|
|||||||
@FlywayDataSource ObjectProvider<DataSource> flywayDataSource,
|
@FlywayDataSource ObjectProvider<DataSource> flywayDataSource,
|
||||||
ObjectProvider<FlywayConfigurationCustomizer> fluentConfigurationCustomizers,
|
ObjectProvider<FlywayConfigurationCustomizer> fluentConfigurationCustomizers,
|
||||||
ObjectProvider<JavaMigration> javaMigrations, ObjectProvider<Callback> callbacks,
|
ObjectProvider<JavaMigration> javaMigrations, ObjectProvider<Callback> callbacks,
|
||||||
ResourceProviderCustomizer resourceProviderCustomizer) {
|
ResourceProviderCustomizer resourceProviderCustomizer,
|
||||||
|
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||||
FluentConfiguration configuration = new FluentConfiguration(resourceLoader.getClassLoader());
|
FluentConfiguration configuration = new FluentConfiguration(resourceLoader.getClassLoader());
|
||||||
configureDataSource(configuration, properties, flywayDataSource.getIfAvailable(), dataSource.getIfUnique());
|
JdbcConnectionDetails connectionDetails = (connectionDetailsProvider != null)
|
||||||
|
? connectionDetailsProvider.getIfAvailable() : null;
|
||||||
|
connectionDetails = (connectionDetails != null) ? connectionDetails
|
||||||
|
: new FlywayPropertiesJdbcConnectionDetails(properties);
|
||||||
|
configureDataSource(configuration, flywayDataSource.getIfAvailable(), dataSource.getIfUnique(),
|
||||||
|
connectionDetails);
|
||||||
configureProperties(configuration, properties);
|
configureProperties(configuration, properties);
|
||||||
configureCallbacks(configuration, callbacks.orderedStream().toList());
|
configureCallbacks(configuration, callbacks.orderedStream().toList());
|
||||||
configureJavaMigrations(configuration, javaMigrations.orderedStream().toList());
|
configureJavaMigrations(configuration, javaMigrations.orderedStream().toList());
|
||||||
@ -144,38 +152,41 @@ public class FlywayAutoConfiguration {
|
|||||||
return configuration.load();
|
return configuration.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureDataSource(FluentConfiguration configuration, FlywayProperties properties,
|
private void configureDataSource(FluentConfiguration configuration, DataSource flywayDataSource,
|
||||||
DataSource flywayDataSource, DataSource dataSource) {
|
DataSource dataSource, JdbcConnectionDetails connectionDetails) {
|
||||||
DataSource migrationDataSource = getMigrationDataSource(properties, flywayDataSource, dataSource);
|
DataSource migrationDataSource = getMigrationDataSource(flywayDataSource, dataSource, connectionDetails);
|
||||||
configuration.dataSource(migrationDataSource);
|
configuration.dataSource(migrationDataSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataSource getMigrationDataSource(FlywayProperties properties, DataSource flywayDataSource,
|
private DataSource getMigrationDataSource(DataSource flywayDataSource, DataSource dataSource,
|
||||||
DataSource dataSource) {
|
JdbcConnectionDetails connectionDetails) {
|
||||||
if (flywayDataSource != null) {
|
if (flywayDataSource != null) {
|
||||||
return flywayDataSource;
|
return flywayDataSource;
|
||||||
}
|
}
|
||||||
if (properties.getUrl() != null) {
|
String url = connectionDetails.getJdbcUrl();
|
||||||
|
if (url != null) {
|
||||||
DataSourceBuilder<?> builder = DataSourceBuilder.create().type(SimpleDriverDataSource.class);
|
DataSourceBuilder<?> builder = DataSourceBuilder.create().type(SimpleDriverDataSource.class);
|
||||||
builder.url(properties.getUrl());
|
builder.url(url);
|
||||||
applyCommonBuilderProperties(properties, builder);
|
applyConnectionDetails(connectionDetails, builder);
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
if (properties.getUser() != null && dataSource != null) {
|
String user = connectionDetails.getUsername();
|
||||||
|
if (user != null && dataSource != null) {
|
||||||
DataSourceBuilder<?> builder = DataSourceBuilder.derivedFrom(dataSource)
|
DataSourceBuilder<?> builder = DataSourceBuilder.derivedFrom(dataSource)
|
||||||
.type(SimpleDriverDataSource.class);
|
.type(SimpleDriverDataSource.class);
|
||||||
applyCommonBuilderProperties(properties, builder);
|
applyConnectionDetails(connectionDetails, builder);
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
Assert.state(dataSource != null, "Flyway migration DataSource missing");
|
Assert.state(dataSource != null, "Flyway migration DataSource missing");
|
||||||
return dataSource;
|
return dataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyCommonBuilderProperties(FlywayProperties properties, DataSourceBuilder<?> builder) {
|
private void applyConnectionDetails(JdbcConnectionDetails connectionDetails, DataSourceBuilder<?> builder) {
|
||||||
builder.username(properties.getUser());
|
builder.username(connectionDetails.getUsername());
|
||||||
builder.password(properties.getPassword());
|
builder.password(connectionDetails.getPassword());
|
||||||
if (StringUtils.hasText(properties.getDriverClassName())) {
|
String driverClassName = connectionDetails.getDriverClassName();
|
||||||
builder.driverClassName(properties.getDriverClassName());
|
if (StringUtils.hasText(driverClassName)) {
|
||||||
|
builder.driverClassName(driverClassName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,6 +384,11 @@ public class FlywayAutoConfiguration {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ConditionalOnBean(JdbcConnectionDetails.class)
|
||||||
|
private static final class JdbcConnectionDetailsCondition {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@ConditionalOnProperty(prefix = "spring.flyway", name = "url")
|
@ConditionalOnProperty(prefix = "spring.flyway", name = "url")
|
||||||
private static final class FlywayUrlCondition {
|
private static final class FlywayUrlCondition {
|
||||||
|
|
||||||
@ -389,4 +405,37 @@ public class FlywayAutoConfiguration {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapts {@link FlywayProperties} to {@link JdbcConnectionDetails}.
|
||||||
|
*/
|
||||||
|
private static final class FlywayPropertiesJdbcConnectionDetails implements JdbcConnectionDetails {
|
||||||
|
|
||||||
|
private final FlywayProperties properties;
|
||||||
|
|
||||||
|
private FlywayPropertiesJdbcConnectionDetails(FlywayProperties properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return this.properties.getUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return this.properties.getPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getJdbcUrl() {
|
||||||
|
return this.properties.getUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDriverClassName() {
|
||||||
|
return this.properties.getDriverClassName();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2020 the original author or authors.
|
* Copyright 2012-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -24,10 +24,13 @@ import com.zaxxer.hikari.HikariDataSource;
|
|||||||
import oracle.jdbc.OracleConnection;
|
import oracle.jdbc.OracleConnection;
|
||||||
import oracle.ucp.jdbc.PoolDataSourceImpl;
|
import oracle.ucp.jdbc.PoolDataSourceImpl;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
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;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.boot.jdbc.DataSourceBuilder;
|
||||||
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;
|
||||||
@ -40,6 +43,8 @@ import org.springframework.util.StringUtils;
|
|||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Fabio Grassi
|
* @author Fabio Grassi
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
*/
|
*/
|
||||||
abstract class DataSourceConfiguration {
|
abstract class DataSourceConfiguration {
|
||||||
|
|
||||||
@ -48,6 +53,17 @@ abstract class DataSourceConfiguration {
|
|||||||
return (T) properties.initializeDataSourceBuilder().type(type).build();
|
return (T) properties.initializeDataSourceBuilder().type(type).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected static <T> T createDataSource(JdbcConnectionDetails connectionDetails, Class<? extends DataSource> type,
|
||||||
|
ClassLoader classLoader) {
|
||||||
|
return (T) DataSourceBuilder.create(classLoader)
|
||||||
|
.url(connectionDetails.getJdbcUrl())
|
||||||
|
.username(connectionDetails.getUsername())
|
||||||
|
.password(connectionDetails.getPassword())
|
||||||
|
.type(type)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tomcat Pool DataSource configuration.
|
* Tomcat Pool DataSource configuration.
|
||||||
*/
|
*/
|
||||||
@ -58,13 +74,26 @@ abstract class DataSourceConfiguration {
|
|||||||
matchIfMissing = true)
|
matchIfMissing = true)
|
||||||
static class Tomcat {
|
static class Tomcat {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnBean(JdbcConnectionDetails.class)
|
||||||
|
static TomcatJdbcConnectionDetailsBeanPostProcessor tomcatJdbcConnectionDetailsBeanPostProcessor(
|
||||||
|
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||||
|
return new TomcatJdbcConnectionDetailsBeanPostProcessor(connectionDetailsProvider);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConfigurationProperties(prefix = "spring.datasource.tomcat")
|
@ConfigurationProperties(prefix = "spring.datasource.tomcat")
|
||||||
org.apache.tomcat.jdbc.pool.DataSource dataSource(DataSourceProperties properties) {
|
org.apache.tomcat.jdbc.pool.DataSource dataSource(DataSourceProperties properties,
|
||||||
org.apache.tomcat.jdbc.pool.DataSource dataSource = createDataSource(properties,
|
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||||
org.apache.tomcat.jdbc.pool.DataSource.class);
|
JdbcConnectionDetails connectionDetails = connectionDetailsProvider.getIfAvailable();
|
||||||
DatabaseDriver databaseDriver = DatabaseDriver.fromJdbcUrl(properties.determineUrl());
|
Class<? extends DataSource> dataSourceType = org.apache.tomcat.jdbc.pool.DataSource.class;
|
||||||
String validationQuery = databaseDriver.getValidationQuery();
|
org.apache.tomcat.jdbc.pool.DataSource dataSource = (connectionDetails != null)
|
||||||
|
? createDataSource(connectionDetails, dataSourceType, properties.getClassLoader())
|
||||||
|
: createDataSource(properties, dataSourceType);
|
||||||
|
String validationQuery;
|
||||||
|
String url = (connectionDetails != null) ? connectionDetails.getJdbcUrl() : properties.determineUrl();
|
||||||
|
DatabaseDriver databaseDriver = DatabaseDriver.fromJdbcUrl(url);
|
||||||
|
validationQuery = databaseDriver.getValidationQuery();
|
||||||
if (validationQuery != null) {
|
if (validationQuery != null) {
|
||||||
dataSource.setTestOnBorrow(true);
|
dataSource.setTestOnBorrow(true);
|
||||||
dataSource.setValidationQuery(validationQuery);
|
dataSource.setValidationQuery(validationQuery);
|
||||||
@ -84,10 +113,21 @@ abstract class DataSourceConfiguration {
|
|||||||
matchIfMissing = true)
|
matchIfMissing = true)
|
||||||
static class Hikari {
|
static class Hikari {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnBean(JdbcConnectionDetails.class)
|
||||||
|
static HikariJdbcConnectionDetailsBeanPostProcessor jdbcConnectionDetailsHikariBeanPostProcessor(
|
||||||
|
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||||
|
return new HikariJdbcConnectionDetailsBeanPostProcessor(connectionDetailsProvider);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConfigurationProperties(prefix = "spring.datasource.hikari")
|
@ConfigurationProperties(prefix = "spring.datasource.hikari")
|
||||||
HikariDataSource dataSource(DataSourceProperties properties) {
|
HikariDataSource dataSource(DataSourceProperties properties,
|
||||||
HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class);
|
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||||
|
JdbcConnectionDetails connectionDetails = connectionDetailsProvider.getIfAvailable();
|
||||||
|
HikariDataSource dataSource = (connectionDetails != null)
|
||||||
|
? createDataSource(connectionDetails, HikariDataSource.class, properties.getClassLoader())
|
||||||
|
: createDataSource(properties, HikariDataSource.class);
|
||||||
if (StringUtils.hasText(properties.getName())) {
|
if (StringUtils.hasText(properties.getName())) {
|
||||||
dataSource.setPoolName(properties.getName());
|
dataSource.setPoolName(properties.getName());
|
||||||
}
|
}
|
||||||
@ -106,10 +146,22 @@ abstract class DataSourceConfiguration {
|
|||||||
matchIfMissing = true)
|
matchIfMissing = true)
|
||||||
static class Dbcp2 {
|
static class Dbcp2 {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnBean(JdbcConnectionDetails.class)
|
||||||
|
static Dbcp2JdbcConnectionDetailsBeanPostProcessor dbcp2JdbcConnectionDetailsBeanPostProcessor(
|
||||||
|
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||||
|
return new Dbcp2JdbcConnectionDetailsBeanPostProcessor(connectionDetailsProvider);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConfigurationProperties(prefix = "spring.datasource.dbcp2")
|
@ConfigurationProperties(prefix = "spring.datasource.dbcp2")
|
||||||
org.apache.commons.dbcp2.BasicDataSource dataSource(DataSourceProperties properties) {
|
org.apache.commons.dbcp2.BasicDataSource dataSource(DataSourceProperties properties,
|
||||||
return createDataSource(properties, org.apache.commons.dbcp2.BasicDataSource.class);
|
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||||
|
JdbcConnectionDetails connectionDetails = connectionDetailsProvider.getIfAvailable();
|
||||||
|
Class<? extends DataSource> dataSourceType = org.apache.commons.dbcp2.BasicDataSource.class;
|
||||||
|
return (connectionDetails != null)
|
||||||
|
? createDataSource(connectionDetails, dataSourceType, properties.getClassLoader())
|
||||||
|
: createDataSource(properties, dataSourceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -124,10 +176,21 @@ abstract class DataSourceConfiguration {
|
|||||||
matchIfMissing = true)
|
matchIfMissing = true)
|
||||||
static class OracleUcp {
|
static class OracleUcp {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnBean(JdbcConnectionDetails.class)
|
||||||
|
static OracleUcpJdbcConnectionDetailsBeanPostProcessor oracleUcpJdbcConnectionDetailsBeanPostProcessor(
|
||||||
|
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||||
|
return new OracleUcpJdbcConnectionDetailsBeanPostProcessor(connectionDetailsProvider);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConfigurationProperties(prefix = "spring.datasource.oracleucp")
|
@ConfigurationProperties(prefix = "spring.datasource.oracleucp")
|
||||||
PoolDataSourceImpl dataSource(DataSourceProperties properties) throws SQLException {
|
PoolDataSourceImpl dataSource(DataSourceProperties properties,
|
||||||
PoolDataSourceImpl dataSource = createDataSource(properties, PoolDataSourceImpl.class);
|
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) throws SQLException {
|
||||||
|
JdbcConnectionDetails connectionDetails = connectionDetailsProvider.getIfAvailable();
|
||||||
|
PoolDataSourceImpl dataSource = (connectionDetails != null)
|
||||||
|
? createDataSource(connectionDetails, PoolDataSourceImpl.class, properties.getClassLoader())
|
||||||
|
: createDataSource(properties, PoolDataSourceImpl.class);
|
||||||
dataSource.setValidateConnectionOnBorrow(true);
|
dataSource.setValidateConnectionOnBorrow(true);
|
||||||
if (StringUtils.hasText(properties.getName())) {
|
if (StringUtils.hasText(properties.getName())) {
|
||||||
dataSource.setConnectionPoolName(properties.getName());
|
dataSource.setConnectionPoolName(properties.getName());
|
||||||
@ -146,7 +209,17 @@ abstract class DataSourceConfiguration {
|
|||||||
static class Generic {
|
static class Generic {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
DataSource dataSource(DataSourceProperties properties) {
|
DataSource dataSource(DataSourceProperties properties,
|
||||||
|
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||||
|
JdbcConnectionDetails connectionDetails = connectionDetailsProvider.getIfAvailable();
|
||||||
|
if (connectionDetails != null) {
|
||||||
|
return DataSourceBuilder.create(properties.getClassLoader())
|
||||||
|
.url(connectionDetails.getJdbcUrl())
|
||||||
|
.username(connectionDetails.getUsername())
|
||||||
|
.password(connectionDetails.getPassword())
|
||||||
|
.type(properties.getType())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
return properties.initializeDataSourceBuilder().build();
|
return properties.initializeDataSourceBuilder().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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.autoconfigure.jdbc;
|
||||||
|
|
||||||
|
import org.apache.commons.dbcp2.BasicDataSource;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post-processes beans of type {@link BasicDataSource} and name 'dataSource' to apply the
|
||||||
|
* values from {@link JdbcConnectionDetails}.
|
||||||
|
*
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class Dbcp2JdbcConnectionDetailsBeanPostProcessor extends JdbcConnectionDetailsBeanPostProcessor<BasicDataSource> {
|
||||||
|
|
||||||
|
Dbcp2JdbcConnectionDetailsBeanPostProcessor(ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||||
|
super(BasicDataSource.class, connectionDetailsProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object processDataSource(BasicDataSource dataSource, JdbcConnectionDetails connectionDetails) {
|
||||||
|
dataSource.setUrl(connectionDetails.getJdbcUrl());
|
||||||
|
dataSource.setUsername(connectionDetails.getUsername());
|
||||||
|
dataSource.setPassword(connectionDetails.getPassword());
|
||||||
|
dataSource.setDriverClassName(connectionDetails.getDriverClassName());
|
||||||
|
return dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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.autoconfigure.jdbc;
|
||||||
|
|
||||||
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post-processes beans of type {@link HikariDataSource} and name 'dataSource' to apply
|
||||||
|
* the values from {@link JdbcConnectionDetails}.
|
||||||
|
*
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class HikariJdbcConnectionDetailsBeanPostProcessor extends JdbcConnectionDetailsBeanPostProcessor<HikariDataSource> {
|
||||||
|
|
||||||
|
HikariJdbcConnectionDetailsBeanPostProcessor(ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||||
|
super(HikariDataSource.class, connectionDetailsProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object processDataSource(HikariDataSource dataSource, JdbcConnectionDetails connectionDetails) {
|
||||||
|
dataSource.setJdbcUrl(connectionDetails.getJdbcUrl());
|
||||||
|
dataSource.setUsername(connectionDetails.getUsername());
|
||||||
|
dataSource.setPassword(connectionDetails.getPassword());
|
||||||
|
dataSource.setDriverClassName(connectionDetails.getDriverClassName());
|
||||||
|
return dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* 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.autoconfigure.jdbc;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
|
||||||
|
import org.springframework.boot.jdbc.DatabaseDriver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Details required to establish a connection to an SQL service using JDBC.
|
||||||
|
*
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 3.1.0
|
||||||
|
*/
|
||||||
|
public interface JdbcConnectionDetails extends ConnectionDetails {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hostname for the database.
|
||||||
|
* @return the username for the database
|
||||||
|
*/
|
||||||
|
String getUsername();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Password for the database.
|
||||||
|
* @return the password for the database
|
||||||
|
*/
|
||||||
|
String getPassword();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JDBC url for the database.
|
||||||
|
* @return the JDBC url for the database
|
||||||
|
*/
|
||||||
|
String getJdbcUrl();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the JDBC driver class. Defaults to the class name of the driver
|
||||||
|
* specified in the JDBC URL.
|
||||||
|
* @return the JDBC driver class name
|
||||||
|
* @see #getJdbcUrl()
|
||||||
|
* @see DatabaseDriver#fromJdbcUrl(String)
|
||||||
|
* @see DatabaseDriver#getDriverClassName()
|
||||||
|
*/
|
||||||
|
default String getDriverClassName() {
|
||||||
|
return DatabaseDriver.fromJdbcUrl(getJdbcUrl()).getDriverClassName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the XA DataSource class. Defaults to the class name from the
|
||||||
|
* driver specified in the JDBC URL.
|
||||||
|
* @return the XA DataSource class name
|
||||||
|
* @see #getJdbcUrl()
|
||||||
|
* @see DatabaseDriver#fromJdbcUrl(String)
|
||||||
|
* @see DatabaseDriver#getXaDataSourceClassName()
|
||||||
|
*/
|
||||||
|
default String getXaDataSourceClassName() {
|
||||||
|
return DatabaseDriver.fromJdbcUrl(getJdbcUrl()).getXaDataSourceClassName();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* 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.autoconfigure.jdbc;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.PriorityOrdered;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract base class for DataSource bean post processors which apply values from
|
||||||
|
* {@link JdbcConnectionDetails}. Acts on beans named 'dataSource' of type {@code T}.
|
||||||
|
*
|
||||||
|
* @param <T> type of the datasource
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
abstract class JdbcConnectionDetailsBeanPostProcessor<T> implements BeanPostProcessor, PriorityOrdered {
|
||||||
|
|
||||||
|
private final Class<T> dataSourceClass;
|
||||||
|
|
||||||
|
private final ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider;
|
||||||
|
|
||||||
|
JdbcConnectionDetailsBeanPostProcessor(Class<T> dataSourceClass,
|
||||||
|
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||||
|
this.dataSourceClass = dataSourceClass;
|
||||||
|
this.connectionDetailsProvider = connectionDetailsProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||||
|
if (this.dataSourceClass.isAssignableFrom(bean.getClass()) && "dataSource".equals(beanName)) {
|
||||||
|
JdbcConnectionDetails connectionDetails = this.connectionDetailsProvider.getObject();
|
||||||
|
return processDataSource((T) bean, connectionDetails);
|
||||||
|
}
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Object processDataSource(T dataSource, JdbcConnectionDetails connectionDetails);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
// Runs after ConfigurationPropertiesBindingPostProcessor
|
||||||
|
return Ordered.HIGHEST_PRECEDENCE + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* 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.autoconfigure.jdbc;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import oracle.ucp.jdbc.PoolDataSourceImpl;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post-processes beans of type {@link PoolDataSourceImpl} and name 'dataSource' to apply
|
||||||
|
* the values from {@link JdbcConnectionDetails}.
|
||||||
|
*
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class OracleUcpJdbcConnectionDetailsBeanPostProcessor
|
||||||
|
extends JdbcConnectionDetailsBeanPostProcessor<PoolDataSourceImpl> {
|
||||||
|
|
||||||
|
OracleUcpJdbcConnectionDetailsBeanPostProcessor(ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||||
|
super(PoolDataSourceImpl.class, connectionDetailsProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object processDataSource(PoolDataSourceImpl dataSource, JdbcConnectionDetails connectionDetails) {
|
||||||
|
try {
|
||||||
|
dataSource.setURL(connectionDetails.getJdbcUrl());
|
||||||
|
dataSource.setUser(connectionDetails.getUsername());
|
||||||
|
dataSource.setPassword(connectionDetails.getPassword());
|
||||||
|
dataSource.setConnectionFactoryClassName(connectionDetails.getDriverClassName());
|
||||||
|
return dataSource;
|
||||||
|
}
|
||||||
|
catch (SQLException ex) {
|
||||||
|
throw new RuntimeException("Failed to set URL / user / password of datasource", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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.autoconfigure.jdbc;
|
||||||
|
|
||||||
|
import org.apache.tomcat.jdbc.pool.DataSource;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post-processes beans of type {@link DataSource} and name 'dataSource' to apply the
|
||||||
|
* values from {@link JdbcConnectionDetails}.
|
||||||
|
*
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class TomcatJdbcConnectionDetailsBeanPostProcessor extends JdbcConnectionDetailsBeanPostProcessor<DataSource> {
|
||||||
|
|
||||||
|
TomcatJdbcConnectionDetailsBeanPostProcessor(ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||||
|
super(DataSource.class, connectionDetailsProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object processDataSource(DataSource dataSource, JdbcConnectionDetails connectionDetails) {
|
||||||
|
dataSource.setUrl(connectionDetails.getJdbcUrl());
|
||||||
|
dataSource.setUsername(connectionDetails.getUsername());
|
||||||
|
dataSource.setPassword(connectionDetails.getPassword());
|
||||||
|
dataSource.setDriverClassName(connectionDetails.getDriverClassName());
|
||||||
|
return dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2022 the original author or authors.
|
* Copyright 2012-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -40,7 +40,6 @@ import org.springframework.boot.context.properties.source.ConfigurationPropertyN
|
|||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertyNameAliases;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertyNameAliases;
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
|
||||||
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
|
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
|
||||||
import org.springframework.boot.jdbc.DatabaseDriver;
|
|
||||||
import org.springframework.boot.jdbc.XADataSourceWrapper;
|
import org.springframework.boot.jdbc.XADataSourceWrapper;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
||||||
@ -54,6 +53,8 @@ import org.springframework.util.StringUtils;
|
|||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Josh Long
|
* @author Josh Long
|
||||||
* @author Madhura Bhave
|
* @author Madhura Bhave
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*/
|
*/
|
||||||
@AutoConfiguration(before = DataSourceAutoConfiguration.class)
|
@AutoConfiguration(before = DataSourceAutoConfiguration.class)
|
||||||
@ -67,8 +68,10 @@ public class XADataSourceAutoConfiguration implements BeanClassLoaderAware {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public DataSource dataSource(XADataSourceWrapper wrapper, DataSourceProperties properties,
|
public DataSource dataSource(XADataSourceWrapper wrapper, DataSourceProperties properties,
|
||||||
ObjectProvider<XADataSource> xaDataSource) throws Exception {
|
ObjectProvider<JdbcConnectionDetails> connectionDetails, ObjectProvider<XADataSource> xaDataSource)
|
||||||
return wrapper.wrapDataSource(xaDataSource.getIfAvailable(() -> createXaDataSource(properties)));
|
throws Exception {
|
||||||
|
return wrapper.wrapDataSource(xaDataSource.getIfAvailable(() -> createXaDataSource(properties,
|
||||||
|
connectionDetails.getIfAvailable(() -> new PropertiesJdbcConnectionDetails(properties)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -76,14 +79,11 @@ public class XADataSourceAutoConfiguration implements BeanClassLoaderAware {
|
|||||||
this.classLoader = classLoader;
|
this.classLoader = classLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
private XADataSource createXaDataSource(DataSourceProperties properties) {
|
private XADataSource createXaDataSource(DataSourceProperties properties, JdbcConnectionDetails connectionDetails) {
|
||||||
String className = properties.getXa().getDataSourceClassName();
|
String className = connectionDetails.getXaDataSourceClassName();
|
||||||
if (!StringUtils.hasLength(className)) {
|
|
||||||
className = DatabaseDriver.fromJdbcUrl(properties.determineUrl()).getXaDataSourceClassName();
|
|
||||||
}
|
|
||||||
Assert.state(StringUtils.hasLength(className), "No XA DataSource class name specified");
|
Assert.state(StringUtils.hasLength(className), "No XA DataSource class name specified");
|
||||||
XADataSource dataSource = createXaDataSourceInstance(className);
|
XADataSource dataSource = createXaDataSourceInstance(className);
|
||||||
bindXaProperties(dataSource, properties);
|
bindXaProperties(dataSource, properties, connectionDetails);
|
||||||
return dataSource;
|
return dataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,18 +99,19 @@ public class XADataSourceAutoConfiguration implements BeanClassLoaderAware {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindXaProperties(XADataSource target, DataSourceProperties dataSourceProperties) {
|
private void bindXaProperties(XADataSource target, DataSourceProperties dataSourceProperties,
|
||||||
Binder binder = new Binder(getBinderSource(dataSourceProperties));
|
JdbcConnectionDetails connectionDetails) {
|
||||||
|
Binder binder = new Binder(getBinderSource(dataSourceProperties, connectionDetails));
|
||||||
binder.bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(target));
|
binder.bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(target));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConfigurationPropertySource getBinderSource(DataSourceProperties dataSourceProperties) {
|
private ConfigurationPropertySource getBinderSource(DataSourceProperties dataSourceProperties,
|
||||||
Map<Object, Object> properties = new HashMap<>();
|
JdbcConnectionDetails connectionDetails) {
|
||||||
properties.putAll(dataSourceProperties.getXa().getProperties());
|
Map<Object, Object> properties = new HashMap<>(dataSourceProperties.getXa().getProperties());
|
||||||
properties.computeIfAbsent("user", (key) -> dataSourceProperties.determineUsername());
|
properties.computeIfAbsent("user", (key) -> connectionDetails.getUsername());
|
||||||
properties.computeIfAbsent("password", (key) -> dataSourceProperties.determinePassword());
|
properties.computeIfAbsent("password", (key) -> connectionDetails.getPassword());
|
||||||
try {
|
try {
|
||||||
properties.computeIfAbsent("url", (key) -> dataSourceProperties.determineUrl());
|
properties.computeIfAbsent("url", (key) -> connectionDetails.getJdbcUrl());
|
||||||
}
|
}
|
||||||
catch (DataSourceBeanCreationException ex) {
|
catch (DataSourceBeanCreationException ex) {
|
||||||
// Continue as not all XA DataSource's require a URL
|
// Continue as not all XA DataSource's require a URL
|
||||||
@ -121,4 +122,45 @@ public class XADataSourceAutoConfiguration implements BeanClassLoaderAware {
|
|||||||
return source.withAliases(aliases);
|
return source.withAliases(aliases);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapts {@link DataSourceProperties} to {@link JdbcConnectionDetails}.
|
||||||
|
*/
|
||||||
|
private static class PropertiesJdbcConnectionDetails implements JdbcConnectionDetails {
|
||||||
|
|
||||||
|
private final DataSourceProperties properties;
|
||||||
|
|
||||||
|
PropertiesJdbcConnectionDetails(DataSourceProperties properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return this.properties.determineUsername();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return this.properties.determinePassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getJdbcUrl() {
|
||||||
|
return this.properties.determineUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDriverClassName() {
|
||||||
|
return (this.properties.getDriverClassName() != null) ? this.properties.getDriverClassName()
|
||||||
|
: JdbcConnectionDetails.super.getDriverClassName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getXaDataSourceClassName() {
|
||||||
|
return (this.properties.getXa().getDataSourceClassName() != null)
|
||||||
|
? this.properties.getXa().getDataSourceClassName()
|
||||||
|
: JdbcConnectionDetails.super.getXaDataSourceClassName();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
|||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
|
||||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseAutoConfigurationRuntimeHints;
|
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseAutoConfigurationRuntimeHints;
|
||||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseDataSourceCondition;
|
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseDataSourceCondition;
|
||||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
||||||
@ -61,6 +62,7 @@ import org.springframework.util.StringUtils;
|
|||||||
* @author András Deák
|
* @author András Deák
|
||||||
* @author Ferenc Gratzer
|
* @author Ferenc Gratzer
|
||||||
* @author Evgeniy Cheban
|
* @author Evgeniy Cheban
|
||||||
|
* @author Moritz Halbritter
|
||||||
* @since 1.1.0
|
* @since 1.1.0
|
||||||
*/
|
*/
|
||||||
@AutoConfiguration(after = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
|
@AutoConfiguration(after = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
|
||||||
@ -83,38 +85,34 @@ public class LiquibaseAutoConfiguration {
|
|||||||
@EnableConfigurationProperties(LiquibaseProperties.class)
|
@EnableConfigurationProperties(LiquibaseProperties.class)
|
||||||
public static class LiquibaseConfiguration {
|
public static class LiquibaseConfiguration {
|
||||||
|
|
||||||
private final LiquibaseProperties properties;
|
|
||||||
|
|
||||||
public LiquibaseConfiguration(LiquibaseProperties properties) {
|
|
||||||
this.properties = properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SpringLiquibase liquibase(ObjectProvider<DataSource> dataSource,
|
public SpringLiquibase liquibase(ObjectProvider<DataSource> dataSource,
|
||||||
@LiquibaseDataSource ObjectProvider<DataSource> liquibaseDataSource) {
|
@LiquibaseDataSource ObjectProvider<DataSource> liquibaseDataSource, LiquibaseProperties properties,
|
||||||
|
ObjectProvider<JdbcConnectionDetails> connectionDetails) {
|
||||||
SpringLiquibase liquibase = createSpringLiquibase(liquibaseDataSource.getIfAvailable(),
|
SpringLiquibase liquibase = createSpringLiquibase(liquibaseDataSource.getIfAvailable(),
|
||||||
dataSource.getIfUnique());
|
dataSource.getIfUnique(),
|
||||||
liquibase.setChangeLog(this.properties.getChangeLog());
|
connectionDetails.getIfAvailable(() -> new LiquibasePropertiesJdbcConnectionDetails(properties)));
|
||||||
liquibase.setClearCheckSums(this.properties.isClearChecksums());
|
liquibase.setChangeLog(properties.getChangeLog());
|
||||||
liquibase.setContexts(this.properties.getContexts());
|
liquibase.setClearCheckSums(properties.isClearChecksums());
|
||||||
liquibase.setDefaultSchema(this.properties.getDefaultSchema());
|
liquibase.setContexts(properties.getContexts());
|
||||||
liquibase.setLiquibaseSchema(this.properties.getLiquibaseSchema());
|
liquibase.setDefaultSchema(properties.getDefaultSchema());
|
||||||
liquibase.setLiquibaseTablespace(this.properties.getLiquibaseTablespace());
|
liquibase.setLiquibaseSchema(properties.getLiquibaseSchema());
|
||||||
liquibase.setDatabaseChangeLogTable(this.properties.getDatabaseChangeLogTable());
|
liquibase.setLiquibaseTablespace(properties.getLiquibaseTablespace());
|
||||||
liquibase.setDatabaseChangeLogLockTable(this.properties.getDatabaseChangeLogLockTable());
|
liquibase.setDatabaseChangeLogTable(properties.getDatabaseChangeLogTable());
|
||||||
liquibase.setDropFirst(this.properties.isDropFirst());
|
liquibase.setDatabaseChangeLogLockTable(properties.getDatabaseChangeLogLockTable());
|
||||||
liquibase.setShouldRun(this.properties.isEnabled());
|
liquibase.setDropFirst(properties.isDropFirst());
|
||||||
liquibase.setLabelFilter(this.properties.getLabelFilter());
|
liquibase.setShouldRun(properties.isEnabled());
|
||||||
liquibase.setChangeLogParameters(this.properties.getParameters());
|
liquibase.setLabelFilter(properties.getLabelFilter());
|
||||||
liquibase.setRollbackFile(this.properties.getRollbackFile());
|
liquibase.setChangeLogParameters(properties.getParameters());
|
||||||
liquibase.setTestRollbackOnUpdate(this.properties.isTestRollbackOnUpdate());
|
liquibase.setRollbackFile(properties.getRollbackFile());
|
||||||
liquibase.setTag(this.properties.getTag());
|
liquibase.setTestRollbackOnUpdate(properties.isTestRollbackOnUpdate());
|
||||||
|
liquibase.setTag(properties.getTag());
|
||||||
return liquibase;
|
return liquibase;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SpringLiquibase createSpringLiquibase(DataSource liquibaseDataSource, DataSource dataSource) {
|
private SpringLiquibase createSpringLiquibase(DataSource liquibaseDataSource, DataSource dataSource,
|
||||||
LiquibaseProperties properties = this.properties;
|
JdbcConnectionDetails connectionDetails) {
|
||||||
DataSource migrationDataSource = getMigrationDataSource(liquibaseDataSource, dataSource, properties);
|
DataSource migrationDataSource = getMigrationDataSource(liquibaseDataSource, dataSource, connectionDetails);
|
||||||
SpringLiquibase liquibase = (migrationDataSource == liquibaseDataSource
|
SpringLiquibase liquibase = (migrationDataSource == liquibaseDataSource
|
||||||
|| migrationDataSource == dataSource) ? new SpringLiquibase()
|
|| migrationDataSource == dataSource) ? new SpringLiquibase()
|
||||||
: new DataSourceClosingSpringLiquibase();
|
: new DataSourceClosingSpringLiquibase();
|
||||||
@ -123,31 +121,34 @@ public class LiquibaseAutoConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private DataSource getMigrationDataSource(DataSource liquibaseDataSource, DataSource dataSource,
|
private DataSource getMigrationDataSource(DataSource liquibaseDataSource, DataSource dataSource,
|
||||||
LiquibaseProperties properties) {
|
JdbcConnectionDetails connectionDetails) {
|
||||||
if (liquibaseDataSource != null) {
|
if (liquibaseDataSource != null) {
|
||||||
return liquibaseDataSource;
|
return liquibaseDataSource;
|
||||||
}
|
}
|
||||||
if (properties.getUrl() != null) {
|
String url = connectionDetails.getJdbcUrl();
|
||||||
|
if (url != null) {
|
||||||
DataSourceBuilder<?> builder = DataSourceBuilder.create().type(SimpleDriverDataSource.class);
|
DataSourceBuilder<?> builder = DataSourceBuilder.create().type(SimpleDriverDataSource.class);
|
||||||
builder.url(properties.getUrl());
|
builder.url(url);
|
||||||
applyCommonBuilderProperties(properties, builder);
|
applyConnectionDetails(connectionDetails, builder);
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
if (properties.getUser() != null && dataSource != null) {
|
String user = connectionDetails.getUsername();
|
||||||
|
if (user != null && dataSource != null) {
|
||||||
DataSourceBuilder<?> builder = DataSourceBuilder.derivedFrom(dataSource)
|
DataSourceBuilder<?> builder = DataSourceBuilder.derivedFrom(dataSource)
|
||||||
.type(SimpleDriverDataSource.class);
|
.type(SimpleDriverDataSource.class);
|
||||||
applyCommonBuilderProperties(properties, builder);
|
applyConnectionDetails(connectionDetails, builder);
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
Assert.state(dataSource != null, "Liquibase migration DataSource missing");
|
Assert.state(dataSource != null, "Liquibase migration DataSource missing");
|
||||||
return dataSource;
|
return dataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyCommonBuilderProperties(LiquibaseProperties properties, DataSourceBuilder<?> builder) {
|
private void applyConnectionDetails(JdbcConnectionDetails connectionDetails, DataSourceBuilder<?> builder) {
|
||||||
builder.username(properties.getUser());
|
builder.username(connectionDetails.getUsername());
|
||||||
builder.password(properties.getPassword());
|
builder.password(connectionDetails.getPassword());
|
||||||
if (StringUtils.hasText(properties.getDriverClassName())) {
|
String driverClassName = connectionDetails.getDriverClassName();
|
||||||
builder.driverClassName(properties.getDriverClassName());
|
if (StringUtils.hasText(driverClassName)) {
|
||||||
|
builder.driverClassName(driverClassName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,6 +165,11 @@ public class LiquibaseAutoConfiguration {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ConditionalOnBean(JdbcConnectionDetails.class)
|
||||||
|
private static final class JdbcConnectionDetailsCondition {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@ConditionalOnProperty(prefix = "spring.liquibase", name = "url")
|
@ConditionalOnProperty(prefix = "spring.liquibase", name = "url")
|
||||||
private static final class LiquibaseUrlCondition {
|
private static final class LiquibaseUrlCondition {
|
||||||
|
|
||||||
@ -180,4 +186,37 @@ public class LiquibaseAutoConfiguration {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapts {@link LiquibaseProperties} to {@link JdbcConnectionDetails}.
|
||||||
|
*/
|
||||||
|
private static final class LiquibasePropertiesJdbcConnectionDetails implements JdbcConnectionDetails {
|
||||||
|
|
||||||
|
private final LiquibaseProperties properties;
|
||||||
|
|
||||||
|
private LiquibasePropertiesJdbcConnectionDetails(LiquibaseProperties properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return this.properties.getUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return this.properties.getPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getJdbcUrl() {
|
||||||
|
return this.properties.getUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDriverClassName() {
|
||||||
|
return this.properties.getDriverClassName();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurations;
|
|||||||
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayAutoConfigurationRuntimeHints;
|
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration.FlywayAutoConfigurationRuntimeHints;
|
||||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
||||||
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
|
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.boot.jdbc.DataSourceBuilder;
|
import org.springframework.boot.jdbc.DataSourceBuilder;
|
||||||
import org.springframework.boot.jdbc.SchemaManagement;
|
import org.springframework.boot.jdbc.SchemaManagement;
|
||||||
@ -120,6 +121,16 @@ class FlywayAutoConfigurationTests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createsDataSourceWithNoDataSourceBeanAndJdbcConnectionDetails() {
|
||||||
|
this.contextRunner
|
||||||
|
.withUserConfiguration(JdbcConnectionDetailsConfiguration.class, MockFlywayMigrationStrategy.class)
|
||||||
|
.run((context) -> {
|
||||||
|
assertThat(context).hasSingleBean(Flyway.class);
|
||||||
|
assertThat(context.getBean(Flyway.class).getConfiguration().getDataSource()).isNotNull();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void backsOffWithFlywayUrlAndNoSpringJdbc() {
|
void backsOffWithFlywayUrlAndNoSpringJdbc() {
|
||||||
this.contextRunner.withPropertyValues("spring.flyway.url:jdbc:hsqldb:mem:" + UUID.randomUUID())
|
this.contextRunner.withPropertyValues("spring.flyway.url:jdbc:hsqldb:mem:" + UUID.randomUUID())
|
||||||
@ -137,6 +148,28 @@ class FlywayAutoConfigurationTests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createDataSourceWithJdbcConnectionDetails() {
|
||||||
|
this.contextRunner
|
||||||
|
.withUserConfiguration(EmbeddedDataSourceConfiguration.class, JdbcConnectionDetailsConfiguration.class,
|
||||||
|
MockFlywayMigrationStrategy.class)
|
||||||
|
.withPropertyValues("spring.flyway.url=jdbc:hsqldb:mem:flywaytest", "spring.flyway.user=some-user",
|
||||||
|
"spring.flyway.password=some-password",
|
||||||
|
"spring.flyway.driver-class-name=org.hsqldb.jdbc.JDBCDriver")
|
||||||
|
.run((context) -> {
|
||||||
|
assertThat(context).hasSingleBean(Flyway.class);
|
||||||
|
Flyway flyway = context.getBean(Flyway.class);
|
||||||
|
DataSource dataSource = flyway.getConfiguration().getDataSource();
|
||||||
|
assertThat(dataSource).isInstanceOf(SimpleDriverDataSource.class);
|
||||||
|
SimpleDriverDataSource simpleDriverDataSource = (SimpleDriverDataSource) dataSource;
|
||||||
|
assertThat(simpleDriverDataSource.getUrl())
|
||||||
|
.isEqualTo("jdbc:postgresql://database.example.com:12345/database-1");
|
||||||
|
assertThat(simpleDriverDataSource.getUsername()).isEqualTo("user-1");
|
||||||
|
assertThat(simpleDriverDataSource.getPassword()).isEqualTo("secret-1");
|
||||||
|
assertThat(simpleDriverDataSource.getDriver()).isInstanceOf(org.postgresql.Driver.class);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void createDataSourceWithUser() {
|
void createDataSourceWithUser() {
|
||||||
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
|
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
|
||||||
@ -200,6 +233,19 @@ class FlywayAutoConfigurationTests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void flywayDataSourceIsUsedWhenJdbcConnectionDetailsIsAvailable() {
|
||||||
|
this.contextRunner
|
||||||
|
.withUserConfiguration(FlywayDataSourceConfiguration.class, EmbeddedDataSourceConfiguration.class,
|
||||||
|
JdbcConnectionDetailsConfiguration.class)
|
||||||
|
.run((context) -> {
|
||||||
|
assertThat(context).hasSingleBean(JdbcConnectionDetails.class);
|
||||||
|
assertThat(context).hasSingleBean(Flyway.class);
|
||||||
|
assertThat(context.getBean(Flyway.class).getConfiguration().getDataSource())
|
||||||
|
.isEqualTo(context.getBean("flywayDataSource"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void flywayDataSourceWithoutDataSourceAutoConfiguration() {
|
void flywayDataSourceWithoutDataSourceAutoConfiguration() {
|
||||||
this.contextRunner.withUserConfiguration(FlywayDataSourceConfiguration.class).run((context) -> {
|
this.contextRunner.withUserConfiguration(FlywayDataSourceConfiguration.class).run((context) -> {
|
||||||
@ -1036,4 +1082,31 @@ class FlywayAutoConfigurationTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
static class JdbcConnectionDetailsConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
JdbcConnectionDetails jdbcConnectionDetails() {
|
||||||
|
return new JdbcConnectionDetails() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getJdbcUrl() {
|
||||||
|
return "jdbc:postgresql://database.example.com:12345/database-1";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return "user-1";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return "secret-1";
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ import com.zaxxer.hikari.HikariDataSource;
|
|||||||
import io.r2dbc.spi.ConnectionFactory;
|
import io.r2dbc.spi.ConnectionFactory;
|
||||||
import oracle.ucp.jdbc.PoolDataSourceImpl;
|
import oracle.ucp.jdbc.PoolDataSourceImpl;
|
||||||
import org.apache.commons.dbcp2.BasicDataSource;
|
import org.apache.commons.dbcp2.BasicDataSource;
|
||||||
|
import org.assertj.core.api.InstanceOfAssertFactories;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.beans.factory.BeanCreationException;
|
import org.springframework.beans.factory.BeanCreationException;
|
||||||
@ -60,6 +61,9 @@ import static org.mockito.Mockito.mock;
|
|||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
class DataSourceAutoConfigurationTests {
|
class DataSourceAutoConfigurationTests {
|
||||||
|
|
||||||
@ -244,6 +248,41 @@ class DataSourceAutoConfigurationTests {
|
|||||||
.run((context) -> assertThat(context).doesNotHaveBean(DataSourceScriptDatabaseInitializer.class));
|
.run((context) -> assertThat(context).doesNotHaveBean(DataSourceScriptDatabaseInitializer.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void dbcp2UsesJdbcConnectionDetailsIfAvailable() {
|
||||||
|
ApplicationContextRunner runner = new ApplicationContextRunner()
|
||||||
|
.withPropertyValues("spring.datasource.type=org.apache.commons.dbcp2.BasicDataSource",
|
||||||
|
"spring.datasource.dbcp2.url=jdbc:broken", "spring.datasource.dbcp2.username=alice",
|
||||||
|
"spring.datasource.dbcp2.password=secret")
|
||||||
|
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class));
|
||||||
|
runner.withUserConfiguration(JdbcConnectionDetailsConfiguration.class).run((context) -> {
|
||||||
|
DataSource dataSource = context.getBean(DataSource.class);
|
||||||
|
assertThat(dataSource).asInstanceOf(InstanceOfAssertFactories.type(BasicDataSource.class))
|
||||||
|
.satisfies((dbcp2) -> {
|
||||||
|
assertThat(dbcp2.getUsername()).isEqualTo("user-1");
|
||||||
|
assertThat(dbcp2.getPassword()).isEqualTo("password-1");
|
||||||
|
assertThat(dbcp2.getDriverClassName()).isEqualTo("org.postgresql.Driver");
|
||||||
|
assertThat(dbcp2.getUrl()).isEqualTo("jdbc:postgresql://postgres.example.com:12345/database-1");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void genericUsesJdbcConnectionDetailsIfAvailable() {
|
||||||
|
ApplicationContextRunner runner = new ApplicationContextRunner()
|
||||||
|
.withPropertyValues("spring.datasource.type=" + TestDataSource.class.getName())
|
||||||
|
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class));
|
||||||
|
runner.withUserConfiguration(JdbcConnectionDetailsConfiguration.class).run((context) -> {
|
||||||
|
DataSource dataSource = context.getBean(DataSource.class);
|
||||||
|
assertThat(dataSource).isInstanceOf(TestDataSource.class);
|
||||||
|
TestDataSource source = (TestDataSource) dataSource;
|
||||||
|
assertThat(source.getUsername()).isEqualTo("user-1");
|
||||||
|
assertThat(source.getPassword()).isEqualTo("password-1");
|
||||||
|
assertThat(source.getDriver().getClass().getName()).isEqualTo("org.postgresql.Driver");
|
||||||
|
assertThat(source.getUrl()).isEqualTo("jdbc:postgresql://postgres.example.com:12345/database-1");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private static Function<ApplicationContextRunner, ApplicationContextRunner> hideConnectionPools() {
|
private static Function<ApplicationContextRunner, ApplicationContextRunner> hideConnectionPools() {
|
||||||
return (runner) -> runner.withClassLoader(new FilteredClassLoader("org.apache.tomcat", "com.zaxxer.hikari",
|
return (runner) -> runner.withClassLoader(new FilteredClassLoader("org.apache.tomcat", "com.zaxxer.hikari",
|
||||||
"org.apache.commons.dbcp2", "oracle.ucp.jdbc", "com.mchange"));
|
"org.apache.commons.dbcp2", "oracle.ucp.jdbc", "com.mchange"));
|
||||||
@ -259,6 +298,16 @@ class DataSourceAutoConfigurationTests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
static class JdbcConnectionDetailsConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
JdbcConnectionDetails sqlJdbcConnectionDetails() {
|
||||||
|
return new TestJdbcConnectionDetails();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
static class TestDataSourceConfiguration {
|
static class TestDataSourceConfiguration {
|
||||||
|
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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.autoconfigure.jdbc;
|
||||||
|
|
||||||
|
import org.apache.commons.dbcp2.BasicDataSource;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.jdbc.DatabaseDriver;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link Dbcp2JdbcConnectionDetailsBeanPostProcessor}.
|
||||||
|
*
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class Dbcp2JdbcConnectionDetailsBeanPostProcessorTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void setUsernamePasswordAndUrl() {
|
||||||
|
BasicDataSource dataSource = new BasicDataSource();
|
||||||
|
dataSource.setUrl("will-be-overwritten");
|
||||||
|
dataSource.setUsername("will-be-overwritten");
|
||||||
|
dataSource.setPassword("will-be-overwritten");
|
||||||
|
dataSource.setDriverClassName("will-be-overwritten");
|
||||||
|
new Dbcp2JdbcConnectionDetailsBeanPostProcessor(null).processDataSource(dataSource,
|
||||||
|
new TestJdbcConnectionDetails());
|
||||||
|
assertThat(dataSource.getUrl()).isEqualTo("jdbc:postgresql://postgres.example.com:12345/database-1");
|
||||||
|
assertThat(dataSource.getUsername()).isEqualTo("user-1");
|
||||||
|
assertThat(dataSource.getPassword()).isEqualTo("password-1");
|
||||||
|
assertThat(dataSource.getDriverClassName()).isEqualTo(DatabaseDriver.POSTGRESQL.getDriverClassName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -19,10 +19,13 @@ package org.springframework.boot.autoconfigure.jdbc;
|
|||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import com.zaxxer.hikari.HikariDataSource;
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
import org.assertj.core.api.InstanceOfAssertFactories;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
@ -31,9 +34,14 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
class HikariDataSourceConfigurationTests {
|
class HikariDataSourceConfigurationTests {
|
||||||
|
|
||||||
|
private static final String PREFIX = "spring.datasource.hikari.";
|
||||||
|
|
||||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||||
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class))
|
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class))
|
||||||
.withPropertyValues("spring.datasource.type=" + HikariDataSource.class.getName());
|
.withPropertyValues("spring.datasource.type=" + HikariDataSource.class.getName());
|
||||||
@ -49,8 +57,7 @@ class HikariDataSourceConfigurationTests {
|
|||||||
@Test
|
@Test
|
||||||
void testDataSourcePropertiesOverridden() {
|
void testDataSourcePropertiesOverridden() {
|
||||||
this.contextRunner
|
this.contextRunner
|
||||||
.withPropertyValues("spring.datasource.hikari.jdbc-url=jdbc:foo//bar/spam",
|
.withPropertyValues(PREFIX + "jdbc-url=jdbc:foo//bar/spam", "spring.datasource.hikari.max-lifetime=1234")
|
||||||
"spring.datasource.hikari.max-lifetime=1234")
|
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
HikariDataSource ds = context.getBean(HikariDataSource.class);
|
HikariDataSource ds = context.getBean(HikariDataSource.class);
|
||||||
assertThat(ds.getJdbcUrl()).isEqualTo("jdbc:foo//bar/spam");
|
assertThat(ds.getJdbcUrl()).isEqualTo("jdbc:foo//bar/spam");
|
||||||
@ -61,8 +68,7 @@ class HikariDataSourceConfigurationTests {
|
|||||||
@Test
|
@Test
|
||||||
void testDataSourceGenericPropertiesOverridden() {
|
void testDataSourceGenericPropertiesOverridden() {
|
||||||
this.contextRunner
|
this.contextRunner
|
||||||
.withPropertyValues(
|
.withPropertyValues(PREFIX + "data-source-properties.dataSourceClassName=org.h2.JDBCDataSource")
|
||||||
"spring.datasource.hikari.data-source-properties.dataSourceClassName=org.h2.JDBCDataSource")
|
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
HikariDataSource ds = context.getBean(HikariDataSource.class);
|
HikariDataSource ds = context.getBean(HikariDataSource.class);
|
||||||
assertThat(ds.getDataSourceProperties().getProperty("dataSourceClassName"))
|
assertThat(ds.getDataSourceProperties().getProperty("dataSourceClassName"))
|
||||||
@ -90,12 +96,38 @@ class HikariDataSourceConfigurationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void poolNameTakesPrecedenceOverName() {
|
void poolNameTakesPrecedenceOverName() {
|
||||||
this.contextRunner
|
this.contextRunner.withPropertyValues("spring.datasource.name=myDS", PREFIX + "pool-name=myHikariDS")
|
||||||
.withPropertyValues("spring.datasource.name=myDS", "spring.datasource.hikari.pool-name=myHikariDS")
|
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
HikariDataSource ds = context.getBean(HikariDataSource.class);
|
HikariDataSource ds = context.getBean(HikariDataSource.class);
|
||||||
assertThat(ds.getPoolName()).isEqualTo("myHikariDS");
|
assertThat(ds.getPoolName()).isEqualTo("myHikariDS");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void usesConnectionDetailsIfAvailable() {
|
||||||
|
this.contextRunner.withUserConfiguration(ConnectionDetailsConfiguration.class)
|
||||||
|
.withPropertyValues(PREFIX + "url=jdbc:broken", PREFIX + "username=alice", PREFIX + "password=secret")
|
||||||
|
.run((context) -> {
|
||||||
|
DataSource dataSource = context.getBean(DataSource.class);
|
||||||
|
assertThat(dataSource).asInstanceOf(InstanceOfAssertFactories.type(HikariDataSource.class))
|
||||||
|
.satisfies((hikari) -> {
|
||||||
|
assertThat(hikari.getUsername()).isEqualTo("user-1");
|
||||||
|
assertThat(hikari.getPassword()).isEqualTo("password-1");
|
||||||
|
assertThat(hikari.getDriverClassName()).isEqualTo("org.postgresql.Driver");
|
||||||
|
assertThat(hikari.getJdbcUrl())
|
||||||
|
.isEqualTo("jdbc:postgresql://postgres.example.com:12345/database-1");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
static class ConnectionDetailsConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
JdbcConnectionDetails sqlConnectionDetails() {
|
||||||
|
return new TestJdbcConnectionDetails();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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.autoconfigure.jdbc;
|
||||||
|
|
||||||
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.jdbc.DatabaseDriver;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link HikariJdbcConnectionDetailsBeanPostProcessor}.
|
||||||
|
*
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class HikariJdbcConnectionDetailsBeanPostProcessorTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void setUsernamePasswordAndUrl() {
|
||||||
|
HikariDataSource dataSource = new HikariDataSource();
|
||||||
|
dataSource.setJdbcUrl("will-be-overwritten");
|
||||||
|
dataSource.setUsername("will-be-overwritten");
|
||||||
|
dataSource.setPassword("will-be-overwritten");
|
||||||
|
dataSource.setDriverClassName(DatabaseDriver.H2.getDriverClassName());
|
||||||
|
new HikariJdbcConnectionDetailsBeanPostProcessor(null).processDataSource(dataSource,
|
||||||
|
new TestJdbcConnectionDetails());
|
||||||
|
assertThat(dataSource.getJdbcUrl()).isEqualTo("jdbc:postgresql://postgres.example.com:12345/database-1");
|
||||||
|
assertThat(dataSource.getUsername()).isEqualTo("user-1");
|
||||||
|
assertThat(dataSource.getPassword()).isEqualTo("password-1");
|
||||||
|
assertThat(dataSource.getDriverClassName()).isEqualTo(DatabaseDriver.POSTGRESQL.getDriverClassName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -22,10 +22,13 @@ import javax.sql.DataSource;
|
|||||||
|
|
||||||
import oracle.ucp.jdbc.PoolDataSource;
|
import oracle.ucp.jdbc.PoolDataSource;
|
||||||
import oracle.ucp.jdbc.PoolDataSourceImpl;
|
import oracle.ucp.jdbc.PoolDataSourceImpl;
|
||||||
|
import oracle.ucp.util.OpaqueString;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
@ -34,9 +37,14 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
*
|
*
|
||||||
* @author Fabio Grassi
|
* @author Fabio Grassi
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
class OracleUcpDataSourceConfigurationTests {
|
class OracleUcpDataSourceConfigurationTests {
|
||||||
|
|
||||||
|
private static final String PREFIX = "spring.datasource.oracleucp.";
|
||||||
|
|
||||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||||
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class))
|
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class))
|
||||||
.withPropertyValues("spring.datasource.type=" + PoolDataSource.class.getName());
|
.withPropertyValues("spring.datasource.type=" + PoolDataSource.class.getName());
|
||||||
@ -54,9 +62,7 @@ class OracleUcpDataSourceConfigurationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testDataSourcePropertiesOverridden() {
|
void testDataSourcePropertiesOverridden() {
|
||||||
this.contextRunner
|
this.contextRunner.withPropertyValues(PREFIX + "url=jdbc:foo//bar/spam", PREFIX + "max-idle-time=1234")
|
||||||
.withPropertyValues("spring.datasource.oracleucp.url=jdbc:foo//bar/spam",
|
|
||||||
"spring.datasource.oracleucp.max-idle-time=1234")
|
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
PoolDataSourceImpl ds = context.getBean(PoolDataSourceImpl.class);
|
PoolDataSourceImpl ds = context.getBean(PoolDataSourceImpl.class);
|
||||||
assertThat(ds.getURL()).isEqualTo("jdbc:foo//bar/spam");
|
assertThat(ds.getURL()).isEqualTo("jdbc:foo//bar/spam");
|
||||||
@ -66,11 +72,10 @@ class OracleUcpDataSourceConfigurationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testDataSourceConnectionPropertiesOverridden() {
|
void testDataSourceConnectionPropertiesOverridden() {
|
||||||
this.contextRunner.withPropertyValues("spring.datasource.oracleucp.connection-properties.autoCommit=false")
|
this.contextRunner.withPropertyValues(PREFIX + "connection-properties.autoCommit=false").run((context) -> {
|
||||||
.run((context) -> {
|
PoolDataSourceImpl ds = context.getBean(PoolDataSourceImpl.class);
|
||||||
PoolDataSourceImpl ds = context.getBean(PoolDataSourceImpl.class);
|
assertThat(ds.getConnectionProperty("autoCommit")).isEqualTo("false");
|
||||||
assertThat(ds.getConnectionProperty("autoCommit")).isEqualTo("false");
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -100,12 +105,38 @@ class OracleUcpDataSourceConfigurationTests {
|
|||||||
@Test
|
@Test
|
||||||
void poolNameTakesPrecedenceOverName() {
|
void poolNameTakesPrecedenceOverName() {
|
||||||
this.contextRunner
|
this.contextRunner
|
||||||
.withPropertyValues("spring.datasource.name=myDS",
|
.withPropertyValues("spring.datasource.name=myDS", PREFIX + "connection-pool-name=myOracleUcpDS")
|
||||||
"spring.datasource.oracleucp.connection-pool-name=myOracleUcpDS")
|
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
PoolDataSourceImpl ds = context.getBean(PoolDataSourceImpl.class);
|
PoolDataSourceImpl ds = context.getBean(PoolDataSourceImpl.class);
|
||||||
assertThat(ds.getConnectionPoolName()).isEqualTo("myOracleUcpDS");
|
assertThat(ds.getConnectionPoolName()).isEqualTo("myOracleUcpDS");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void usesJdbcConnectionDetailsIfAvailable() {
|
||||||
|
this.contextRunner.withUserConfiguration(ConnectionDetailsConfiguration.class)
|
||||||
|
.withPropertyValues(PREFIX + "url=jdbc:broken", PREFIX + "username=alice", PREFIX + "password=secret")
|
||||||
|
.run((context) -> {
|
||||||
|
DataSource dataSource = context.getBean(DataSource.class);
|
||||||
|
assertThat(dataSource).isInstanceOf(PoolDataSourceImpl.class);
|
||||||
|
PoolDataSourceImpl oracleUcp = (PoolDataSourceImpl) dataSource;
|
||||||
|
assertThat(oracleUcp.getUser()).isEqualTo("user-1");
|
||||||
|
assertThat(oracleUcp).extracting("password")
|
||||||
|
.extracting((o) -> ((OpaqueString) o).get())
|
||||||
|
.isEqualTo("password-1");
|
||||||
|
assertThat(oracleUcp.getConnectionFactoryClassName()).isEqualTo("org.postgresql.Driver");
|
||||||
|
assertThat(oracleUcp.getURL()).isEqualTo("jdbc:postgresql://postgres.example.com:12345/database-1");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
static class ConnectionDetailsConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
JdbcConnectionDetails jdbcConnectionDetails() {
|
||||||
|
return new TestJdbcConnectionDetails();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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.autoconfigure.jdbc;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import oracle.ucp.jdbc.PoolDataSourceImpl;
|
||||||
|
import oracle.ucp.util.OpaqueString;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.jdbc.DatabaseDriver;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link OracleUcpJdbcConnectionDetailsBeanPostProcessor}.
|
||||||
|
*
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class OracleUcpJdbcConnectionDetailsBeanPostProcessorTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void setUsernamePasswordAndUrl() throws SQLException {
|
||||||
|
PoolDataSourceImpl dataSource = new PoolDataSourceImpl();
|
||||||
|
dataSource.setURL("will-be-overwritten");
|
||||||
|
dataSource.setUser("will-be-overwritten");
|
||||||
|
dataSource.setPassword("will-be-overwritten");
|
||||||
|
dataSource.setConnectionFactoryClassName("will-be-overwritten");
|
||||||
|
new OracleUcpJdbcConnectionDetailsBeanPostProcessor(null).processDataSource(dataSource,
|
||||||
|
new TestJdbcConnectionDetails());
|
||||||
|
assertThat(dataSource.getURL()).isEqualTo("jdbc:postgresql://postgres.example.com:12345/database-1");
|
||||||
|
assertThat(dataSource.getUser()).isEqualTo("user-1");
|
||||||
|
assertThat(dataSource).extracting("password")
|
||||||
|
.extracting((password) -> ((OpaqueString) password).get())
|
||||||
|
.isEqualTo("password-1");
|
||||||
|
assertThat(dataSource.getConnectionFactoryClassName())
|
||||||
|
.isEqualTo(DatabaseDriver.POSTGRESQL.getDriverClassName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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.autoconfigure.jdbc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link JdbcConnectionDetails} used in tests.
|
||||||
|
*
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
*/
|
||||||
|
class TestJdbcConnectionDetails implements JdbcConnectionDetails {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getJdbcUrl() {
|
||||||
|
return "jdbc:postgresql://postgres.example.com:12345/database-1";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return "user-1";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return "password-1";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -24,9 +24,11 @@ import org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReport;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.boot.jdbc.DataSourceBuilder;
|
import org.springframework.boot.jdbc.DataSourceBuilder;
|
||||||
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||||
import org.springframework.boot.test.util.TestPropertyValues;
|
import org.springframework.boot.test.util.TestPropertyValues;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@ -41,6 +43,9 @@ import static org.junit.jupiter.api.Assertions.fail;
|
|||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
class TomcatDataSourceConfigurationTests {
|
class TomcatDataSourceConfigurationTests {
|
||||||
|
|
||||||
@ -48,6 +53,10 @@ class TomcatDataSourceConfigurationTests {
|
|||||||
|
|
||||||
private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||||
|
|
||||||
|
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||||
|
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class))
|
||||||
|
.withPropertyValues("spring.datasource.type=" + org.apache.tomcat.jdbc.pool.DataSource.class.getName());
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void init() {
|
void init() {
|
||||||
TestPropertyValues.of(PREFIX + "initialize:false").applyTo(this.context);
|
TestPropertyValues.of(PREFIX + "initialize:false").applyTo(this.context);
|
||||||
@ -106,6 +115,32 @@ class TomcatDataSourceConfigurationTests {
|
|||||||
assertThat(ds.getValidationInterval()).isEqualTo(3000L);
|
assertThat(ds.getValidationInterval()).isEqualTo(3000L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void usesJdbcConnectionDetailsIfAvailable() {
|
||||||
|
this.contextRunner.withUserConfiguration(ConnectionDetailsConfiguration.class)
|
||||||
|
.withPropertyValues(PREFIX + "url=jdbc:broken", PREFIX + "username=alice", PREFIX + "password=secret")
|
||||||
|
.run((context) -> {
|
||||||
|
DataSource dataSource = context.getBean(DataSource.class);
|
||||||
|
assertThat(dataSource).isInstanceOf(org.apache.tomcat.jdbc.pool.DataSource.class);
|
||||||
|
org.apache.tomcat.jdbc.pool.DataSource tomcat = (org.apache.tomcat.jdbc.pool.DataSource) dataSource;
|
||||||
|
assertThat(tomcat.getPoolProperties().getUsername()).isEqualTo("user-1");
|
||||||
|
assertThat(tomcat.getPoolProperties().getPassword()).isEqualTo("password-1");
|
||||||
|
assertThat(tomcat.getPoolProperties().getDriverClassName()).isEqualTo("org.postgresql.Driver");
|
||||||
|
assertThat(tomcat.getPoolProperties().getUrl())
|
||||||
|
.isEqualTo("jdbc:postgresql://postgres.example.com:12345/database-1");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
static class ConnectionDetailsConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
JdbcConnectionDetails jdbcConnectionDetails() {
|
||||||
|
return new TestJdbcConnectionDetails();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@EnableConfigurationProperties
|
@EnableConfigurationProperties
|
||||||
@EnableMBeanExport
|
@EnableMBeanExport
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* 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.autoconfigure.jdbc;
|
||||||
|
|
||||||
|
import org.apache.tomcat.jdbc.pool.DataSource;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.jdbc.DatabaseDriver;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link TomcatJdbcConnectionDetailsBeanPostProcessor}.
|
||||||
|
*
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class TomcatJdbcConnectionDetailsBeanPostProcessorTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void setUsernamePasswordAndUrl() {
|
||||||
|
DataSource dataSource = new DataSource();
|
||||||
|
dataSource.setUrl("will-be-overwritten");
|
||||||
|
dataSource.setUsername("will-be-overwritten");
|
||||||
|
dataSource.setPassword("will-be-overwritten");
|
||||||
|
dataSource.setDriverClassName("will-be-overwritten");
|
||||||
|
new TomcatJdbcConnectionDetailsBeanPostProcessor(null).processDataSource(dataSource,
|
||||||
|
new TestJdbcConnectionDetails());
|
||||||
|
assertThat(dataSource.getUrl()).isEqualTo("jdbc:postgresql://postgres.example.com:12345/database-1");
|
||||||
|
assertThat(dataSource.getUsername()).isEqualTo("user-1");
|
||||||
|
assertThat(dataSource.getPoolProperties().getPassword()).isEqualTo("password-1");
|
||||||
|
assertThat(dataSource.getPoolProperties().getDriverClassName())
|
||||||
|
.isEqualTo(DatabaseDriver.POSTGRESQL.getDriverClassName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -22,6 +22,7 @@ import javax.sql.XADataSource;
|
|||||||
import com.ibm.db2.jcc.DB2XADataSource;
|
import com.ibm.db2.jcc.DB2XADataSource;
|
||||||
import org.hsqldb.jdbc.pool.JDBCXADataSource;
|
import org.hsqldb.jdbc.pool.JDBCXADataSource;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.postgresql.xa.PGXADataSource;
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
import org.springframework.boot.jdbc.XADataSourceWrapper;
|
import org.springframework.boot.jdbc.XADataSourceWrapper;
|
||||||
@ -40,6 +41,8 @@ import static org.mockito.Mockito.mock;
|
|||||||
* Tests for {@link XADataSourceAutoConfiguration}.
|
* Tests for {@link XADataSourceAutoConfiguration}.
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Andy Wilkinson
|
||||||
*/
|
*/
|
||||||
class XADataSourceAutoConfigurationTests {
|
class XADataSourceAutoConfigurationTests {
|
||||||
|
|
||||||
@ -90,6 +93,20 @@ class XADataSourceAutoConfigurationTests {
|
|||||||
assertThat(dataSource.getLoginTimeout()).isEqualTo(123);
|
assertThat(dataSource.getLoginTimeout()).isEqualTo(123);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldUseConnectionDetailsIfAvailable() {
|
||||||
|
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(XADataSourceAutoConfiguration.class))
|
||||||
|
.withUserConfiguration(FromProperties.class, JdbcConnectionDetailsConfiguration.class)
|
||||||
|
.run((context) -> {
|
||||||
|
MockXADataSourceWrapper wrapper = context.getBean(MockXADataSourceWrapper.class);
|
||||||
|
PGXADataSource dataSource = (PGXADataSource) wrapper.getXaDataSource();
|
||||||
|
assertThat(dataSource).isNotNull();
|
||||||
|
assertThat(dataSource.getUrl()).startsWith("jdbc:postgresql://postgres.example.com:12345/database-1");
|
||||||
|
assertThat(dataSource.getUser()).isEqualTo("user-1");
|
||||||
|
assertThat(dataSource.getPassword()).isEqualTo("password-1");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private ApplicationContext createContext(Class<?> configuration, String... env) {
|
private ApplicationContext createContext(Class<?> configuration, String... env) {
|
||||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||||
TestPropertyValues.of(env).applyTo(context);
|
TestPropertyValues.of(env).applyTo(context);
|
||||||
@ -98,6 +115,16 @@ class XADataSourceAutoConfigurationTests {
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
static class JdbcConnectionDetailsConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
JdbcConnectionDetails jdbcConnectionDetails() {
|
||||||
|
return new TestJdbcConnectionDetails();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
static class WrapExisting {
|
static class WrapExisting {
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ import java.util.function.Consumer;
|
|||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
import liquibase.integration.spring.SpringLiquibase;
|
import liquibase.integration.spring.SpringLiquibase;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@ -39,6 +40,7 @@ import org.springframework.beans.factory.BeanCreationException;
|
|||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
|
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
|
||||||
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
|
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration;
|
import org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseAutoConfigurationRuntimeHints;
|
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseAutoConfigurationRuntimeHints;
|
||||||
@ -75,6 +77,8 @@ import static org.assertj.core.api.Assertions.contentOf;
|
|||||||
* @author Andrii Hrytsiuk
|
* @author Andrii Hrytsiuk
|
||||||
* @author Ferenc Gratzer
|
* @author Ferenc Gratzer
|
||||||
* @author Evgeniy Cheban
|
* @author Evgeniy Cheban
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
@ExtendWith(OutputCaptureExtension.class)
|
@ExtendWith(OutputCaptureExtension.class)
|
||||||
class LiquibaseAutoConfigurationTests {
|
class LiquibaseAutoConfigurationTests {
|
||||||
@ -97,6 +101,18 @@ class LiquibaseAutoConfigurationTests {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createsDataSourceWithNoDataSourceBeanAndJdbcConnectionDetails() {
|
||||||
|
this.contextRunner.withSystemProperties("shouldRun=false")
|
||||||
|
.withUserConfiguration(JdbcConnectionDetailsConfiguration.class)
|
||||||
|
.run(assertLiquibase((liquibase) -> {
|
||||||
|
SimpleDriverDataSource dataSource = (SimpleDriverDataSource) liquibase.getDataSource();
|
||||||
|
assertThat(dataSource.getUrl()).isEqualTo("jdbc:postgresql://database.example.com:12345/database-1");
|
||||||
|
assertThat(dataSource.getUsername()).isEqualTo("user-1");
|
||||||
|
assertThat(dataSource.getPassword()).isEqualTo("secret-1");
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void backsOffWithLiquibaseUrlAndNoSpringJdbc() {
|
void backsOffWithLiquibaseUrlAndNoSpringJdbc() {
|
||||||
this.contextRunner.withPropertyValues("spring.liquibase.url:jdbc:hsqldb:mem:" + UUID.randomUUID())
|
this.contextRunner.withPropertyValues("spring.liquibase.url:jdbc:hsqldb:mem:" + UUID.randomUUID())
|
||||||
@ -116,6 +132,30 @@ class LiquibaseAutoConfigurationTests {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void jdbcConnectionDetailsAreUsedIfAvailable() {
|
||||||
|
this.contextRunner.withSystemProperties("shouldRun=false")
|
||||||
|
.withUserConfiguration(EmbeddedDataSourceConfiguration.class, JdbcConnectionDetailsConfiguration.class)
|
||||||
|
.run(assertLiquibase((liquibase) -> {
|
||||||
|
SimpleDriverDataSource dataSource = (SimpleDriverDataSource) liquibase.getDataSource();
|
||||||
|
assertThat(dataSource.getUrl()).isEqualTo("jdbc:postgresql://database.example.com:12345/database-1");
|
||||||
|
assertThat(dataSource.getUsername()).isEqualTo("user-1");
|
||||||
|
assertThat(dataSource.getPassword()).isEqualTo("secret-1");
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void liquibaseDataSourceIsUsedOverJdbcConnectionDetails() {
|
||||||
|
this.contextRunner
|
||||||
|
.withUserConfiguration(LiquibaseDataSourceConfiguration.class, JdbcConnectionDetailsConfiguration.class)
|
||||||
|
.run(assertLiquibase((liquibase) -> {
|
||||||
|
HikariDataSource dataSource = (HikariDataSource) liquibase.getDataSource();
|
||||||
|
assertThat(dataSource.getJdbcUrl()).startsWith("jdbc:hsqldb:mem:liquibasetest");
|
||||||
|
assertThat(dataSource.getUsername()).isEqualTo("sa");
|
||||||
|
assertThat(dataSource.getPassword()).isNull();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void changelogXml() {
|
void changelogXml() {
|
||||||
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
|
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
|
||||||
@ -509,6 +549,33 @@ class LiquibaseAutoConfigurationTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
static class JdbcConnectionDetailsConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
JdbcConnectionDetails jdbcConnectionDetails() {
|
||||||
|
return new JdbcConnectionDetails() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getJdbcUrl() {
|
||||||
|
return "jdbc:postgresql://database.example.com:12345/database-1";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return "user-1";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return "secret-1";
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static class CustomH2Driver extends org.h2.Driver {
|
static class CustomH2Driver extends org.h2.Driver {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user