mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-07-05 00:56:58 +08:00
Always define connection details beans
Closes gh-34776
This commit is contained in:
parent
466b81f13d
commit
d4980ea993
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -50,6 +50,12 @@ import org.springframework.context.annotation.Import;
|
||||
@ConditionalOnEnabledTracing
|
||||
public class ZipkinAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ZipkinConnectionDetails.class)
|
||||
PropertiesZipkinConnectionDetails zipkinConnectionDetails(ZipkinProperties properties) {
|
||||
return new PropertiesZipkinConnectionDetails(properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public BytesEncoder<Span> spanBytesEncoder() {
|
||||
|
@ -64,6 +64,25 @@ class ZipkinAutoConfigurationTests {
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(BytesEncoder.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void definesPropertiesBasedConnectionDetailsByDefault() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(PropertiesZipkinConnectionDetails.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseCustomConnectionDetailsWhenDefined() {
|
||||
this.contextRunner.withBean(ZipkinConnectionDetails.class, () -> new ZipkinConnectionDetails() {
|
||||
|
||||
@Override
|
||||
public String getSpanEndpoint() {
|
||||
return "http://localhost";
|
||||
}
|
||||
|
||||
})
|
||||
.run((context) -> assertThat(context).hasSingleBean(ZipkinConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesZipkinConnectionDetails.class));
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
private static class CustomConfiguration {
|
||||
|
||||
|
@ -25,13 +25,12 @@ import java.util.List;
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public class PropertiesRabbitConnectionDetails implements RabbitConnectionDetails {
|
||||
class PropertiesRabbitConnectionDetails implements RabbitConnectionDetails {
|
||||
|
||||
private final RabbitProperties properties;
|
||||
|
||||
public PropertiesRabbitConnectionDetails(RabbitProperties properties) {
|
||||
PropertiesRabbitConnectionDetails(RabbitProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
|
@ -82,22 +82,24 @@ public class RabbitAutoConfiguration {
|
||||
|
||||
private final RabbitProperties properties;
|
||||
|
||||
private final RabbitConnectionDetails connectionDetails;
|
||||
|
||||
protected RabbitConnectionFactoryCreator(RabbitProperties properties,
|
||||
ObjectProvider<RabbitConnectionDetails> connectionDetails) {
|
||||
this.properties = properties;
|
||||
this.connectionDetails = connectionDetails
|
||||
.getIfAvailable(() -> new PropertiesRabbitConnectionDetails(properties));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(RabbitConnectionDetails.class)
|
||||
RabbitConnectionDetails rabbitConnectionDetails() {
|
||||
return new PropertiesRabbitConnectionDetails(this.properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
RabbitConnectionFactoryBeanConfigurer rabbitConnectionFactoryBeanConfigurer(ResourceLoader resourceLoader,
|
||||
ObjectProvider<CredentialsProvider> credentialsProvider,
|
||||
RabbitConnectionDetails connectionDetails, ObjectProvider<CredentialsProvider> credentialsProvider,
|
||||
ObjectProvider<CredentialsRefreshService> credentialsRefreshService) {
|
||||
RabbitConnectionFactoryBeanConfigurer configurer = new RabbitConnectionFactoryBeanConfigurer(resourceLoader,
|
||||
this.properties, this.connectionDetails);
|
||||
this.properties, connectionDetails);
|
||||
configurer.setCredentialsProvider(credentialsProvider.getIfUnique());
|
||||
configurer.setCredentialsRefreshService(credentialsRefreshService.getIfUnique());
|
||||
return configurer;
|
||||
@ -105,10 +107,10 @@ public class RabbitAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
CachingConnectionFactoryConfigurer rabbitConnectionFactoryConfigurer(
|
||||
CachingConnectionFactoryConfigurer rabbitConnectionFactoryConfigurer(RabbitConnectionDetails connectionDetails,
|
||||
ObjectProvider<ConnectionNameStrategy> connectionNameStrategy) {
|
||||
CachingConnectionFactoryConfigurer configurer = new CachingConnectionFactoryConfigurer(this.properties,
|
||||
this.connectionDetails);
|
||||
connectionDetails);
|
||||
configurer.setConnectionNameStrategy(connectionNameStrategy.getIfUnique());
|
||||
return configurer;
|
||||
}
|
||||
|
@ -84,13 +84,14 @@ public class CassandraAutoConfiguration {
|
||||
|
||||
private final CassandraProperties properties;
|
||||
|
||||
private final CassandraConnectionDetails connectionDetails;
|
||||
|
||||
CassandraAutoConfiguration(CassandraProperties properties,
|
||||
ObjectProvider<CassandraConnectionDetails> connectionDetails) {
|
||||
CassandraAutoConfiguration(CassandraProperties properties) {
|
||||
this.properties = properties;
|
||||
this.connectionDetails = connectionDetails
|
||||
.getIfAvailable(() -> new PropertiesCassandraConnectionDetails(properties));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(CassandraConnectionDetails.class)
|
||||
PropertiesCassandraConnectionDetails cassandraConnectionDetails() {
|
||||
return new PropertiesCassandraConnectionDetails(this.properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ -104,24 +105,25 @@ public class CassandraAutoConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
@Scope("prototype")
|
||||
public CqlSessionBuilder cassandraSessionBuilder(DriverConfigLoader driverConfigLoader,
|
||||
CassandraConnectionDetails connectionDetails,
|
||||
ObjectProvider<CqlSessionBuilderCustomizer> builderCustomizers) {
|
||||
CqlSessionBuilder builder = CqlSession.builder().withConfigLoader(driverConfigLoader);
|
||||
configureAuthentication(builder);
|
||||
configureSsl(builder);
|
||||
configureAuthentication(builder, connectionDetails);
|
||||
configureSsl(builder, connectionDetails);
|
||||
builder.withKeyspace(this.properties.getKeyspaceName());
|
||||
builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
|
||||
return builder;
|
||||
}
|
||||
|
||||
private void configureAuthentication(CqlSessionBuilder builder) {
|
||||
String username = this.connectionDetails.getUsername();
|
||||
private void configureAuthentication(CqlSessionBuilder builder, CassandraConnectionDetails connectionDetails) {
|
||||
String username = connectionDetails.getUsername();
|
||||
if (username != null) {
|
||||
builder.withAuthCredentials(username, this.connectionDetails.getPassword());
|
||||
builder.withAuthCredentials(username, connectionDetails.getPassword());
|
||||
}
|
||||
}
|
||||
|
||||
private void configureSsl(CqlSessionBuilder builder) {
|
||||
if (this.connectionDetails instanceof PropertiesCassandraConnectionDetails && this.properties.isSsl()) {
|
||||
private void configureSsl(CqlSessionBuilder builder, CassandraConnectionDetails connectionDetails) {
|
||||
if (connectionDetails instanceof PropertiesCassandraConnectionDetails && this.properties.isSsl()) {
|
||||
try {
|
||||
builder.withSslContext(SSLContext.getDefault());
|
||||
}
|
||||
@ -133,18 +135,18 @@ public class CassandraAutoConfiguration {
|
||||
|
||||
@Bean(destroyMethod = "")
|
||||
@ConditionalOnMissingBean
|
||||
public DriverConfigLoader cassandraDriverConfigLoader(
|
||||
public DriverConfigLoader cassandraDriverConfigLoader(CassandraConnectionDetails connectionDetails,
|
||||
ObjectProvider<DriverConfigLoaderBuilderCustomizer> builderCustomizers) {
|
||||
ProgrammaticDriverConfigLoaderBuilder builder = new DefaultProgrammaticDriverConfigLoaderBuilder(
|
||||
() -> cassandraConfiguration(), DefaultDriverConfigLoader.DEFAULT_ROOT_PATH);
|
||||
() -> cassandraConfiguration(connectionDetails), DefaultDriverConfigLoader.DEFAULT_ROOT_PATH);
|
||||
builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private Config cassandraConfiguration() {
|
||||
private Config cassandraConfiguration(CassandraConnectionDetails connectionDetails) {
|
||||
ConfigFactory.invalidateCaches();
|
||||
Config config = ConfigFactory.defaultOverrides();
|
||||
config = config.withFallback(mapConfig());
|
||||
config = config.withFallback(mapConfig(connectionDetails));
|
||||
if (this.properties.getConfig() != null) {
|
||||
config = config.withFallback(loadConfig(this.properties.getConfig()));
|
||||
}
|
||||
@ -162,24 +164,24 @@ public class CassandraAutoConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
private Config mapConfig() {
|
||||
private Config mapConfig(CassandraConnectionDetails connectionDetails) {
|
||||
CassandraDriverOptions options = new CassandraDriverOptions();
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
map.from(this.properties.getSessionName())
|
||||
.whenHasText()
|
||||
.to((sessionName) -> options.add(DefaultDriverOption.SESSION_NAME, sessionName));
|
||||
map.from(this.connectionDetails.getUsername())
|
||||
map.from(connectionDetails.getUsername())
|
||||
.to((value) -> options.add(DefaultDriverOption.AUTH_PROVIDER_USER_NAME, value)
|
||||
.add(DefaultDriverOption.AUTH_PROVIDER_PASSWORD, this.connectionDetails.getPassword()));
|
||||
.add(DefaultDriverOption.AUTH_PROVIDER_PASSWORD, connectionDetails.getPassword()));
|
||||
map.from(this.properties::getCompression)
|
||||
.to((compression) -> options.add(DefaultDriverOption.PROTOCOL_COMPRESSION, compression));
|
||||
mapConnectionOptions(options);
|
||||
mapPoolingOptions(options);
|
||||
mapRequestOptions(options);
|
||||
mapControlConnectionOptions(options);
|
||||
map.from(mapContactPoints())
|
||||
map.from(mapContactPoints(connectionDetails))
|
||||
.to((contactPoints) -> options.add(DefaultDriverOption.CONTACT_POINTS, contactPoints));
|
||||
map.from(this.connectionDetails.getLocalDatacenter())
|
||||
map.from(connectionDetails.getLocalDatacenter())
|
||||
.whenHasText()
|
||||
.to((localDatacenter) -> options.add(DefaultDriverOption.LOAD_BALANCING_LOCAL_DATACENTER, localDatacenter));
|
||||
return options.build();
|
||||
@ -244,11 +246,8 @@ public class CassandraAutoConfiguration {
|
||||
.to((timeout) -> options.add(DefaultDriverOption.CONTROL_CONNECTION_TIMEOUT, timeout));
|
||||
}
|
||||
|
||||
private List<String> mapContactPoints() {
|
||||
return this.connectionDetails.getContactPoints()
|
||||
.stream()
|
||||
.map((node) -> node.host() + ":" + node.port())
|
||||
.toList();
|
||||
private List<String> mapContactPoints(CassandraConnectionDetails connectionDetails) {
|
||||
return connectionDetails.getContactPoints().stream().map((node) -> node.host() + ":" + node.port()).toList();
|
||||
}
|
||||
|
||||
private static class CassandraDriverOptions {
|
||||
@ -289,7 +288,7 @@ public class CassandraAutoConfiguration {
|
||||
/**
|
||||
* Adapts {@link CassandraProperties} to {@link CassandraConnectionDetails}.
|
||||
*/
|
||||
private static final class PropertiesCassandraConnectionDetails implements CassandraConnectionDetails {
|
||||
static final class PropertiesCassandraConnectionDetails implements CassandraConnectionDetails {
|
||||
|
||||
private final CassandraProperties properties;
|
||||
|
||||
|
@ -69,34 +69,37 @@ public class CouchbaseAutoConfiguration {
|
||||
|
||||
private final CouchbaseProperties properties;
|
||||
|
||||
private final CouchbaseConnectionDetails connectionDetails;
|
||||
|
||||
CouchbaseAutoConfiguration(CouchbaseProperties properties,
|
||||
ObjectProvider<CouchbaseConnectionDetails> connectionDetails) {
|
||||
this.properties = properties;
|
||||
this.connectionDetails = connectionDetails
|
||||
.getIfAvailable(() -> new PropertiesCouchbaseConnectionDetails(properties));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(CouchbaseConnectionDetails.class)
|
||||
PropertiesCouchbaseConnectionDetails couchbaseConnectionDetails() {
|
||||
return new PropertiesCouchbaseConnectionDetails(this.properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ClusterEnvironment couchbaseClusterEnvironment(
|
||||
public ClusterEnvironment couchbaseClusterEnvironment(CouchbaseConnectionDetails connectionDetails,
|
||||
ObjectProvider<ClusterEnvironmentBuilderCustomizer> customizers) {
|
||||
Builder builder = initializeEnvironmentBuilder();
|
||||
Builder builder = initializeEnvironmentBuilder(connectionDetails);
|
||||
customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Bean(destroyMethod = "disconnect")
|
||||
@ConditionalOnMissingBean
|
||||
public Cluster couchbaseCluster(ClusterEnvironment couchbaseClusterEnvironment) {
|
||||
public Cluster couchbaseCluster(ClusterEnvironment couchbaseClusterEnvironment,
|
||||
CouchbaseConnectionDetails connectionDetails) {
|
||||
ClusterOptions options = ClusterOptions
|
||||
.clusterOptions(this.connectionDetails.getUsername(), this.connectionDetails.getPassword())
|
||||
.clusterOptions(connectionDetails.getUsername(), connectionDetails.getPassword())
|
||||
.environment(couchbaseClusterEnvironment);
|
||||
return Cluster.connect(this.connectionDetails.getConnectionString(), options);
|
||||
return Cluster.connect(connectionDetails.getConnectionString(), options);
|
||||
}
|
||||
|
||||
private ClusterEnvironment.Builder initializeEnvironmentBuilder() {
|
||||
private ClusterEnvironment.Builder initializeEnvironmentBuilder(CouchbaseConnectionDetails connectionDetails) {
|
||||
ClusterEnvironment.Builder builder = ClusterEnvironment.builder();
|
||||
Timeouts timeouts = this.properties.getEnv().getTimeouts();
|
||||
builder.timeoutConfig((config) -> config.kvTimeout(timeouts.getKeyValue())
|
||||
@ -112,7 +115,7 @@ public class CouchbaseAutoConfiguration {
|
||||
builder.ioConfig((config) -> config.maxHttpConnections(io.getMaxEndpoints())
|
||||
.numKvConnections(io.getMinEndpoints())
|
||||
.idleHttpConnectionTimeout(io.getIdleHttpConnectionTimeout()));
|
||||
if ((this.connectionDetails instanceof PropertiesCouchbaseConnectionDetails)
|
||||
if ((connectionDetails instanceof PropertiesCouchbaseConnectionDetails)
|
||||
&& this.properties.getEnv().getSsl().getEnabled()) {
|
||||
builder.securityConfig((config) -> config.enableTls(true)
|
||||
.trustManagerFactory(getTrustManagerFactory(this.properties.getEnv().getSsl())));
|
||||
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,9 +21,13 @@ import com.mongodb.client.MongoClient;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoConnectionDetails;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
|
||||
import org.springframework.boot.autoconfigure.mongo.PropertiesMongoConnectionDetails;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
|
||||
@ -53,4 +57,10 @@ import org.springframework.data.mongodb.gridfs.GridFsTemplate;
|
||||
MongoDatabaseFactoryDependentConfiguration.class })
|
||||
public class MongoDataAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(MongoConnectionDetails.class)
|
||||
PropertiesMongoConnectionDetails mongoConnectionDetails(MongoProperties properties) {
|
||||
return new PropertiesMongoConnectionDetails(properties);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,12 +18,10 @@ package org.springframework.boot.autoconfigure.data.mongo;
|
||||
|
||||
import com.mongodb.client.MongoClient;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoConnectionDetails;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
|
||||
import org.springframework.boot.autoconfigure.mongo.PropertiesMongoConnectionDetails;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.mongodb.MongoDatabaseFactory;
|
||||
@ -45,11 +43,8 @@ class MongoDatabaseFactoryConfiguration {
|
||||
|
||||
@Bean
|
||||
MongoDatabaseFactorySupport<?> mongoDatabaseFactory(MongoClient mongoClient, MongoProperties properties,
|
||||
ObjectProvider<MongoConnectionDetails> connectionDetails) {
|
||||
return new SimpleMongoClientDatabaseFactory(mongoClient,
|
||||
connectionDetails.getIfAvailable(() -> new PropertiesMongoConnectionDetails(properties))
|
||||
.getConnectionString()
|
||||
.getDatabase());
|
||||
MongoConnectionDetails connectionDetails) {
|
||||
return new SimpleMongoClientDatabaseFactory(mongoClient, connectionDetails.getConnectionString().getDatabase());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,14 +20,12 @@ import com.mongodb.ClientSessionOptions;
|
||||
import com.mongodb.client.ClientSession;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoConnectionDetails;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoConnectionDetails.GridFs;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoProperties.Gridfs;
|
||||
import org.springframework.boot.autoconfigure.mongo.PropertiesMongoConnectionDetails;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
@ -76,9 +74,7 @@ class MongoDatabaseFactoryDependentConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(GridFsOperations.class)
|
||||
GridFsTemplate gridFsTemplate(MongoProperties properties, MongoDatabaseFactory factory, MongoTemplate mongoTemplate,
|
||||
ObjectProvider<MongoConnectionDetails> connectionDetailsProvider) {
|
||||
MongoConnectionDetails connectionDetails = connectionDetailsProvider
|
||||
.getIfAvailable(() -> new PropertiesMongoConnectionDetails(properties));
|
||||
MongoConnectionDetails connectionDetails) {
|
||||
return new GridFsTemplate(new GridFsMongoDatabaseFactory(factory, connectionDetails),
|
||||
mongoTemplate.getConverter(),
|
||||
(connectionDetails.getGridFs() != null) ? connectionDetails.getGridFs().getBucket() : null);
|
||||
|
@ -26,7 +26,6 @@ import org.bson.codecs.Codec;
|
||||
import org.bson.codecs.configuration.CodecRegistry;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
@ -36,7 +35,6 @@ import org.springframework.boot.autoconfigure.mongo.MongoConnectionDetails;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoConnectionDetails.GridFs;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.mongo.PropertiesMongoConnectionDetails;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
@ -80,10 +78,8 @@ public class MongoReactiveDataAutoConfiguration {
|
||||
|
||||
private final MongoConnectionDetails connectionDetails;
|
||||
|
||||
MongoReactiveDataAutoConfiguration(MongoProperties properties,
|
||||
ObjectProvider<MongoConnectionDetails> connectionDetails) {
|
||||
this.connectionDetails = connectionDetails
|
||||
.getIfAvailable(() -> new PropertiesMongoConnectionDetails(properties));
|
||||
MongoReactiveDataAutoConfiguration(MongoConnectionDetails connectionDetails) {
|
||||
this.connectionDetails = connectionDetails;
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -55,10 +55,9 @@ class JedisConnectionConfiguration extends RedisConnectionConfiguration {
|
||||
JedisConnectionConfiguration(RedisProperties properties,
|
||||
ObjectProvider<RedisStandaloneConfiguration> standaloneConfigurationProvider,
|
||||
ObjectProvider<RedisSentinelConfiguration> sentinelConfiguration,
|
||||
ObjectProvider<RedisClusterConfiguration> clusterConfiguration,
|
||||
ObjectProvider<RedisConnectionDetails> connectionDetailsProvider) {
|
||||
super(properties, standaloneConfigurationProvider, sentinelConfiguration, clusterConfiguration,
|
||||
connectionDetailsProvider);
|
||||
ObjectProvider<RedisClusterConfiguration> clusterConfiguration, RedisConnectionDetails connectionDetails) {
|
||||
super(properties, connectionDetails, standaloneConfigurationProvider, sentinelConfiguration,
|
||||
clusterConfiguration);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -64,9 +64,9 @@ class LettuceConnectionConfiguration extends RedisConnectionConfiguration {
|
||||
ObjectProvider<RedisStandaloneConfiguration> standaloneConfigurationProvider,
|
||||
ObjectProvider<RedisSentinelConfiguration> sentinelConfigurationProvider,
|
||||
ObjectProvider<RedisClusterConfiguration> clusterConfigurationProvider,
|
||||
ObjectProvider<RedisConnectionDetails> connectionDetailsProvider) {
|
||||
super(properties, standaloneConfigurationProvider, sentinelConfigurationProvider, clusterConfigurationProvider,
|
||||
connectionDetailsProvider);
|
||||
RedisConnectionDetails connectionDetails) {
|
||||
super(properties, connectionDetails, standaloneConfigurationProvider, sentinelConfigurationProvider,
|
||||
clusterConfigurationProvider);
|
||||
}
|
||||
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -49,6 +49,12 @@ import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
|
||||
public class RedisAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(RedisConnectionDetails.class)
|
||||
PropertiesRedisConnectionDetails redisConnectionDetails(RedisProperties properties) {
|
||||
return new PropertiesRedisConnectionDetails(properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(name = "redisTemplate")
|
||||
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
|
||||
|
@ -60,17 +60,15 @@ abstract class RedisConnectionConfiguration {
|
||||
|
||||
private final RedisConnectionDetails connectionDetails;
|
||||
|
||||
protected RedisConnectionConfiguration(RedisProperties properties,
|
||||
protected RedisConnectionConfiguration(RedisProperties properties, RedisConnectionDetails connectionDetails,
|
||||
ObjectProvider<RedisStandaloneConfiguration> standaloneConfigurationProvider,
|
||||
ObjectProvider<RedisSentinelConfiguration> sentinelConfigurationProvider,
|
||||
ObjectProvider<RedisClusterConfiguration> clusterConfigurationProvider,
|
||||
ObjectProvider<RedisConnectionDetails> connectionDetailsProvider) {
|
||||
ObjectProvider<RedisClusterConfiguration> clusterConfigurationProvider) {
|
||||
this.properties = properties;
|
||||
this.standaloneConfiguration = standaloneConfigurationProvider.getIfAvailable();
|
||||
this.sentinelConfiguration = sentinelConfigurationProvider.getIfAvailable();
|
||||
this.clusterConfiguration = clusterConfigurationProvider.getIfAvailable();
|
||||
this.connectionDetails = connectionDetailsProvider
|
||||
.getIfAvailable(() -> new PropertiesRedisConnectionDetails(properties));
|
||||
this.connectionDetails = connectionDetails;
|
||||
}
|
||||
|
||||
protected final RedisStandaloneConfiguration getStandaloneConfig() {
|
||||
|
@ -62,24 +62,27 @@ class ElasticsearchRestClientConfigurations {
|
||||
|
||||
private final ElasticsearchProperties properties;
|
||||
|
||||
private final ElasticsearchConnectionDetails connectionDetails;
|
||||
|
||||
RestClientBuilderConfiguration(ElasticsearchProperties properties,
|
||||
ObjectProvider<ElasticsearchConnectionDetails> connectionDetails) {
|
||||
this.properties = properties;
|
||||
this.connectionDetails = connectionDetails
|
||||
.getIfAvailable(() -> new PropertiesElasticsearchConnectionDetails(properties));
|
||||
}
|
||||
|
||||
@Bean
|
||||
RestClientBuilderCustomizer defaultRestClientBuilderCustomizer() {
|
||||
return new DefaultRestClientBuilderCustomizer(this.properties, this.connectionDetails);
|
||||
@ConditionalOnMissingBean(ElasticsearchConnectionDetails.class)
|
||||
PropertiesElasticsearchConnectionDetails elasticsearchConnectionDetails() {
|
||||
return new PropertiesElasticsearchConnectionDetails(this.properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
RestClientBuilder elasticsearchRestClientBuilder(
|
||||
RestClientBuilderCustomizer defaultRestClientBuilderCustomizer(
|
||||
ElasticsearchConnectionDetails connectionDetails) {
|
||||
return new DefaultRestClientBuilderCustomizer(this.properties, connectionDetails);
|
||||
}
|
||||
|
||||
@Bean
|
||||
RestClientBuilder elasticsearchRestClientBuilder(ElasticsearchConnectionDetails connectionDetails,
|
||||
ObjectProvider<RestClientBuilderCustomizer> builderCustomizers) {
|
||||
RestClientBuilder builder = RestClient.builder(this.connectionDetails.getNodes()
|
||||
RestClientBuilder builder = RestClient.builder(connectionDetails.getNodes()
|
||||
.stream()
|
||||
.map((node) -> new HttpHost(node.hostname(), node.port(), node.protocol().getScheme()))
|
||||
.toArray(HttpHost[]::new));
|
||||
@ -91,7 +94,7 @@ class ElasticsearchRestClientConfigurations {
|
||||
builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(requestConfigBuilder));
|
||||
return requestConfigBuilder;
|
||||
});
|
||||
String pathPrefix = this.connectionDetails.getPathPrefix();
|
||||
String pathPrefix = connectionDetails.getPathPrefix();
|
||||
if (pathPrefix != null) {
|
||||
builder.setPathPrefix(pathPrefix);
|
||||
}
|
||||
@ -212,7 +215,7 @@ class ElasticsearchRestClientConfigurations {
|
||||
/**
|
||||
* Adapts {@link ElasticsearchProperties} to {@link ElasticsearchConnectionDetails}.
|
||||
*/
|
||||
private static class PropertiesElasticsearchConnectionDetails implements ElasticsearchConnectionDetails {
|
||||
static class PropertiesElasticsearchConnectionDetails implements ElasticsearchConnectionDetails {
|
||||
|
||||
private final ElasticsearchProperties properties;
|
||||
|
||||
|
@ -24,6 +24,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
@ -121,27 +122,31 @@ public class FlywayAutoConfiguration {
|
||||
return new ResourceProviderCustomizer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(FlywayConnectionDetails.class)
|
||||
PropertiesFlywayConnectionDetails flywayConnectionDetails(FlywayProperties properties,
|
||||
ObjectProvider<JdbcConnectionDetails> jdbcConnectionDetails) {
|
||||
return new PropertiesFlywayConnectionDetails(properties, jdbcConnectionDetails.getIfAvailable());
|
||||
}
|
||||
|
||||
@Deprecated(since = "3.0.0", forRemoval = true)
|
||||
public Flyway flyway(FlywayProperties properties, ResourceLoader resourceLoader,
|
||||
ObjectProvider<DataSource> dataSource, ObjectProvider<DataSource> flywayDataSource,
|
||||
ObjectProvider<FlywayConfigurationCustomizer> fluentConfigurationCustomizers,
|
||||
ObjectProvider<JavaMigration> javaMigrations, ObjectProvider<Callback> callbacks) {
|
||||
return flyway(properties, resourceLoader, dataSource, flywayDataSource, fluentConfigurationCustomizers,
|
||||
javaMigrations, callbacks, new ResourceProviderCustomizer(), null);
|
||||
return flyway(properties, new PropertiesFlywayConnectionDetails(properties, null), resourceLoader,
|
||||
dataSource, flywayDataSource, fluentConfigurationCustomizers, javaMigrations, callbacks,
|
||||
new ResourceProviderCustomizer());
|
||||
}
|
||||
|
||||
@Bean
|
||||
Flyway flyway(FlywayProperties properties, ResourceLoader resourceLoader, ObjectProvider<DataSource> dataSource,
|
||||
Flyway flyway(FlywayProperties properties, FlywayConnectionDetails connectionDetails,
|
||||
ResourceLoader resourceLoader, ObjectProvider<DataSource> dataSource,
|
||||
@FlywayDataSource ObjectProvider<DataSource> flywayDataSource,
|
||||
ObjectProvider<FlywayConfigurationCustomizer> fluentConfigurationCustomizers,
|
||||
ObjectProvider<JavaMigration> javaMigrations, ObjectProvider<Callback> callbacks,
|
||||
ResourceProviderCustomizer resourceProviderCustomizer,
|
||||
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||
ResourceProviderCustomizer resourceProviderCustomizer) {
|
||||
FluentConfiguration configuration = new FluentConfiguration(resourceLoader.getClassLoader());
|
||||
JdbcConnectionDetails connectionDetails = (connectionDetailsProvider != null)
|
||||
? connectionDetailsProvider.getIfAvailable() : null;
|
||||
connectionDetails = (connectionDetails != null) ? connectionDetails
|
||||
: new FlywayPropertiesJdbcConnectionDetails(properties);
|
||||
configureDataSource(configuration, flywayDataSource.getIfAvailable(), dataSource.getIfUnique(),
|
||||
connectionDetails);
|
||||
configureProperties(configuration, properties);
|
||||
@ -153,13 +158,13 @@ public class FlywayAutoConfiguration {
|
||||
}
|
||||
|
||||
private void configureDataSource(FluentConfiguration configuration, DataSource flywayDataSource,
|
||||
DataSource dataSource, JdbcConnectionDetails connectionDetails) {
|
||||
DataSource dataSource, FlywayConnectionDetails connectionDetails) {
|
||||
DataSource migrationDataSource = getMigrationDataSource(flywayDataSource, dataSource, connectionDetails);
|
||||
configuration.dataSource(migrationDataSource);
|
||||
}
|
||||
|
||||
private DataSource getMigrationDataSource(DataSource flywayDataSource, DataSource dataSource,
|
||||
JdbcConnectionDetails connectionDetails) {
|
||||
FlywayConnectionDetails connectionDetails) {
|
||||
if (flywayDataSource != null) {
|
||||
return flywayDataSource;
|
||||
}
|
||||
@ -181,7 +186,7 @@ public class FlywayAutoConfiguration {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
private void applyConnectionDetails(JdbcConnectionDetails connectionDetails, DataSourceBuilder<?> builder) {
|
||||
private void applyConnectionDetails(FlywayConnectionDetails connectionDetails, DataSourceBuilder<?> builder) {
|
||||
builder.username(connectionDetails.getUsername());
|
||||
builder.password(connectionDetails.getPassword());
|
||||
String driverClassName = connectionDetails.getDriverClassName();
|
||||
@ -406,34 +411,46 @@ public class FlywayAutoConfiguration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapts {@link FlywayProperties} to {@link JdbcConnectionDetails}.
|
||||
* Adapts {@link FlywayProperties} to {@link FlywayConnectionDetails}, using
|
||||
* {@link JdbcConnectionDetails} as a fallback when Flyway-specific properties have
|
||||
* not be configured.
|
||||
*/
|
||||
private static final class FlywayPropertiesJdbcConnectionDetails implements JdbcConnectionDetails {
|
||||
static final class PropertiesFlywayConnectionDetails implements FlywayConnectionDetails {
|
||||
|
||||
private final JdbcConnectionDetails fallback;
|
||||
|
||||
private final FlywayProperties properties;
|
||||
|
||||
private FlywayPropertiesJdbcConnectionDetails(FlywayProperties properties) {
|
||||
PropertiesFlywayConnectionDetails(FlywayProperties properties, JdbcConnectionDetails fallback) {
|
||||
this.fallback = fallback;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.properties.getUser();
|
||||
return get(this.properties.getUser(), JdbcConnectionDetails::getUsername);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return this.properties.getPassword();
|
||||
return get(this.properties.getPassword(), JdbcConnectionDetails::getPassword);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJdbcUrl() {
|
||||
return this.properties.getUrl();
|
||||
return get(this.properties.getUrl(), JdbcConnectionDetails::getJdbcUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDriverClassName() {
|
||||
return this.properties.getDriverClassName();
|
||||
return get(this.properties.getDriverClassName(), JdbcConnectionDetails::getDriverClassName);
|
||||
}
|
||||
|
||||
private String get(String primary, Function<JdbcConnectionDetails, String> fallbackProperty) {
|
||||
if (primary != null) {
|
||||
return primary;
|
||||
}
|
||||
return (this.fallback != null) ? fallbackProperty.apply(this.fallback) : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.flyway;
|
||||
|
||||
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
|
||||
import org.springframework.boot.jdbc.DatabaseDriver;
|
||||
|
||||
/**
|
||||
* Details required for Flyway to establish a connection to an SQL service using JDBC.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public interface FlywayConnectionDetails extends ConnectionDetails {
|
||||
|
||||
/**
|
||||
* Username 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();
|
||||
}
|
||||
|
||||
}
|
@ -30,6 +30,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration.InfluxDBCondition;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
@ -48,17 +49,21 @@ import org.springframework.context.annotation.Conditional;
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@ConditionalOnClass(InfluxDB.class)
|
||||
@Conditional(InfluxDBCondition.class)
|
||||
@EnableConfigurationProperties(InfluxDbProperties.class)
|
||||
public class InfluxDbAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(InfluxDbConnectionDetails.class)
|
||||
PropertiesInfluxDbConnectionDetails influxDbConnectionDetails(InfluxDbProperties properties) {
|
||||
return new PropertiesInfluxDbConnectionDetails(properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@Conditional(InfluxDBCondition.class)
|
||||
public InfluxDB influxDb(InfluxDbProperties properties, ObjectProvider<InfluxDbOkHttpClientBuilderProvider> builder,
|
||||
ObjectProvider<InfluxDbCustomizer> customizers,
|
||||
ObjectProvider<InfluxDbConnectionDetails> connectionDetailsProvider) {
|
||||
InfluxDbConnectionDetails connectionDetails = connectionDetailsProvider
|
||||
.getIfAvailable(() -> new PropertiesInfluxDbConnectionDetails(properties));
|
||||
public InfluxDB influxDb(InfluxDbConnectionDetails connectionDetails,
|
||||
ObjectProvider<InfluxDbOkHttpClientBuilderProvider> builder,
|
||||
ObjectProvider<InfluxDbCustomizer> customizers) {
|
||||
InfluxDB influxDb = new InfluxDBImpl(connectionDetails.getUrl().toString(), connectionDetails.getUsername(),
|
||||
connectionDetails.getPassword(), determineBuilder(builder.getIfAvailable()));
|
||||
customizers.orderedStream().forEach((customizer) -> customizer.customize(influxDb));
|
||||
|
@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -33,6 +33,7 @@ import org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConf
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.jdbc.DataSourceBuilder;
|
||||
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
@ -75,6 +76,12 @@ public class DataSourceAutoConfiguration {
|
||||
DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class })
|
||||
protected static class PooledDataSourceConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(JdbcConnectionDetails.class)
|
||||
PropertiesJdbcConnectionDetails jdbcConnectionDetails(DataSourceProperties properties) {
|
||||
return new PropertiesJdbcConnectionDetails(properties);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,7 +25,6 @@ import oracle.jdbc.OracleConnection;
|
||||
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.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
@ -48,20 +47,15 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
abstract class DataSourceConfiguration {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T createDataSource(DataSourceProperties properties, Class<? extends DataSource> type) {
|
||||
return (T) properties.initializeDataSourceBuilder().type(type).build();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T createDataSource(JdbcConnectionDetails connectionDetails, Class<? extends DataSource> type,
|
||||
ClassLoader classLoader) {
|
||||
return (T) DataSourceBuilder.create(classLoader)
|
||||
.type(type)
|
||||
.driverClassName(connectionDetails.getDriverClassName())
|
||||
.url(connectionDetails.getJdbcUrl())
|
||||
.username(connectionDetails.getUsername())
|
||||
.password(connectionDetails.getPassword())
|
||||
.driverClassName(connectionDetails.getDriverClassName())
|
||||
.type(type)
|
||||
.build();
|
||||
}
|
||||
|
||||
@ -76,7 +70,7 @@ abstract class DataSourceConfiguration {
|
||||
static class Tomcat {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(JdbcConnectionDetails.class)
|
||||
@ConditionalOnMissingBean(PropertiesJdbcConnectionDetails.class)
|
||||
static TomcatJdbcConnectionDetailsBeanPostProcessor tomcatJdbcConnectionDetailsBeanPostProcessor(
|
||||
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||
return new TomcatJdbcConnectionDetailsBeanPostProcessor(connectionDetailsProvider);
|
||||
@ -85,15 +79,12 @@ abstract class DataSourceConfiguration {
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "spring.datasource.tomcat")
|
||||
org.apache.tomcat.jdbc.pool.DataSource dataSource(DataSourceProperties properties,
|
||||
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||
JdbcConnectionDetails connectionDetails = connectionDetailsProvider.getIfAvailable();
|
||||
JdbcConnectionDetails connectionDetails) {
|
||||
Class<? extends DataSource> dataSourceType = org.apache.tomcat.jdbc.pool.DataSource.class;
|
||||
org.apache.tomcat.jdbc.pool.DataSource dataSource = (connectionDetails != null)
|
||||
? createDataSource(connectionDetails, dataSourceType, properties.getClassLoader())
|
||||
: createDataSource(properties, dataSourceType);
|
||||
org.apache.tomcat.jdbc.pool.DataSource dataSource = createDataSource(connectionDetails, dataSourceType,
|
||||
properties.getClassLoader());
|
||||
String validationQuery;
|
||||
String url = (connectionDetails != null) ? connectionDetails.getJdbcUrl() : properties.determineUrl();
|
||||
DatabaseDriver databaseDriver = DatabaseDriver.fromJdbcUrl(url);
|
||||
DatabaseDriver databaseDriver = DatabaseDriver.fromJdbcUrl(connectionDetails.getJdbcUrl());
|
||||
validationQuery = databaseDriver.getValidationQuery();
|
||||
if (validationQuery != null) {
|
||||
dataSource.setTestOnBorrow(true);
|
||||
@ -115,7 +106,6 @@ abstract class DataSourceConfiguration {
|
||||
static class Hikari {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(JdbcConnectionDetails.class)
|
||||
static HikariJdbcConnectionDetailsBeanPostProcessor jdbcConnectionDetailsHikariBeanPostProcessor(
|
||||
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||
return new HikariJdbcConnectionDetailsBeanPostProcessor(connectionDetailsProvider);
|
||||
@ -123,12 +113,9 @@ abstract class DataSourceConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "spring.datasource.hikari")
|
||||
HikariDataSource dataSource(DataSourceProperties properties,
|
||||
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||
JdbcConnectionDetails connectionDetails = connectionDetailsProvider.getIfAvailable();
|
||||
HikariDataSource dataSource = (connectionDetails != null)
|
||||
? createDataSource(connectionDetails, HikariDataSource.class, properties.getClassLoader())
|
||||
: createDataSource(properties, HikariDataSource.class);
|
||||
HikariDataSource dataSource(DataSourceProperties properties, JdbcConnectionDetails connectionDetails) {
|
||||
HikariDataSource dataSource = createDataSource(connectionDetails, HikariDataSource.class,
|
||||
properties.getClassLoader());
|
||||
if (StringUtils.hasText(properties.getName())) {
|
||||
dataSource.setPoolName(properties.getName());
|
||||
}
|
||||
@ -148,7 +135,6 @@ abstract class DataSourceConfiguration {
|
||||
static class Dbcp2 {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(JdbcConnectionDetails.class)
|
||||
static Dbcp2JdbcConnectionDetailsBeanPostProcessor dbcp2JdbcConnectionDetailsBeanPostProcessor(
|
||||
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||
return new Dbcp2JdbcConnectionDetailsBeanPostProcessor(connectionDetailsProvider);
|
||||
@ -157,12 +143,9 @@ abstract class DataSourceConfiguration {
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "spring.datasource.dbcp2")
|
||||
org.apache.commons.dbcp2.BasicDataSource dataSource(DataSourceProperties properties,
|
||||
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||
JdbcConnectionDetails connectionDetails = connectionDetailsProvider.getIfAvailable();
|
||||
JdbcConnectionDetails connectionDetails) {
|
||||
Class<? extends DataSource> dataSourceType = org.apache.commons.dbcp2.BasicDataSource.class;
|
||||
return (connectionDetails != null)
|
||||
? createDataSource(connectionDetails, dataSourceType, properties.getClassLoader())
|
||||
: createDataSource(properties, dataSourceType);
|
||||
return createDataSource(connectionDetails, dataSourceType, properties.getClassLoader());
|
||||
}
|
||||
|
||||
}
|
||||
@ -178,7 +161,6 @@ abstract class DataSourceConfiguration {
|
||||
static class OracleUcp {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(JdbcConnectionDetails.class)
|
||||
static OracleUcpJdbcConnectionDetailsBeanPostProcessor oracleUcpJdbcConnectionDetailsBeanPostProcessor(
|
||||
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||
return new OracleUcpJdbcConnectionDetailsBeanPostProcessor(connectionDetailsProvider);
|
||||
@ -186,12 +168,10 @@ abstract class DataSourceConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "spring.datasource.oracleucp")
|
||||
PoolDataSourceImpl dataSource(DataSourceProperties properties,
|
||||
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) throws SQLException {
|
||||
JdbcConnectionDetails connectionDetails = connectionDetailsProvider.getIfAvailable();
|
||||
PoolDataSourceImpl dataSource = (connectionDetails != null)
|
||||
? createDataSource(connectionDetails, PoolDataSourceImpl.class, properties.getClassLoader())
|
||||
: createDataSource(properties, PoolDataSourceImpl.class);
|
||||
PoolDataSourceImpl dataSource(DataSourceProperties properties, JdbcConnectionDetails connectionDetails)
|
||||
throws SQLException {
|
||||
PoolDataSourceImpl dataSource = createDataSource(connectionDetails, PoolDataSourceImpl.class,
|
||||
properties.getClassLoader());
|
||||
dataSource.setValidateConnectionOnBorrow(true);
|
||||
if (StringUtils.hasText(properties.getName())) {
|
||||
dataSource.setConnectionPoolName(properties.getName());
|
||||
@ -210,13 +190,8 @@ abstract class DataSourceConfiguration {
|
||||
static class Generic {
|
||||
|
||||
@Bean
|
||||
DataSource dataSource(DataSourceProperties properties,
|
||||
ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
|
||||
JdbcConnectionDetails connectionDetails = connectionDetailsProvider.getIfAvailable();
|
||||
if (connectionDetails != null) {
|
||||
return createDataSource(connectionDetails, properties.getType(), properties.getClassLoader());
|
||||
}
|
||||
return properties.initializeDataSourceBuilder().build();
|
||||
DataSource dataSource(DataSourceProperties properties, JdbcConnectionDetails connectionDetails) {
|
||||
return createDataSource(connectionDetails, properties.getType(), properties.getClassLoader());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ import org.springframework.boot.jdbc.DatabaseDriver;
|
||||
public interface JdbcConnectionDetails extends ConnectionDetails {
|
||||
|
||||
/**
|
||||
* Hostname for the database.
|
||||
* Username for the database.
|
||||
* @return the username for the database
|
||||
*/
|
||||
String getUsername();
|
||||
|
@ -24,7 +24,10 @@ 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}.
|
||||
* {@link JdbcConnectionDetails}. Property-based connection details
|
||||
* ({@link PropertiesJdbcConnectionDetails} are ignored as the expectation is that they
|
||||
* will have already been applied by configuration property binding. Acts on beans named
|
||||
* 'dataSource' of type {@code T}.
|
||||
*
|
||||
* @param <T> type of the datasource
|
||||
* @author Moritz Halbritter
|
||||
@ -48,7 +51,9 @@ abstract class JdbcConnectionDetailsBeanPostProcessor<T> implements BeanPostProc
|
||||
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);
|
||||
if (!(connectionDetails instanceof PropertiesJdbcConnectionDetails)) {
|
||||
return processDataSource((T) bean, connectionDetails);
|
||||
}
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Adapts {@link DataSourceProperties} to {@link JdbcConnectionDetails}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
final 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.determineDriverClassName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getXaDataSourceClassName() {
|
||||
return (this.properties.getXa().getDataSourceClassName() != null)
|
||||
? this.properties.getXa().getDataSourceClassName()
|
||||
: JdbcConnectionDetails.super.getXaDataSourceClassName();
|
||||
}
|
||||
|
||||
}
|
@ -66,12 +66,17 @@ public class XADataSourceAutoConfiguration implements BeanClassLoaderAware {
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(JdbcConnectionDetails.class)
|
||||
PropertiesJdbcConnectionDetails jdbcConnectionDetails(DataSourceProperties properties) {
|
||||
return new PropertiesJdbcConnectionDetails(properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource(XADataSourceWrapper wrapper, DataSourceProperties properties,
|
||||
ObjectProvider<JdbcConnectionDetails> connectionDetails, ObjectProvider<XADataSource> xaDataSource)
|
||||
throws Exception {
|
||||
return wrapper.wrapDataSource(xaDataSource.getIfAvailable(() -> createXaDataSource(properties,
|
||||
connectionDetails.getIfAvailable(() -> new PropertiesJdbcConnectionDetails(properties)))));
|
||||
JdbcConnectionDetails connectionDetails, ObjectProvider<XADataSource> xaDataSource) throws Exception {
|
||||
return wrapper
|
||||
.wrapDataSource(xaDataSource.getIfAvailable(() -> createXaDataSource(properties, connectionDetails)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -122,45 +127,4 @@ public class XADataSourceAutoConfiguration implements BeanClassLoaderAware {
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -76,12 +76,14 @@ public class KafkaAutoConfiguration {
|
||||
|
||||
private final KafkaProperties properties;
|
||||
|
||||
private final KafkaConnectionDetails connectionDetails;
|
||||
|
||||
KafkaAutoConfiguration(KafkaProperties properties, ObjectProvider<KafkaConnectionDetails> connectionDetails) {
|
||||
KafkaAutoConfiguration(KafkaProperties properties) {
|
||||
this.properties = properties;
|
||||
this.connectionDetails = connectionDetails
|
||||
.getIfAvailable(() -> new PropertiesKafkaConnectionDetails(properties));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(KafkaConnectionDetails.class)
|
||||
PropertiesKafkaConnectionDetails kafkaConnectionDetails(KafkaProperties properties) {
|
||||
return new PropertiesKafkaConnectionDetails(properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ -106,10 +108,10 @@ public class KafkaAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ConsumerFactory.class)
|
||||
public DefaultKafkaConsumerFactory<?, ?> kafkaConsumerFactory(
|
||||
public DefaultKafkaConsumerFactory<?, ?> kafkaConsumerFactory(KafkaConnectionDetails connectionDetails,
|
||||
ObjectProvider<DefaultKafkaConsumerFactoryCustomizer> customizers) {
|
||||
Map<String, Object> properties = this.properties.buildConsumerProperties();
|
||||
applyKafkaConnectionDetailsForConsumer(properties);
|
||||
applyKafkaConnectionDetailsForConsumer(properties, connectionDetails);
|
||||
DefaultKafkaConsumerFactory<Object, Object> factory = new DefaultKafkaConsumerFactory<>(properties);
|
||||
customizers.orderedStream().forEach((customizer) -> customizer.customize(factory));
|
||||
return factory;
|
||||
@ -117,10 +119,10 @@ public class KafkaAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ProducerFactory.class)
|
||||
public DefaultKafkaProducerFactory<?, ?> kafkaProducerFactory(
|
||||
public DefaultKafkaProducerFactory<?, ?> kafkaProducerFactory(KafkaConnectionDetails connectionDetails,
|
||||
ObjectProvider<DefaultKafkaProducerFactoryCustomizer> customizers) {
|
||||
Map<String, Object> properties = this.properties.buildProducerProperties();
|
||||
applyKafkaConnectionDetailsForProducer(properties);
|
||||
applyKafkaConnectionDetailsForProducer(properties, connectionDetails);
|
||||
DefaultKafkaProducerFactory<?, ?> factory = new DefaultKafkaProducerFactory<>(properties);
|
||||
String transactionIdPrefix = this.properties.getProducer().getTransactionIdPrefix();
|
||||
if (transactionIdPrefix != null) {
|
||||
@ -155,9 +157,9 @@ public class KafkaAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public KafkaAdmin kafkaAdmin() {
|
||||
public KafkaAdmin kafkaAdmin(KafkaConnectionDetails connectionDetails) {
|
||||
Map<String, Object> properties = this.properties.buildAdminProperties();
|
||||
applyKafkaConnectionDetailsForAdmin(properties);
|
||||
applyKafkaConnectionDetailsForAdmin(properties, connectionDetails);
|
||||
KafkaAdmin kafkaAdmin = new KafkaAdmin(properties);
|
||||
KafkaProperties.Admin admin = this.properties.getAdmin();
|
||||
if (admin.getCloseTimeout() != null) {
|
||||
@ -186,26 +188,29 @@ public class KafkaAutoConfiguration {
|
||||
return builder.create(kafkaTemplate);
|
||||
}
|
||||
|
||||
private void applyKafkaConnectionDetailsForConsumer(Map<String, Object> properties) {
|
||||
private void applyKafkaConnectionDetailsForConsumer(Map<String, Object> properties,
|
||||
KafkaConnectionDetails connectionDetails) {
|
||||
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,
|
||||
nodesToStringList(this.connectionDetails.getConsumerBootstrapNodes()));
|
||||
if (!(this.connectionDetails instanceof PropertiesKafkaConnectionDetails)) {
|
||||
nodesToStringList(connectionDetails.getConsumerBootstrapNodes()));
|
||||
if (!(connectionDetails instanceof PropertiesKafkaConnectionDetails)) {
|
||||
properties.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "PLAINTEXT");
|
||||
}
|
||||
}
|
||||
|
||||
private void applyKafkaConnectionDetailsForProducer(Map<String, Object> properties) {
|
||||
private void applyKafkaConnectionDetailsForProducer(Map<String, Object> properties,
|
||||
KafkaConnectionDetails connectionDetails) {
|
||||
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,
|
||||
nodesToStringList(this.connectionDetails.getProducerBootstrapNodes()));
|
||||
if (!(this.connectionDetails instanceof PropertiesKafkaConnectionDetails)) {
|
||||
nodesToStringList(connectionDetails.getProducerBootstrapNodes()));
|
||||
if (!(connectionDetails instanceof PropertiesKafkaConnectionDetails)) {
|
||||
properties.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "PLAINTEXT");
|
||||
}
|
||||
}
|
||||
|
||||
private void applyKafkaConnectionDetailsForAdmin(Map<String, Object> properties) {
|
||||
private void applyKafkaConnectionDetailsForAdmin(Map<String, Object> properties,
|
||||
KafkaConnectionDetails connectionDetails) {
|
||||
properties.put(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG,
|
||||
nodesToStringList(this.connectionDetails.getAdminBootstrapNodes()));
|
||||
if (!(this.connectionDetails instanceof PropertiesKafkaConnectionDetails)) {
|
||||
nodesToStringList(connectionDetails.getAdminBootstrapNodes()));
|
||||
if (!(connectionDetails instanceof PropertiesKafkaConnectionDetails)) {
|
||||
properties.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "PLAINTEXT");
|
||||
}
|
||||
}
|
||||
|
@ -63,11 +63,9 @@ class KafkaStreamsAnnotationDrivenConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
@Bean(KafkaStreamsDefaultConfiguration.DEFAULT_STREAMS_CONFIG_BEAN_NAME)
|
||||
KafkaStreamsConfiguration defaultKafkaStreamsConfig(Environment environment,
|
||||
ObjectProvider<KafkaConnectionDetails> connectionDetailsProvider) {
|
||||
KafkaConnectionDetails connectionDetails = connectionDetailsProvider
|
||||
.getIfAvailable(() -> new PropertiesKafkaConnectionDetails(this.properties));
|
||||
KafkaConnectionDetails connectionDetails) {
|
||||
Map<String, Object> properties = this.properties.buildStreamsProperties();
|
||||
applyKafkaConnectionDetailsForStreams(connectionDetails, properties);
|
||||
applyKafkaConnectionDetailsForStreams(properties, connectionDetails);
|
||||
if (this.properties.getStreams().getApplicationId() == null) {
|
||||
String applicationName = environment.getProperty("spring.application.name");
|
||||
if (applicationName == null) {
|
||||
@ -87,8 +85,8 @@ class KafkaStreamsAnnotationDrivenConfiguration {
|
||||
return new KafkaStreamsFactoryBeanConfigurer(this.properties, factoryBean);
|
||||
}
|
||||
|
||||
private void applyKafkaConnectionDetailsForStreams(KafkaConnectionDetails connectionDetails,
|
||||
Map<String, Object> properties) {
|
||||
private void applyKafkaConnectionDetailsForStreams(Map<String, Object> properties,
|
||||
KafkaConnectionDetails connectionDetails) {
|
||||
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,
|
||||
nodesToStringList(connectionDetails.getStreamsBootstrapNodes()));
|
||||
if (!(connectionDetails instanceof PropertiesKafkaConnectionDetails)) {
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.liquibase;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import liquibase.change.DatabaseChange;
|
||||
@ -31,6 +33,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.flyway.FlywayConnectionDetails;
|
||||
import org.springframework.boot.autoconfigure.flyway.FlywayProperties;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
|
||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration.LiquibaseAutoConfigurationRuntimeHints;
|
||||
@ -85,13 +89,19 @@ public class LiquibaseAutoConfiguration {
|
||||
@EnableConfigurationProperties(LiquibaseProperties.class)
|
||||
public static class LiquibaseConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(LiquibaseConnectionDetails.class)
|
||||
PropertiesLiquibaseConnectionDetails liquibaseConnectionDetails(LiquibaseProperties properties,
|
||||
ObjectProvider<JdbcConnectionDetails> jdbcConnectionDetails) {
|
||||
return new PropertiesLiquibaseConnectionDetails(properties, jdbcConnectionDetails.getIfAvailable());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SpringLiquibase liquibase(ObjectProvider<DataSource> dataSource,
|
||||
@LiquibaseDataSource ObjectProvider<DataSource> liquibaseDataSource, LiquibaseProperties properties,
|
||||
ObjectProvider<JdbcConnectionDetails> connectionDetails) {
|
||||
LiquibaseConnectionDetails connectionDetails) {
|
||||
SpringLiquibase liquibase = createSpringLiquibase(liquibaseDataSource.getIfAvailable(),
|
||||
dataSource.getIfUnique(),
|
||||
connectionDetails.getIfAvailable(() -> new LiquibasePropertiesJdbcConnectionDetails(properties)));
|
||||
dataSource.getIfUnique(), connectionDetails);
|
||||
liquibase.setChangeLog(properties.getChangeLog());
|
||||
liquibase.setClearCheckSums(properties.isClearChecksums());
|
||||
liquibase.setContexts(properties.getContexts());
|
||||
@ -111,7 +121,7 @@ public class LiquibaseAutoConfiguration {
|
||||
}
|
||||
|
||||
private SpringLiquibase createSpringLiquibase(DataSource liquibaseDataSource, DataSource dataSource,
|
||||
JdbcConnectionDetails connectionDetails) {
|
||||
LiquibaseConnectionDetails connectionDetails) {
|
||||
DataSource migrationDataSource = getMigrationDataSource(liquibaseDataSource, dataSource, connectionDetails);
|
||||
SpringLiquibase liquibase = (migrationDataSource == liquibaseDataSource
|
||||
|| migrationDataSource == dataSource) ? new SpringLiquibase()
|
||||
@ -121,7 +131,7 @@ public class LiquibaseAutoConfiguration {
|
||||
}
|
||||
|
||||
private DataSource getMigrationDataSource(DataSource liquibaseDataSource, DataSource dataSource,
|
||||
JdbcConnectionDetails connectionDetails) {
|
||||
LiquibaseConnectionDetails connectionDetails) {
|
||||
if (liquibaseDataSource != null) {
|
||||
return liquibaseDataSource;
|
||||
}
|
||||
@ -143,7 +153,8 @@ public class LiquibaseAutoConfiguration {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
private void applyConnectionDetails(JdbcConnectionDetails connectionDetails, DataSourceBuilder<?> builder) {
|
||||
private void applyConnectionDetails(LiquibaseConnectionDetails connectionDetails,
|
||||
DataSourceBuilder<?> builder) {
|
||||
builder.username(connectionDetails.getUsername());
|
||||
builder.password(connectionDetails.getPassword());
|
||||
String driverClassName = connectionDetails.getDriverClassName();
|
||||
@ -187,34 +198,46 @@ public class LiquibaseAutoConfiguration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapts {@link LiquibaseProperties} to {@link JdbcConnectionDetails}.
|
||||
* Adapts {@link FlywayProperties} to {@link FlywayConnectionDetails}, using
|
||||
* {@link JdbcConnectionDetails} as a fallback when Flyway-specific properties have
|
||||
* not be configured.
|
||||
*/
|
||||
private static final class LiquibasePropertiesJdbcConnectionDetails implements JdbcConnectionDetails {
|
||||
static final class PropertiesLiquibaseConnectionDetails implements LiquibaseConnectionDetails {
|
||||
|
||||
private final JdbcConnectionDetails fallback;
|
||||
|
||||
private final LiquibaseProperties properties;
|
||||
|
||||
private LiquibasePropertiesJdbcConnectionDetails(LiquibaseProperties properties) {
|
||||
PropertiesLiquibaseConnectionDetails(LiquibaseProperties properties, JdbcConnectionDetails fallback) {
|
||||
this.fallback = fallback;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.properties.getUser();
|
||||
return get(this.properties.getUser(), JdbcConnectionDetails::getUsername);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return this.properties.getPassword();
|
||||
return get(this.properties.getPassword(), JdbcConnectionDetails::getPassword);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJdbcUrl() {
|
||||
return this.properties.getUrl();
|
||||
return get(this.properties.getUrl(), JdbcConnectionDetails::getJdbcUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDriverClassName() {
|
||||
return this.properties.getDriverClassName();
|
||||
return get(this.properties.getDriverClassName(), JdbcConnectionDetails::getDriverClassName);
|
||||
}
|
||||
|
||||
private String get(String primary, Function<JdbcConnectionDetails, String> fallbackProperty) {
|
||||
if (primary != null) {
|
||||
return primary;
|
||||
}
|
||||
return (this.fallback != null) ? fallbackProperty.apply(this.fallback) : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.liquibase;
|
||||
|
||||
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
|
||||
import org.springframework.boot.jdbc.DatabaseDriver;
|
||||
|
||||
/**
|
||||
* Details required for Liquibase to establish a connection to an SQL service using JDBC.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public interface LiquibaseConnectionDetails extends ConnectionDetails {
|
||||
|
||||
/**
|
||||
* Username 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();
|
||||
}
|
||||
|
||||
}
|
@ -45,6 +45,12 @@ import org.springframework.context.annotation.Configuration;
|
||||
@ConditionalOnMissingBean(type = "org.springframework.data.mongodb.MongoDatabaseFactory")
|
||||
public class MongoAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(MongoConnectionDetails.class)
|
||||
PropertiesMongoConnectionDetails mongoConnectionDetails(MongoProperties properties) {
|
||||
return new PropertiesMongoConnectionDetails(properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(MongoClient.class)
|
||||
public MongoClient mongo(ObjectProvider<MongoClientSettingsBuilderCustomizer> builderCustomizers,
|
||||
@ -63,9 +69,7 @@ public class MongoAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
StandardMongoClientSettingsBuilderCustomizer standardMongoSettingsCustomizer(MongoProperties properties,
|
||||
ObjectProvider<MongoConnectionDetails> connectionDetailsProvider) {
|
||||
MongoConnectionDetails connectionDetails = connectionDetailsProvider
|
||||
.getIfAvailable(() -> new PropertiesMongoConnectionDetails(properties));
|
||||
MongoConnectionDetails connectionDetails) {
|
||||
return new StandardMongoClientSettingsBuilderCustomizer(connectionDetails.getConnectionString(),
|
||||
properties.getUuidRepresentation());
|
||||
}
|
||||
|
@ -50,6 +50,12 @@ import org.springframework.core.annotation.Order;
|
||||
@EnableConfigurationProperties(MongoProperties.class)
|
||||
public class MongoReactiveAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(MongoConnectionDetails.class)
|
||||
PropertiesMongoConnectionDetails mongoConnectionDetails(MongoProperties properties) {
|
||||
return new PropertiesMongoConnectionDetails(properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public MongoClient reactiveStreamsMongoClient(
|
||||
@ -70,9 +76,7 @@ public class MongoReactiveAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
StandardMongoClientSettingsBuilderCustomizer standardMongoSettingsCustomizer(MongoProperties properties,
|
||||
ObjectProvider<MongoConnectionDetails> connectionDetailsProvider) {
|
||||
MongoConnectionDetails connectionDetails = connectionDetailsProvider
|
||||
.getIfAvailable(() -> new PropertiesMongoConnectionDetails(properties));
|
||||
MongoConnectionDetails connectionDetails) {
|
||||
return new StandardMongoClientSettingsBuilderCustomizer(connectionDetails.getConnectionString(),
|
||||
properties.getUuidRepresentation());
|
||||
}
|
||||
|
@ -61,13 +61,17 @@ import org.springframework.util.StringUtils;
|
||||
@EnableConfigurationProperties(Neo4jProperties.class)
|
||||
public class Neo4jAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(Neo4jConnectionDetails.class)
|
||||
PropertiesNeo4jConnectionDetails neo4jConnectionDetails(Neo4jProperties properties) {
|
||||
return new PropertiesNeo4jConnectionDetails(properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public Driver neo4jDriver(Neo4jProperties properties, Environment environment,
|
||||
ObjectProvider<ConfigBuilderCustomizer> configBuilderCustomizers,
|
||||
ObjectProvider<Neo4jConnectionDetails> connectionDetailsProvider) {
|
||||
Neo4jConnectionDetails connectionDetails = connectionDetailsProvider
|
||||
.getIfAvailable(() -> new PropertiesNeo4jConnectionDetails(properties));
|
||||
Neo4jConnectionDetails connectionDetails,
|
||||
ObjectProvider<ConfigBuilderCustomizer> configBuilderCustomizers) {
|
||||
AuthToken authToken = connectionDetails.getAuthToken();
|
||||
Config config = mapDriverConfig(properties, connectionDetails,
|
||||
configBuilderCustomizers.orderedStream().toList());
|
||||
|
@ -172,14 +172,21 @@ class RabbitAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void definesPropertiesBasedConnectionDetailsByDefault() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(PropertiesRabbitConnectionDetails.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void testConnectionFactoryWithOverridesWhenUsingConnectionDetails() {
|
||||
void testConnectionFactoryWithOverridesWhenUsingCustomConnectionDetails() {
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class, ConnectionDetailsConfiguration.class)
|
||||
.withPropertyValues("spring.rabbitmq.host:remote-server", "spring.rabbitmq.port:9000",
|
||||
"spring.rabbitmq.username:alice", "spring.rabbitmq.password:secret",
|
||||
"spring.rabbitmq.virtual_host:/vhost")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(RabbitConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesRabbitConnectionDetails.class);
|
||||
CachingConnectionFactory connectionFactory = context.getBean(CachingConnectionFactory.class);
|
||||
assertThat(connectionFactory.getHost()).isEqualTo("rabbit.example.com");
|
||||
assertThat(connectionFactory.getPort()).isEqualTo(12345);
|
||||
|
@ -33,6 +33,7 @@ import com.datastax.oss.driver.internal.core.session.throttling.RateLimitingRequ
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration.PropertiesCassandraConnectionDetails;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@ -95,13 +96,21 @@ class CassandraAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseConnectionDetails() {
|
||||
void definesPropertiesBasedConnectionDetailsByDefault() {
|
||||
this.contextRunner
|
||||
.run((context) -> assertThat(context).hasSingleBean(PropertiesCassandraConnectionDetails.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseCustomConnectionDetailsWhenDefined() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.cassandra.contact-points=localhost:9042", "spring.cassandra.username=a-user",
|
||||
"spring.cassandra.password=a-password", "spring.cassandra.local-datacenter=some-datacenter")
|
||||
.withBean(CassandraConnectionDetails.class, this::cassandraConnectionDetails)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(DriverConfigLoader.class);
|
||||
assertThat(context).hasSingleBean(DriverConfigLoader.class)
|
||||
.hasSingleBean(CassandraConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesCassandraConnectionDetails.class);
|
||||
DriverExecutionProfile configuration = context.getBean(DriverConfigLoader.class)
|
||||
.getInitialConfig()
|
||||
.getDefaultProfile();
|
||||
|
@ -34,6 +34,7 @@ import org.assertj.core.api.InstanceOfAssertFactories;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration.PropertiesCouchbaseConnectionDetails;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -64,10 +65,20 @@ class CouchbaseAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseConnectionDetails() {
|
||||
void definesPropertiesBasedConnectionDetailsByDefault() {
|
||||
this.contextRunner.withUserConfiguration(CouchbaseTestConfiguration.class)
|
||||
.withPropertyValues("spring.couchbase.connection-string=localhost")
|
||||
.run((context) -> assertThat(context).hasSingleBean(PropertiesCouchbaseConnectionDetails.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseCustomConnectionDetailsWhenDefined() {
|
||||
this.contextRunner.withBean(CouchbaseConnectionDetails.class, this::couchbaseConnectionDetails)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(ClusterEnvironment.class).hasSingleBean(Cluster.class);
|
||||
assertThat(context).hasSingleBean(ClusterEnvironment.class)
|
||||
.hasSingleBean(Cluster.class)
|
||||
.hasSingleBean(CouchbaseConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesCouchbaseConnectionDetails.class);
|
||||
Cluster cluster = context.getBean(Cluster.class);
|
||||
assertThat(cluster.core()).extracting("connectionString.hosts")
|
||||
.asList()
|
||||
|
@ -33,6 +33,7 @@ import org.springframework.boot.autoconfigure.data.mongo.country.Country;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoConnectionDetails;
|
||||
import org.springframework.boot.autoconfigure.mongo.PropertiesMongoConnectionDetails;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -225,6 +226,25 @@ class MongoDataAutoConfigurationTests {
|
||||
.run((context) -> assertThat(context).hasSingleBean(MongoTemplate.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void definesPropertiesBasedConnectionDetailsByDefault() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(PropertiesMongoConnectionDetails.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseCustomConnectionDetailsWhenDefined() {
|
||||
this.contextRunner.withBean(MongoConnectionDetails.class, () -> new MongoConnectionDetails() {
|
||||
|
||||
@Override
|
||||
public ConnectionString getConnectionString() {
|
||||
return new ConnectionString("mongodb://localhost/testdb");
|
||||
}
|
||||
|
||||
})
|
||||
.run((context) -> assertThat(context).hasSingleBean(MongoConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesMongoConnectionDetails.class));
|
||||
}
|
||||
|
||||
private static void assertDomainTypesDiscovered(MongoMappingContext mappingContext, Class<?>... types) {
|
||||
ManagedTypes managedTypes = (ManagedTypes) ReflectionTestUtils.getField(mappingContext, "managedTypes");
|
||||
assertThat(managedTypes.toList()).containsOnly(types);
|
||||
|
@ -495,8 +495,15 @@ class RedisAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void usesStandaloneFromConnectionDetailsIfAvailable() {
|
||||
void definesPropertiesBasedConnectionDetailsByDefault() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(PropertiesRedisConnectionDetails.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void usesStandaloneFromCustomConnectionDetails() {
|
||||
this.contextRunner.withUserConfiguration(ConnectionDetailsStandaloneConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(RedisConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesRedisConnectionDetails.class);
|
||||
LettuceConnectionFactory cf = context.getBean(LettuceConnectionFactory.class);
|
||||
assertThat(cf.isUseSsl()).isFalse();
|
||||
RedisStandaloneConfiguration configuration = cf.getStandaloneConfiguration();
|
||||
@ -509,8 +516,10 @@ class RedisAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void usesSentinelFromConnectionDetailsIfAvailable() {
|
||||
void usesSentinelFromCustomConnectionDetails() {
|
||||
this.contextRunner.withUserConfiguration(ConnectionDetailsSentinelConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(RedisConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesRedisConnectionDetails.class);
|
||||
LettuceConnectionFactory cf = context.getBean(LettuceConnectionFactory.class);
|
||||
assertThat(cf.isUseSsl()).isFalse();
|
||||
RedisSentinelConfiguration configuration = cf.getSentinelConfiguration();
|
||||
@ -526,8 +535,10 @@ class RedisAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void usesClusterFromConnectionDetailsIfAvailable() {
|
||||
void usesClusterFromCustomConnectionDetails() {
|
||||
this.contextRunner.withUserConfiguration(ConnectionDetailsClusterConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(RedisConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesRedisConnectionDetails.class);
|
||||
LettuceConnectionFactory cf = context.getBean(LettuceConnectionFactory.class);
|
||||
assertThat(cf.isUseSsl()).isFalse();
|
||||
RedisClusterConfiguration configuration = cf.getClusterConfiguration();
|
||||
|
@ -34,6 +34,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchConnectionDetails.Node.Protocol;
|
||||
import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientConfigurations.PropertiesElasticsearchConnectionDetails;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -248,9 +249,17 @@ class ElasticsearchRestClientAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void connectionDetailsAreUsedIfAvailable() {
|
||||
void definesPropertiesBasedConnectionDetailsByDefault() {
|
||||
this.contextRunner
|
||||
.run((context) -> assertThat(context).hasSingleBean(PropertiesElasticsearchConnectionDetails.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseCustomConnectionDetailsWhenDefined() {
|
||||
this.contextRunner.withUserConfiguration(ConnectionDetailsConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(RestClient.class);
|
||||
assertThat(context).hasSingleBean(RestClient.class)
|
||||
.hasSingleBean(ElasticsearchConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesElasticsearchConnectionDetails.class);
|
||||
RestClient restClient = context.getBean(RestClient.class);
|
||||
assertThat(restClient).hasFieldOrPropertyWithValue("pathPrefix", "/some-path");
|
||||
assertThat(restClient.getNodes().stream().map(Node::getHost).map(HttpHost::toString))
|
||||
|
@ -40,6 +40,7 @@ import org.jooq.impl.DefaultDSLContext;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InOrder;
|
||||
import org.postgresql.Driver;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
|
||||
@ -149,13 +150,34 @@ class FlywayAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void createDataSourceWithJdbcConnectionDetails() {
|
||||
void flywayPropertiesAreUsedOverJdbcConnectionDetails() {
|
||||
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:hsqldb:mem:flywaytest");
|
||||
assertThat(simpleDriverDataSource.getUsername()).isEqualTo("some-user");
|
||||
assertThat(simpleDriverDataSource.getPassword()).isEqualTo("some-password");
|
||||
assertThat(simpleDriverDataSource.getDriver()).isInstanceOf(org.hsqldb.jdbc.JDBCDriver.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void flywayConnectionDetailsAreUsedOverFlywayProperties() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(EmbeddedDataSourceConfiguration.class, FlywayConnectionDetailsConfiguration.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);
|
||||
@ -166,7 +188,7 @@ class FlywayAutoConfigurationTests {
|
||||
.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);
|
||||
assertThat(simpleDriverDataSource.getDriver()).isInstanceOf(Driver.class);
|
||||
});
|
||||
}
|
||||
|
||||
@ -246,6 +268,19 @@ class FlywayAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void flywayDataSourceIsUsedWhenFlywayConnectionDetailsIsAvailable() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(FlywayDataSourceConfiguration.class, EmbeddedDataSourceConfiguration.class,
|
||||
FlywayConnectionDetailsConfiguration.class)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(FlywayConnectionDetails.class);
|
||||
assertThat(context).hasSingleBean(Flyway.class);
|
||||
assertThat(context.getBean(Flyway.class).getConfiguration().getDataSource())
|
||||
.isEqualTo(context.getBean("flywayDataSource"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void flywayDataSourceWithoutDataSourceAutoConfiguration() {
|
||||
this.contextRunner.withUserConfiguration(FlywayDataSourceConfiguration.class).run((context) -> {
|
||||
@ -1109,4 +1144,31 @@ class FlywayAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class FlywayConnectionDetailsConfiguration {
|
||||
|
||||
@Bean
|
||||
FlywayConnectionDetails flywayConnectionDetails() {
|
||||
return new FlywayConnectionDetails() {
|
||||
|
||||
@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";
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import org.junit.jupiter.api.Test;
|
||||
import retrofit2.Retrofit;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration.PropertiesInfluxDbConnectionDetails;
|
||||
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -54,9 +55,17 @@ class InfluxDbAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseConnectionDetails() {
|
||||
void definesPropertiesBasedConnectionDetailsByDefault() {
|
||||
this.contextRunner.withPropertyValues("spring.influx.url=http://localhost")
|
||||
.run((context) -> assertThat(context).hasSingleBean(PropertiesInfluxDbConnectionDetails.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseCustomConnectionDetailsWhenDefined() {
|
||||
this.contextRunner.withBean(InfluxDbConnectionDetails.class, this::influxDbConnectionDetails).run((context) -> {
|
||||
assertThat(context).hasSingleBean(InfluxDB.class);
|
||||
assertThat(context).hasSingleBean(InfluxDB.class)
|
||||
.hasSingleBean(InfluxDbConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesInfluxDbConnectionDetails.class);
|
||||
InfluxDB influxDb = context.getBean(InfluxDB.class);
|
||||
assertThat(influxDb).hasFieldOrPropertyWithValue("hostName", "localhost");
|
||||
});
|
||||
|
@ -249,13 +249,21 @@ class DataSourceAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void dbcp2UsesJdbcConnectionDetailsIfAvailable() {
|
||||
void definesPropertiesBasedConnectionDetailsByDefault() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(PropertiesJdbcConnectionDetails.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void dbcp2UsesCustomConnectionDetailsWhenDefined() {
|
||||
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) -> {
|
||||
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class))
|
||||
.withBean(JdbcConnectionDetails.class, TestJdbcConnectionDetails::new);
|
||||
runner.run((context) -> {
|
||||
assertThat(context).hasSingleBean(JdbcConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesJdbcConnectionDetails.class);
|
||||
DataSource dataSource = context.getBean(DataSource.class);
|
||||
assertThat(dataSource).asInstanceOf(InstanceOfAssertFactories.type(BasicDataSource.class))
|
||||
.satisfies((dbcp2) -> {
|
||||
@ -268,11 +276,14 @@ class DataSourceAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void genericUsesJdbcConnectionDetailsIfAvailable() {
|
||||
void genericUsesCustomJdbcConnectionDetailsWhenAvailable() {
|
||||
ApplicationContextRunner runner = new ApplicationContextRunner()
|
||||
.withPropertyValues("spring.datasource.type=" + TestDataSource.class.getName())
|
||||
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class));
|
||||
runner.withUserConfiguration(JdbcConnectionDetailsConfiguration.class).run((context) -> {
|
||||
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class))
|
||||
.withBean(JdbcConnectionDetails.class, TestJdbcConnectionDetails::new);
|
||||
runner.run((context) -> {
|
||||
assertThat(context).hasSingleBean(JdbcConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesJdbcConnectionDetails.class);
|
||||
DataSource dataSource = context.getBean(DataSource.class);
|
||||
assertThat(dataSource).isInstanceOf(TestDataSource.class);
|
||||
TestDataSource source = (TestDataSource) dataSource;
|
||||
|
@ -104,10 +104,12 @@ class HikariDataSourceConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void usesConnectionDetailsIfAvailable() {
|
||||
this.contextRunner.withUserConfiguration(ConnectionDetailsConfiguration.class)
|
||||
void usesCustomConnectionDetailsWhenDefined() {
|
||||
this.contextRunner.withBean(JdbcConnectionDetails.class, TestJdbcConnectionDetails::new)
|
||||
.withPropertyValues(PREFIX + "url=jdbc:broken", PREFIX + "username=alice", PREFIX + "password=secret")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(JdbcConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesJdbcConnectionDetails.class);
|
||||
DataSource dataSource = context.getBean(DataSource.class);
|
||||
assertThat(dataSource).asInstanceOf(InstanceOfAssertFactories.type(HikariDataSource.class))
|
||||
.satisfies((hikari) -> {
|
||||
|
@ -28,8 +28,6 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.jdbc.DatabaseDriver;
|
||||
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;
|
||||
|
||||
@ -114,10 +112,12 @@ class OracleUcpDataSourceConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void usesJdbcConnectionDetailsIfAvailable() {
|
||||
this.contextRunner.withUserConfiguration(ConnectionDetailsConfiguration.class)
|
||||
void usesCustomJdbcConnectionDetailsWhenDefined() {
|
||||
this.contextRunner.withBean(JdbcConnectionDetails.class, TestJdbcConnectionDetails::new)
|
||||
.withPropertyValues(PREFIX + "url=jdbc:broken", PREFIX + "username=alice", PREFIX + "password=secret")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(JdbcConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesJdbcConnectionDetails.class);
|
||||
DataSource dataSource = context.getBean(DataSource.class);
|
||||
assertThat(dataSource).isInstanceOf(PoolDataSourceImpl.class);
|
||||
PoolDataSourceImpl oracleUcp = (PoolDataSourceImpl) dataSource;
|
||||
@ -131,14 +131,4 @@ class OracleUcpDataSourceConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class ConnectionDetailsConfiguration {
|
||||
|
||||
@Bean
|
||||
JdbcConnectionDetails jdbcConnectionDetails() {
|
||||
return new TestJdbcConnectionDetails();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -117,10 +117,12 @@ class TomcatDataSourceConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void usesJdbcConnectionDetailsIfAvailable() {
|
||||
this.contextRunner.withUserConfiguration(ConnectionDetailsConfiguration.class)
|
||||
void usesCustomJdbcConnectionDetailsWhenDefined() {
|
||||
this.contextRunner.withBean(JdbcConnectionDetails.class, TestJdbcConnectionDetails::new)
|
||||
.withPropertyValues(PREFIX + "url=jdbc:broken", PREFIX + "username=alice", PREFIX + "password=secret")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(JdbcConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesJdbcConnectionDetails.class);
|
||||
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;
|
||||
@ -133,16 +135,6 @@ class TomcatDataSourceConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class ConnectionDetailsConfiguration {
|
||||
|
||||
@Bean
|
||||
JdbcConnectionDetails jdbcConnectionDetails() {
|
||||
return new TestJdbcConnectionDetails();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties
|
||||
@EnableMBeanExport
|
||||
|
@ -96,7 +96,14 @@ class XADataSourceAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseConnectionDetailsIfAvailable() {
|
||||
void definesPropertiesBasedConnectionDetailsByDefault() {
|
||||
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(XADataSourceAutoConfiguration.class))
|
||||
.withUserConfiguration(FromProperties.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(PropertiesJdbcConnectionDetails.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseCustomConnectionDetailsWhenDefined() {
|
||||
JdbcConnectionDetails connectionDetails = mock(JdbcConnectionDetails.class);
|
||||
given(connectionDetails.getUsername()).willReturn("user-1");
|
||||
given(connectionDetails.getPassword()).willReturn("password-1");
|
||||
@ -108,6 +115,8 @@ class XADataSourceAutoConfigurationTests {
|
||||
.withUserConfiguration(FromProperties.class)
|
||||
.withBean(JdbcConnectionDetails.class, () -> connectionDetails)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(JdbcConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesJdbcConnectionDetails.class);
|
||||
MockXADataSourceWrapper wrapper = context.getBean(MockXADataSourceWrapper.class);
|
||||
PGXADataSource dataSource = (PGXADataSource) wrapper.getXaDataSource();
|
||||
assertThat(dataSource).isNotNull();
|
||||
|
@ -164,6 +164,11 @@ class KafkaAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void definesPropertiesBasedConnectionDetailsByDefault() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(PropertiesKafkaConnectionDetails.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void connectionDetailsAreAppliedToConsumer() {
|
||||
this.contextRunner
|
||||
@ -172,6 +177,8 @@ class KafkaAutoConfigurationTests {
|
||||
"spring.kafka.consumer.security.protocol=SSL")
|
||||
.withBean(KafkaConnectionDetails.class, this::kafkaConnectionDetails)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(KafkaConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesKafkaConnectionDetails.class);
|
||||
DefaultKafkaConsumerFactory<?, ?> consumerFactory = context.getBean(DefaultKafkaConsumerFactory.class);
|
||||
Map<String, Object> configs = consumerFactory.getConfigurationProperties();
|
||||
assertThat(configs).containsEntry(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG,
|
||||
@ -240,6 +247,8 @@ class KafkaAutoConfigurationTests {
|
||||
"spring.kafka.producer.security.protocol=SSL")
|
||||
.withBean(KafkaConnectionDetails.class, this::kafkaConnectionDetails)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(KafkaConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesKafkaConnectionDetails.class);
|
||||
DefaultKafkaProducerFactory<?, ?> producerFactory = context.getBean(DefaultKafkaProducerFactory.class);
|
||||
Map<String, Object> configs = producerFactory.getConfigurationProperties();
|
||||
assertThat(configs).containsEntry(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG,
|
||||
@ -298,6 +307,8 @@ class KafkaAutoConfigurationTests {
|
||||
"spring.kafka.admin.security.protocol=SSL")
|
||||
.withBean(KafkaConnectionDetails.class, this::kafkaConnectionDetails)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(KafkaConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesKafkaConnectionDetails.class);
|
||||
KafkaAdmin admin = context.getBean(KafkaAdmin.class);
|
||||
Map<String, Object> configs = admin.getConfigurationProperties();
|
||||
assertThat(configs).containsEntry(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG,
|
||||
@ -363,6 +374,8 @@ class KafkaAutoConfigurationTests {
|
||||
"spring.kafka.security.protocol=SSL", "spring.kafka.streams.security.protocol=SSL")
|
||||
.withBean(KafkaConnectionDetails.class, this::kafkaConnectionDetails)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(KafkaConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesKafkaConnectionDetails.class);
|
||||
Properties configs = context
|
||||
.getBean(KafkaStreamsDefaultConfiguration.DEFAULT_STREAMS_CONFIG_BEAN_NAME,
|
||||
KafkaStreamsConfiguration.class)
|
||||
|
@ -156,6 +156,49 @@ class LiquibaseAutoConfigurationTests {
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void liquibaseDataSourceIsUsedOverLiquibaseConnectionDetails() {
|
||||
this.contextRunner
|
||||
.withUserConfiguration(LiquibaseDataSourceConfiguration.class,
|
||||
LiquibaseConnectionDetailsConfiguration.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
|
||||
void liquibasePropertiesAreUsedOverJdbcConnectionDetails() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.liquibase.url=jdbc:hsqldb:mem:liquibasetest", "spring.liquibase.user=some-user",
|
||||
"spring.liquibase.password=some-password",
|
||||
"spring.liquibase.driver-class-name=org.hsqldb.jdbc.JDBCDriver")
|
||||
.withUserConfiguration(JdbcConnectionDetailsConfiguration.class)
|
||||
.run(assertLiquibase((liquibase) -> {
|
||||
SimpleDriverDataSource dataSource = (SimpleDriverDataSource) liquibase.getDataSource();
|
||||
assertThat(dataSource.getUrl()).startsWith("jdbc:hsqldb:mem:liquibasetest");
|
||||
assertThat(dataSource.getUsername()).isEqualTo("some-user");
|
||||
assertThat(dataSource.getPassword()).isEqualTo("some-password");
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void liquibaseConnectionDetailsAreUsedOverLiquibaseProperties() {
|
||||
this.contextRunner.withSystemProperties("shouldRun=false")
|
||||
.withPropertyValues("spring.liquibase.url=jdbc:hsqldb:mem:liquibasetest", "spring.liquibase.user=some-user",
|
||||
"spring.liquibase.password=some-password",
|
||||
"spring.liquibase.driver-class-name=org.hsqldb.jdbc.JDBCDriver")
|
||||
.withUserConfiguration(LiquibaseConnectionDetailsConfiguration.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 changelogXml() {
|
||||
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
|
||||
@ -578,6 +621,33 @@ class LiquibaseAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class LiquibaseConnectionDetailsConfiguration {
|
||||
|
||||
@Bean
|
||||
LiquibaseConnectionDetails liquibaseConnectionDetails() {
|
||||
return new LiquibaseConnectionDetails() {
|
||||
|
||||
@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 {
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.mongo;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.mongodb.ConnectionString;
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.client.MongoClient;
|
||||
import com.mongodb.client.MongoClients;
|
||||
@ -84,6 +85,25 @@ class MongoAutoConfigurationTests {
|
||||
.run((context) -> assertThat(getSettings(context).getApplicationName()).isEqualTo("overridden-name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void definesPropertiesBasedConnectionDetailsByDefault() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(PropertiesMongoConnectionDetails.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseCustomConnectionDetailsWhenDefined() {
|
||||
this.contextRunner.withBean(MongoConnectionDetails.class, () -> new MongoConnectionDetails() {
|
||||
|
||||
@Override
|
||||
public ConnectionString getConnectionString() {
|
||||
return new ConnectionString("mongodb://localhost");
|
||||
}
|
||||
|
||||
})
|
||||
.run((context) -> assertThat(context).hasSingleBean(MongoConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesMongoConnectionDetails.class));
|
||||
}
|
||||
|
||||
private MongoClientSettings getSettings(AssertableApplicationContext context) {
|
||||
assertThat(context).hasSingleBean(MongoClient.class);
|
||||
MongoClientImpl client = (MongoClientImpl) context.getBean(MongoClient.class);
|
||||
|
@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.mongo;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import com.mongodb.ConnectionString;
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.ReadPreference;
|
||||
import com.mongodb.connection.AsynchronousSocketChannelStreamFactoryFactory;
|
||||
@ -111,6 +112,25 @@ class MongoReactiveAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void definesPropertiesBasedConnectionDetailsByDefault() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(PropertiesMongoConnectionDetails.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseCustomConnectionDetailsWhenDefined() {
|
||||
this.contextRunner.withBean(MongoConnectionDetails.class, () -> new MongoConnectionDetails() {
|
||||
|
||||
@Override
|
||||
public ConnectionString getConnectionString() {
|
||||
return new ConnectionString("mongodb://localhost");
|
||||
}
|
||||
|
||||
})
|
||||
.run((context) -> assertThat(context).hasSingleBean(MongoConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesMongoConnectionDetails.class));
|
||||
}
|
||||
|
||||
private MongoClientSettings getSettings(ApplicationContext context) {
|
||||
MongoClientImpl client = (MongoClientImpl) context.getBean(MongoClient.class);
|
||||
return client.getSettings();
|
||||
|
@ -105,8 +105,13 @@ class Neo4jAutoConfigurationTests {
|
||||
.hasMessageContaining("'%s' is not a supported scheme.", invalidScheme));
|
||||
}
|
||||
|
||||
@Test
|
||||
void definesPropertiesBasedConnectionDetailsByDefault() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(PropertiesNeo4jConnectionDetails.class));
|
||||
}
|
||||
|
||||
@Bean
|
||||
void usesCustomConnectionDetails() {
|
||||
void shouldUseCustomConnectionDetailsWhenDefined() {
|
||||
this.contextRunner.withBean(Neo4jConnectionDetails.class, () -> new Neo4jConnectionDetails() {
|
||||
|
||||
@Override
|
||||
@ -115,7 +120,9 @@ class Neo4jAutoConfigurationTests {
|
||||
}
|
||||
|
||||
}).run((context) -> {
|
||||
assertThat(context).hasSingleBean(Driver.class);
|
||||
assertThat(context).hasSingleBean(Driver.class)
|
||||
.hasSingleBean(Neo4jConnectionDetails.class)
|
||||
.doesNotHaveBean(PropertiesNeo4jConnectionDetails.class);
|
||||
Driver driver = context.getBean(Driver.class);
|
||||
assertThat(driver.isEncrypted()).isTrue();
|
||||
});
|
||||
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.test.autoconfigure.flyway;
|
||||
|
||||
import org.testcontainers.containers.JdbcDatabaseContainer;
|
||||
|
||||
import org.springframework.boot.autoconfigure.flyway.FlywayConnectionDetails;
|
||||
import org.springframework.boot.test.autoconfigure.service.connection.ContainerConnectionDetailsFactory;
|
||||
import org.springframework.boot.test.autoconfigure.service.connection.ContainerConnectionSource;
|
||||
import org.springframework.boot.test.autoconfigure.service.connection.ServiceConnection;
|
||||
|
||||
/**
|
||||
* {@link ContainerConnectionDetailsFactory} for
|
||||
* {@link ServiceConnection @ServiceConnection}-annotated {@link JdbcDatabaseContainer}
|
||||
* fields that should produce {@link FlywayConnectionDetails}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class FlywayContainerConnectionDetailsFactory extends
|
||||
ContainerConnectionDetailsFactory<ServiceConnection, FlywayConnectionDetails, JdbcDatabaseContainer<?>> {
|
||||
|
||||
@Override
|
||||
protected FlywayConnectionDetails getContainerConnectionDetails(
|
||||
ContainerConnectionSource<ServiceConnection, FlywayConnectionDetails, JdbcDatabaseContainer<?>> source) {
|
||||
return new FlywayContainerConnectionDetails(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link FlywayConnectionDetails} backed by a {@link JdbcDatabaseContainer}.
|
||||
*/
|
||||
private static final class FlywayContainerConnectionDetails extends ContainerConnectionDetails
|
||||
implements FlywayConnectionDetails {
|
||||
|
||||
private final JdbcDatabaseContainer<?> container;
|
||||
|
||||
private FlywayContainerConnectionDetails(
|
||||
ContainerConnectionSource<ServiceConnection, FlywayConnectionDetails, JdbcDatabaseContainer<?>> source) {
|
||||
super(source);
|
||||
this.container = source.getContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.container.getUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return this.container.getPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJdbcUrl() {
|
||||
return this.container.getJdbcUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDriverClassName() {
|
||||
return this.container.getDriverClassName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Auto-configuration for using Flyway in tests.
|
||||
*/
|
||||
package org.springframework.boot.test.autoconfigure.flyway;
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.test.autoconfigure.liquibase;
|
||||
|
||||
import org.testcontainers.containers.JdbcDatabaseContainer;
|
||||
|
||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseConnectionDetails;
|
||||
import org.springframework.boot.test.autoconfigure.service.connection.ContainerConnectionDetailsFactory;
|
||||
import org.springframework.boot.test.autoconfigure.service.connection.ContainerConnectionSource;
|
||||
import org.springframework.boot.test.autoconfigure.service.connection.ServiceConnection;
|
||||
|
||||
/**
|
||||
* {@link ContainerConnectionDetailsFactory} for
|
||||
* {@link ServiceConnection @ServiceConnection}-annotated {@link JdbcDatabaseContainer}
|
||||
* fields that should produce {@link LiquibaseConnectionDetails}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class LiquibaseContainerConnectionDetailsFactory extends
|
||||
ContainerConnectionDetailsFactory<ServiceConnection, LiquibaseConnectionDetails, JdbcDatabaseContainer<?>> {
|
||||
|
||||
@Override
|
||||
protected LiquibaseConnectionDetails getContainerConnectionDetails(
|
||||
ContainerConnectionSource<ServiceConnection, LiquibaseConnectionDetails, JdbcDatabaseContainer<?>> source) {
|
||||
return new LiquibaseContainerConnectionDetails(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link LiquibaseConnectionDetails} backed by a {@link JdbcDatabaseContainer}.
|
||||
*/
|
||||
private static final class LiquibaseContainerConnectionDetails extends ContainerConnectionDetails
|
||||
implements LiquibaseConnectionDetails {
|
||||
|
||||
private final JdbcDatabaseContainer<?> container;
|
||||
|
||||
private LiquibaseContainerConnectionDetails(
|
||||
ContainerConnectionSource<ServiceConnection, LiquibaseConnectionDetails, JdbcDatabaseContainer<?>> source) {
|
||||
super(source);
|
||||
this.container = source.getContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.container.getUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return this.container.getPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJdbcUrl() {
|
||||
return this.container.getJdbcUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDriverClassName() {
|
||||
return this.container.getDriverClassName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Auto-configuration for using Liquibase in tests.
|
||||
*/
|
||||
package org.springframework.boot.test.autoconfigure.liquibase;
|
@ -26,9 +26,11 @@ org.springframework.boot.test.autoconfigure.cassandra.CassandraContainerConnecti
|
||||
org.springframework.boot.test.autoconfigure.couchbase.CouchbaseContainerConnectionDetailsFactory,\
|
||||
org.springframework.boot.test.autoconfigure.data.redis.RedisContainerConnectionDetailsFactory,\
|
||||
org.springframework.boot.test.autoconfigure.elasticsearch.ElasticsearchContainerConnectionDetailsFactory,\
|
||||
org.springframework.boot.test.autoconfigure.flyway.FlywayContainerConnectionDetailsFactory,\
|
||||
org.springframework.boot.test.autoconfigure.influx.InfluxDbContainerConnectionDetailsFactory,\
|
||||
org.springframework.boot.test.autoconfigure.jdbc.JdbcContainerConnectionDetailsFactory,\
|
||||
org.springframework.boot.test.autoconfigure.kafka.KafkaContainerConnectionDetailsFactory,\
|
||||
org.springframework.boot.test.autoconfigure.liquibase.LiquibaseContainerConnectionDetailsFactory,\
|
||||
org.springframework.boot.test.autoconfigure.mongo.MongoContainerConnectionDetailsFactory,\
|
||||
org.springframework.boot.test.autoconfigure.neo4j.Neo4jContainerConnectionDetailsFactory,\
|
||||
org.springframework.boot.test.autoconfigure.r2dbc.MariaDbR2dbcContainerConnectionDetailsFactory,\
|
||||
|
@ -23,9 +23,10 @@ import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.flyway.FlywayConnectionDetails;
|
||||
import org.springframework.boot.test.autoconfigure.data.r2dbc.DataR2dbcTest;
|
||||
import org.springframework.boot.test.autoconfigure.jdbc.JdbcServiceConnection;
|
||||
import org.springframework.boot.test.autoconfigure.r2dbc.R2dbcServiceConnection;
|
||||
import org.springframework.boot.test.autoconfigure.service.connection.ServiceConnection;
|
||||
import org.springframework.boot.testsupport.testcontainers.DockerImageNames;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@ -42,8 +43,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class CityRepositoryTests {
|
||||
|
||||
@Container
|
||||
@JdbcServiceConnection
|
||||
@R2dbcServiceConnection
|
||||
@ServiceConnection(FlywayConnectionDetails.class)
|
||||
static PostgreSQLContainer<?> postgresql = new PostgreSQLContainer<>(DockerImageNames.postgresql())
|
||||
.withDatabaseName("test_flyway");
|
||||
|
||||
|
@ -23,9 +23,10 @@ import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseConnectionDetails;
|
||||
import org.springframework.boot.test.autoconfigure.data.r2dbc.DataR2dbcTest;
|
||||
import org.springframework.boot.test.autoconfigure.jdbc.JdbcServiceConnection;
|
||||
import org.springframework.boot.test.autoconfigure.r2dbc.R2dbcServiceConnection;
|
||||
import org.springframework.boot.test.autoconfigure.service.connection.ServiceConnection;
|
||||
import org.springframework.boot.testsupport.testcontainers.DockerImageNames;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@ -42,8 +43,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class CityRepositoryTests {
|
||||
|
||||
@Container
|
||||
@JdbcServiceConnection
|
||||
@R2dbcServiceConnection
|
||||
@ServiceConnection(LiquibaseConnectionDetails.class)
|
||||
static PostgreSQLContainer<?> postgresql = new PostgreSQLContainer<>(DockerImageNames.postgresql())
|
||||
.withDatabaseName("test_liquibase");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user