From 5e9cfea5a83ef3ffb4a7301095775822d360f976 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Fri, 15 Dec 2017 15:05:44 -0800 Subject: [PATCH] Migrate to auto-configurations to PropertyMapper Update auto-configuration classes that have extensive property mapping code to make use of the new `PropertyMapper` utility. Fixes gh-9018 --- ...bitListenerContainerFactoryConfigurer.java | 7 +- .../amqp/RabbitAutoConfiguration.java | 143 +++++++++--------- ...bitListenerContainerFactoryConfigurer.java | 16 +- .../batch/BasicBatchConfigurer.java | 34 ++--- .../cache/CouchbaseCacheConfiguration.java | 9 +- .../cache/InfinispanCacheConfiguration.java | 6 +- .../cassandra/CassandraAutoConfiguration.java | 99 +++++------- .../CassandraDataAutoConfiguration.java | 12 +- .../data/rest/RepositoryRestProperties.java | 48 ++---- .../jest/JestAutoConfiguration.java | 39 +++-- .../jms/JmsAutoConfiguration.java | 62 ++++---- ...fkaListenerContainerFactoryConfigurer.java | 63 ++++---- .../mail/MailSenderAutoConfiguration.java | 25 ++- .../RedisReactiveSessionConfiguration.java | 5 +- .../thymeleaf/ThymeleafAutoConfiguration.java | 41 ++--- .../autoconfigure/web/ResourceProperties.java | 48 +++--- 16 files changed, 295 insertions(+), 362 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/DirectRabbitListenerContainerFactoryConfigurer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/DirectRabbitListenerContainerFactoryConfigurer.java index 82af8d91d5..d3cd82b530 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/DirectRabbitListenerContainerFactoryConfigurer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/DirectRabbitListenerContainerFactoryConfigurer.java @@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.amqp; import org.springframework.amqp.rabbit.config.DirectRabbitListenerContainerFactory; import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.boot.context.properties.PropertyMapper; /** * Configure {@link DirectRabbitListenerContainerFactoryConfigurer} with sensible @@ -33,12 +34,12 @@ public final class DirectRabbitListenerContainerFactoryConfigurer extends @Override public void configure(DirectRabbitListenerContainerFactory factory, ConnectionFactory connectionFactory) { + PropertyMapper map = PropertyMapper.get(); RabbitProperties.DirectContainer config = getRabbitProperties().getListener() .getDirect(); configure(factory, connectionFactory, config); - if (config.getConsumersPerQueue() != null) { - factory.setConsumersPerQueue(config.getConsumersPerQueue()); - } + map.from(config::getConsumersPerQueue).whenNonNull() + .to(factory::setConsumersPerQueue); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitAutoConfiguration.java index a818a76680..583e38ca45 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitAutoConfiguration.java @@ -16,6 +16,8 @@ package org.springframework.boot.autoconfigure.amqp; +import java.time.Duration; + import com.rabbitmq.client.Channel; import org.springframework.amqp.core.AmqpAdmin; @@ -33,6 +35,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -76,6 +79,7 @@ import org.springframework.retry.support.RetryTemplate; * @author Josh Long * @author Stephane Nicoll * @author Gary Russell + * @author Phillip Webb */ @Configuration @ConditionalOnClass({ RabbitTemplate.class, Channel.class }) @@ -88,66 +92,55 @@ public class RabbitAutoConfiguration { protected static class RabbitConnectionFactoryCreator { @Bean - public CachingConnectionFactory rabbitConnectionFactory(RabbitProperties config) - throws Exception { + public CachingConnectionFactory rabbitConnectionFactory( + RabbitProperties properties) throws Exception { + PropertyMapper map = PropertyMapper.get(); + CachingConnectionFactory factory = new CachingConnectionFactory( + getRabbitConnectionFactoryBean(properties).getObject()); + map.from(properties::determineAddresses).to(factory::setAddresses); + map.from(properties::isPublisherConfirms).to(factory::setPublisherConfirms); + map.from(properties::isPublisherReturns).to(factory::setPublisherReturns); + RabbitProperties.Cache.Channel channel = properties.getCache().getChannel(); + map.from(channel::getSize).whenNonNull().to(factory::setChannelCacheSize); + map.from(channel::getCheckoutTimeout).whenNonNull() + .to(factory::setChannelCheckoutTimeout); + RabbitProperties.Cache.Connection connection = properties.getCache() + .getConnection(); + map.from(connection::getMode).whenNonNull().to(factory::setCacheMode); + map.from(connection::getSize).whenNonNull() + .to(factory::setConnectionCacheSize); + return factory; + } + + private RabbitConnectionFactoryBean getRabbitConnectionFactoryBean( + RabbitProperties properties) throws Exception { + PropertyMapper map = PropertyMapper.get(); RabbitConnectionFactoryBean factory = new RabbitConnectionFactoryBean(); - if (config.determineHost() != null) { - factory.setHost(config.determineHost()); - } - factory.setPort(config.determinePort()); - if (config.determineUsername() != null) { - factory.setUsername(config.determineUsername()); - } - if (config.determinePassword() != null) { - factory.setPassword(config.determinePassword()); - } - if (config.determineVirtualHost() != null) { - factory.setVirtualHost(config.determineVirtualHost()); - } - if (config.getRequestedHeartbeat() != null) { - factory.setRequestedHeartbeat( - (int) config.getRequestedHeartbeat().getSeconds()); - } - RabbitProperties.Ssl ssl = config.getSsl(); + map.from(properties::determineHost).whenNonNull().to(factory::setHost); + map.from(properties::determinePort).to(factory::setPort); + map.from(properties::determineUsername).whenNonNull() + .to(factory::setUsername); + map.from(properties::determinePassword).whenNonNull() + .to(factory::setPassword); + map.from(properties::determineVirtualHost).whenNonNull() + .to(factory::setVirtualHost); + map.from(properties::getRequestedHeartbeat).whenNonNull() + .asInt(Duration::getSeconds).to(factory::setRequestedHeartbeat); + RabbitProperties.Ssl ssl = properties.getSsl(); if (ssl.isEnabled()) { factory.setUseSSL(true); - if (ssl.getAlgorithm() != null) { - factory.setSslAlgorithm(ssl.getAlgorithm()); - } - factory.setKeyStoreType(ssl.getKeyStoreType()); - factory.setKeyStore(ssl.getKeyStore()); - factory.setKeyStorePassphrase(ssl.getKeyStorePassword()); - factory.setTrustStoreType(ssl.getTrustStoreType()); - factory.setTrustStore(ssl.getTrustStore()); - factory.setTrustStorePassphrase(ssl.getTrustStorePassword()); - } - if (config.getConnectionTimeout() != null) { - factory.setConnectionTimeout( - (int) config.getConnectionTimeout().toMillis()); + map.from(ssl::getAlgorithm).whenNonNull().to(factory::setSslAlgorithm); + map.from(ssl::getKeyStoreType).to(factory::setKeyStoreType); + map.from(ssl::getKeyStore).to(factory::setKeyStore); + map.from(ssl::getKeyStorePassword).to(factory::setKeyStorePassphrase); + map.from(ssl::getTrustStoreType).to(factory::setTrustStoreType); + map.from(ssl::getTrustStore).to(factory::setTrustStore); + map.from(ssl::getTrustStorePassword).to(factory::setTrustStorePassphrase); } + map.from(properties::getConnectionTimeout).whenNonNull() + .asInt(Duration::toMillis).to(factory::setConnectionTimeout); factory.afterPropertiesSet(); - CachingConnectionFactory connectionFactory = new CachingConnectionFactory( - factory.getObject()); - connectionFactory.setAddresses(config.determineAddresses()); - connectionFactory.setPublisherConfirms(config.isPublisherConfirms()); - connectionFactory.setPublisherReturns(config.isPublisherReturns()); - if (config.getCache().getChannel().getSize() != null) { - connectionFactory - .setChannelCacheSize(config.getCache().getChannel().getSize()); - } - if (config.getCache().getConnection().getMode() != null) { - connectionFactory - .setCacheMode(config.getCache().getConnection().getMode()); - } - if (config.getCache().getConnection().getSize() != null) { - connectionFactory.setConnectionCacheSize( - config.getCache().getConnection().getSize()); - } - if (config.getCache().getChannel().getCheckoutTimeout() != null) { - connectionFactory.setChannelCheckoutTimeout( - config.getCache().getChannel().getCheckoutTimeout()); - } - return connectionFactory; + return factory; } } @@ -171,26 +164,24 @@ public class RabbitAutoConfiguration { @ConditionalOnSingleCandidate(ConnectionFactory.class) @ConditionalOnMissingBean(RabbitTemplate.class) public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) { - RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory); + PropertyMapper map = PropertyMapper.get(); + RabbitTemplate template = new RabbitTemplate(connectionFactory); MessageConverter messageConverter = this.messageConverter.getIfUnique(); if (messageConverter != null) { - rabbitTemplate.setMessageConverter(messageConverter); + template.setMessageConverter(messageConverter); } - rabbitTemplate.setMandatory(determineMandatoryFlag()); - RabbitProperties.Template templateProperties = this.properties.getTemplate(); - RabbitProperties.Retry retryProperties = templateProperties.getRetry(); - if (retryProperties.isEnabled()) { - rabbitTemplate.setRetryTemplate(createRetryTemplate(retryProperties)); + template.setMandatory(determineMandatoryFlag()); + RabbitProperties.Template properties = this.properties.getTemplate(); + if (properties.getRetry().isEnabled()) { + template.setRetryTemplate(createRetryTemplate(properties.getRetry())); } - if (templateProperties.getReceiveTimeout() != null) { - rabbitTemplate.setReceiveTimeout(templateProperties.getReceiveTimeout()); - } - if (templateProperties.getReplyTimeout() != null) { - rabbitTemplate.setReplyTimeout(templateProperties.getReplyTimeout()); - } - rabbitTemplate.setExchange(templateProperties.getExchange()); - rabbitTemplate.setRoutingKey(templateProperties.getRoutingKey()); - return rabbitTemplate; + map.from(properties::getReceiveTimeout).whenNonNull() + .to(template::setReceiveTimeout); + map.from(properties::getReplyTimeout).whenNonNull() + .to(template::setReplyTimeout); + map.from(properties::getExchange).to(template::setExchange); + map.from(properties::getRoutingKey).to(template::setRoutingKey); + return template; } private boolean determineMandatoryFlag() { @@ -199,14 +190,16 @@ public class RabbitAutoConfiguration { } private RetryTemplate createRetryTemplate(RabbitProperties.Retry properties) { + PropertyMapper map = PropertyMapper.get(); RetryTemplate template = new RetryTemplate(); SimpleRetryPolicy policy = new SimpleRetryPolicy(); - policy.setMaxAttempts(properties.getMaxAttempts()); + map.from(properties::getMaxAttempts).to(policy::setMaxAttempts); template.setRetryPolicy(policy); ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy(); - backOffPolicy.setInitialInterval(properties.getInitialInterval()); - backOffPolicy.setMultiplier(properties.getMultiplier()); - backOffPolicy.setMaxInterval(properties.getMaxInterval()); + map.from(properties::getInitialInterval) + .to(backOffPolicy::setInitialInterval); + map.from(properties::getMultiplier).to(backOffPolicy::setMultiplier); + map.from(properties::getMaxInterval).to(backOffPolicy::setMaxInterval); template.setBackOffPolicy(backOffPolicy); return template; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/SimpleRabbitListenerContainerFactoryConfigurer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/SimpleRabbitListenerContainerFactoryConfigurer.java index bf076c8bd6..6321fab609 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/SimpleRabbitListenerContainerFactoryConfigurer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/SimpleRabbitListenerContainerFactoryConfigurer.java @@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.amqp; import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.boot.context.properties.PropertyMapper; /** * Configure {@link SimpleRabbitListenerContainerFactoryConfigurer} with sensible @@ -33,18 +34,15 @@ public final class SimpleRabbitListenerContainerFactoryConfigurer extends @Override public void configure(SimpleRabbitListenerContainerFactory factory, ConnectionFactory connectionFactory) { + PropertyMapper map = PropertyMapper.get(); RabbitProperties.SimpleContainer config = getRabbitProperties().getListener() .getSimple(); configure(factory, connectionFactory, config); - if (config.getConcurrency() != null) { - factory.setConcurrentConsumers(config.getConcurrency()); - } - if (config.getMaxConcurrency() != null) { - factory.setMaxConcurrentConsumers(config.getMaxConcurrency()); - } - if (config.getTransactionSize() != null) { - factory.setTxSize(config.getTransactionSize()); - } + map.from(config::getConcurrency).whenNonNull() + .to(factory::setConcurrentConsumers); + map.from(config::getMaxConcurrency).whenNonNull() + .to(factory::setMaxConcurrentConsumers); + map.from(config::getTransactionSize).whenNonNull().to(factory::setTxSize); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BasicBatchConfigurer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BasicBatchConfigurer.java index 8917fcc008..f14aed862d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BasicBatchConfigurer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BasicBatchConfigurer.java @@ -27,9 +27,9 @@ import org.springframework.batch.core.launch.support.SimpleJobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.util.StringUtils; /** * Basic {@link BatchConfigurer} implementation. @@ -103,14 +103,13 @@ public class BasicBatchConfigurer implements BatchConfigurer { } protected JobExplorer createJobExplorer() throws Exception { - JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean(); - jobExplorerFactoryBean.setDataSource(this.dataSource); - String tablePrefix = this.properties.getTablePrefix(); - if (StringUtils.hasText(tablePrefix)) { - jobExplorerFactoryBean.setTablePrefix(tablePrefix); - } - jobExplorerFactoryBean.afterPropertiesSet(); - return jobExplorerFactoryBean.getObject(); + PropertyMapper map = PropertyMapper.get(); + JobExplorerFactoryBean factory = new JobExplorerFactoryBean(); + factory.setDataSource(this.dataSource); + map.from(this.properties::getTablePrefix).whenHasText() + .to(factory::setTablePrefix); + factory.afterPropertiesSet(); + return factory.getObject(); } protected JobLauncher createJobLauncher() throws Exception { @@ -122,16 +121,13 @@ public class BasicBatchConfigurer implements BatchConfigurer { protected JobRepository createJobRepository() throws Exception { JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); - factory.setDataSource(this.dataSource); - String isolationLevel = determineIsolationLevel(); - if (isolationLevel != null) { - factory.setIsolationLevelForCreate(isolationLevel); - } - String tablePrefix = this.properties.getTablePrefix(); - if (StringUtils.hasText(tablePrefix)) { - factory.setTablePrefix(tablePrefix); - } - factory.setTransactionManager(getTransactionManager()); + PropertyMapper map = PropertyMapper.get(); + map.from(() -> this.dataSource).to(factory::setDataSource); + map.from(this::determineIsolationLevel).whenNonNull() + .to(factory::setIsolationLevelForCreate); + map.from(this.properties::getTablePrefix).whenHasText() + .to(factory::setTablePrefix); + map.from(this::getTransactionManager).to(factory::setTransactionManager); factory.afterPropertiesSet(); return factory.getObject(); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CouchbaseCacheConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CouchbaseCacheConfiguration.java index 650d3c6140..ed92bfc707 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CouchbaseCacheConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CouchbaseCacheConfiguration.java @@ -23,9 +23,11 @@ import com.couchbase.client.java.Bucket; import com.couchbase.client.spring.cache.CacheBuilder; import com.couchbase.client.spring.cache.CouchbaseCacheManager; +import org.springframework.boot.autoconfigure.cache.CacheProperties.Couchbase; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.cache.CacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; @@ -61,10 +63,9 @@ public class CouchbaseCacheConfiguration { public CouchbaseCacheManager cacheManager() { List cacheNames = this.cacheProperties.getCacheNames(); CacheBuilder builder = CacheBuilder.newInstance(this.bucket); - Duration expiration = this.cacheProperties.getCouchbase().getExpiration(); - if (expiration != null) { - builder = builder.withExpiration((int) expiration.getSeconds()); - } + Couchbase couchbase = this.cacheProperties.getCouchbase(); + PropertyMapper.get().from(couchbase::getExpiration).whenNonNull() + .asInt(Duration::getSeconds).to(builder::withExpiration); String[] names = cacheNames.toArray(new String[cacheNames.size()]); CouchbaseCacheManager cacheManager = new CouchbaseCacheManager(builder, names); return this.customizers.customize(cacheManager); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/InfinispanCacheConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/InfinispanCacheConfiguration.java index 440627d267..76bc8da2cf 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/InfinispanCacheConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/InfinispanCacheConfiguration.java @@ -77,10 +77,8 @@ public class InfinispanCacheConfiguration { EmbeddedCacheManager cacheManager = createEmbeddedCacheManager(); List cacheNames = this.cacheProperties.getCacheNames(); if (!CollectionUtils.isEmpty(cacheNames)) { - for (String cacheName : cacheNames) { - cacheManager.defineConfiguration(cacheName, - getDefaultCacheConfiguration()); - } + cacheNames.forEach((cacheName) -> cacheManager.defineConfiguration(cacheName, + getDefaultCacheConfiguration())); } return cacheManager; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfiguration.java index dc90883d95..d8f2e4d933 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfiguration.java @@ -16,15 +16,13 @@ package org.springframework.boot.autoconfigure.cassandra; +import java.time.Duration; import java.util.List; import com.datastax.driver.core.Cluster; import com.datastax.driver.core.PoolingOptions; import com.datastax.driver.core.QueryOptions; import com.datastax.driver.core.SocketOptions; -import com.datastax.driver.core.policies.LoadBalancingPolicy; -import com.datastax.driver.core.policies.ReconnectionPolicy; -import com.datastax.driver.core.policies.RetryPolicy; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.ObjectProvider; @@ -32,6 +30,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -62,36 +61,27 @@ public class CassandraAutoConfiguration { @Bean @ConditionalOnMissingBean public Cluster cassandraCluster() { + PropertyMapper map = PropertyMapper.get(); CassandraProperties properties = this.properties; Cluster.Builder builder = Cluster.builder() .withClusterName(properties.getClusterName()) .withPort(properties.getPort()); - if (properties.getUsername() != null) { - builder.withCredentials(properties.getUsername(), properties.getPassword()); - } - if (properties.getCompression() != null) { - builder.withCompression(properties.getCompression()); - } - if (properties.getLoadBalancingPolicy() != null) { - LoadBalancingPolicy policy = instantiate(properties.getLoadBalancingPolicy()); - builder.withLoadBalancingPolicy(policy); - } - builder.withQueryOptions(getQueryOptions()); - if (properties.getReconnectionPolicy() != null) { - ReconnectionPolicy policy = instantiate(properties.getReconnectionPolicy()); - builder.withReconnectionPolicy(policy); - } - if (properties.getRetryPolicy() != null) { - RetryPolicy policy = instantiate(properties.getRetryPolicy()); - builder.withRetryPolicy(policy); - } - builder.withSocketOptions(getSocketOptions()); - if (properties.isSsl()) { - builder.withSSL(); - } - builder.withPoolingOptions(getPoolingOptions()); - builder.addContactPoints(properties.getContactPoints().toArray(new String[0])); - + map.from(properties::getUsername).whenNonNull().to((username) -> builder + .withCredentials(username, properties.getPassword())); + map.from(properties::getCompression).whenNonNull().to(builder::withCompression); + map.from(properties::getLoadBalancingPolicy).whenNonNull() + .as(BeanUtils::instantiateClass).to(builder::withLoadBalancingPolicy); + map.from(this::getQueryOptions).to(builder::withQueryOptions); + map.from(properties::getReconnectionPolicy).whenNonNull() + .as(BeanUtils::instantiateClass).to(builder::withReconnectionPolicy); + map.from(properties::getRetryPolicy).whenNonNull().as(BeanUtils::instantiateClass) + .to(builder::withRetryPolicy); + map.from(this::getSocketOptions).to(builder::withSocketOptions); + map.from(properties::isSsl).whenTrue().toCall(builder::withSSL); + map.from(this::getPoolingOptions).to(builder::withPoolingOptions); + map.from(properties::getContactPoints) + .as((list) -> list.toArray(new String[list.size()])) + .to(builder::addContactPoints); customize(builder); return builder.build(); } @@ -104,50 +94,39 @@ public class CassandraAutoConfiguration { } } - public static T instantiate(Class type) { - return BeanUtils.instantiateClass(type); - } - private QueryOptions getQueryOptions() { + PropertyMapper map = PropertyMapper.get(); QueryOptions options = new QueryOptions(); CassandraProperties properties = this.properties; - if (properties.getConsistencyLevel() != null) { - options.setConsistencyLevel(properties.getConsistencyLevel()); - } - if (properties.getSerialConsistencyLevel() != null) { - options.setSerialConsistencyLevel(properties.getSerialConsistencyLevel()); - } - options.setFetchSize(properties.getFetchSize()); + map.from(properties::getConsistencyLevel).whenNonNull() + .to(options::setConsistencyLevel); + map.from(properties::getSerialConsistencyLevel).whenNonNull() + .to(options::setSerialConsistencyLevel); + map.from(properties::getFetchSize).to(options::setFetchSize); return options; } private SocketOptions getSocketOptions() { + PropertyMapper map = PropertyMapper.get(); SocketOptions options = new SocketOptions(); - if (this.properties.getConnectTimeout() != null) { - options.setConnectTimeoutMillis( - (int) this.properties.getConnectTimeout().toMillis()); - } - if (this.properties.getReadTimeout() != null) { - options.setReadTimeoutMillis( - (int) this.properties.getReadTimeout().toMillis()); - } + map.from(this.properties::getConnectTimeout).whenNonNull() + .asInt(Duration::toMillis).to(options::setConnectTimeoutMillis); + map.from(this.properties::getReadTimeout).whenNonNull().asInt(Duration::toMillis) + .to(options::setReadTimeoutMillis); return options; } private PoolingOptions getPoolingOptions() { - CassandraProperties.Pool pool = this.properties.getPool(); + PropertyMapper map = PropertyMapper.get(); + CassandraProperties.Pool properties = this.properties.getPool(); PoolingOptions options = new PoolingOptions(); - if (pool.getIdleTimeout() != null) { - options.setIdleTimeoutSeconds((int) pool.getIdleTimeout().getSeconds()); - } - if (pool.getPoolTimeout() != null) { - options.setPoolTimeoutMillis((int) pool.getPoolTimeout().toMillis()); - } - if (pool.getHeartbeatInterval() != null) { - options.setHeartbeatIntervalSeconds( - (int) pool.getHeartbeatInterval().getSeconds()); - } - options.setMaxQueueSize(pool.getMaxQueueSize()); + map.from(properties::getIdleTimeout).whenNonNull().asInt(Duration::getSeconds) + .to(options::setIdleTimeoutSeconds); + map.from(properties::getPoolTimeout).whenNonNull().asInt(Duration::toMillis) + .to(options::setPoolTimeoutMillis); + map.from(properties::getHeartbeatInterval).whenNonNull() + .asInt(Duration::getSeconds).to(options::setHeartbeatIntervalSeconds); + map.from(properties::getMaxQueueSize).to(options::setMaxQueueSize); return options; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java index 22e8ef3333..936443a433 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java @@ -32,6 +32,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.domain.EntityScanPackages; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.boot.context.properties.bind.Binder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -46,7 +47,6 @@ import org.springframework.data.cassandra.core.convert.CassandraCustomConversion import org.springframework.data.cassandra.core.convert.MappingCassandraConverter; import org.springframework.data.cassandra.core.mapping.CassandraMappingContext; import org.springframework.data.cassandra.core.mapping.SimpleUserTypeResolver; -import org.springframework.util.StringUtils; /** * {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Cassandra support. @@ -92,14 +92,16 @@ public class CassandraDataAutoConfiguration { if (!packages.isEmpty()) { context.setInitialEntitySet(CassandraEntityClassScanner.scan(packages)); } - if (StringUtils.hasText(this.properties.getKeyspaceName())) { - context.setUserTypeResolver(new SimpleUserTypeResolver(this.cluster, - this.properties.getKeyspaceName())); - } + PropertyMapper.get().from(this.properties::getKeyspaceName).whenHasText() + .as(this::createSimpleUserTypeResolver).to(context::setUserTypeResolver); context.setCustomConversions(conversions); return context; } + private SimpleUserTypeResolver createSimpleUserTypeResolver(String keyspaceName) { + return new SimpleUserTypeResolver(this.cluster, keyspaceName); + } + @Bean @ConditionalOnMissingBean public CassandraConverter cassandraConverter(CassandraMappingContext mapping, diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/rest/RepositoryRestProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/rest/RepositoryRestProperties.java index 89bdb4b0f0..f81aabf532 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/rest/RepositoryRestProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/rest/RepositoryRestProperties.java @@ -17,6 +17,7 @@ package org.springframework.boot.autoconfigure.data.rest; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.data.rest.core.config.RepositoryRestConfiguration; import org.springframework.data.rest.core.mapping.RepositoryDetectionStrategy.RepositoryDetectionStrategies; import org.springframework.http.MediaType; @@ -176,40 +177,19 @@ public class RepositoryRestProperties { this.enableEnumTranslation = enableEnumTranslation; } - public void applyTo(RepositoryRestConfiguration configuration) { - if (this.basePath != null) { - configuration.setBasePath(this.basePath); - } - if (this.defaultPageSize != null) { - configuration.setDefaultPageSize(this.defaultPageSize); - } - if (this.maxPageSize != null) { - configuration.setMaxPageSize(this.maxPageSize); - } - if (this.pageParamName != null) { - configuration.setPageParamName(this.pageParamName); - } - if (this.limitParamName != null) { - configuration.setLimitParamName(this.limitParamName); - } - if (this.sortParamName != null) { - configuration.setSortParamName(this.sortParamName); - } - if (this.detectionStrategy != null) { - configuration.setRepositoryDetectionStrategy(this.detectionStrategy); - } - if (this.defaultMediaType != null) { - configuration.setDefaultMediaType(this.defaultMediaType); - } - if (this.returnBodyOnCreate != null) { - configuration.setReturnBodyOnCreate(this.returnBodyOnCreate); - } - if (this.returnBodyOnUpdate != null) { - configuration.setReturnBodyOnUpdate(this.returnBodyOnUpdate); - } - if (this.enableEnumTranslation != null) { - configuration.setEnableEnumTranslation(this.enableEnumTranslation); - } + public void applyTo(RepositoryRestConfiguration rest) { + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + map.from(this::getBasePath).to(rest::setBasePath); + map.from(this::getDefaultPageSize).to(rest::setDefaultPageSize); + map.from(this::getMaxPageSize).to(rest::setMaxPageSize); + map.from(this::getPageParamName).to(rest::setPageParamName); + map.from(this::getLimitParamName).to(rest::setLimitParamName); + map.from(this::getSortParamName).to(rest::setSortParamName); + map.from(this::getDetectionStrategy).to(rest::setRepositoryDetectionStrategy); + map.from(this::getDefaultMediaType).to(rest::setDefaultMediaType); + map.from(this::getReturnBodyOnCreate).to(rest::setReturnBodyOnCreate); + map.from(this::getReturnBodyOnUpdate).to(rest::setReturnBodyOnUpdate); + map.from(this::getEnableEnumTranslation).to(rest::setEnableEnumTranslation); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/jest/JestAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/jest/JestAutoConfiguration.java index 35d1fbe037..1996ca5445 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/jest/JestAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/jest/JestAutoConfiguration.java @@ -16,6 +16,7 @@ package org.springframework.boot.autoconfigure.elasticsearch.jest; +import java.time.Duration; import java.util.List; import com.google.gson.Gson; @@ -29,12 +30,13 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter; 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.elasticsearch.jest.JestProperties.Proxy; import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.Assert; -import org.springframework.util.StringUtils; /** * {@link EnableAutoConfiguration Auto-Configuration} for Jest. @@ -72,27 +74,20 @@ public class JestAutoConfiguration { protected HttpClientConfig createHttpClientConfig() { HttpClientConfig.Builder builder = new HttpClientConfig.Builder( this.properties.getUris()); - if (StringUtils.hasText(this.properties.getUsername())) { - builder.defaultCredentials(this.properties.getUsername(), - this.properties.getPassword()); - } - String proxyHost = this.properties.getProxy().getHost(); - if (StringUtils.hasText(proxyHost)) { - Integer proxyPort = this.properties.getProxy().getPort(); - Assert.notNull(proxyPort, "Proxy port must not be null"); - builder.proxy(new HttpHost(proxyHost, proxyPort)); - } - Gson gson = this.gsonProvider.getIfUnique(); - if (gson != null) { - builder.gson(gson); - } - builder.multiThreaded(this.properties.isMultiThreaded()); - if (this.properties.getConnectionTimeout() != null) { - builder.connTimeout((int) this.properties.getConnectionTimeout().toMillis()); - } - if (this.properties.getReadTimeout() != null) { - builder.readTimeout((int) this.properties.getReadTimeout().toMillis()); - } + PropertyMapper map = PropertyMapper.get(); + map.from(this.properties::getUsername).whenHasText().to((username) -> builder + .defaultCredentials(username, this.properties.getPassword())); + Proxy proxy = this.properties.getProxy(); + map.from(proxy::getHost).whenHasText().to((host) -> { + Assert.notNull(proxy.getPort(), "Proxy port must not be null"); + builder.proxy(new HttpHost(host, proxy.getPort())); + }); + map.from(this.gsonProvider::getIfUnique).whenNonNull().to(builder::gson); + map.from(this.properties::isMultiThreaded).to(builder::multiThreaded); + map.from(this.properties::getConnectionTimeout).whenNonNull() + .asInt(Duration::toMillis).to(builder::connTimeout); + map.from(this.properties::getReadTimeout).whenNonNull().asInt(Duration::toMillis) + .to(builder::readTimeout); customize(builder); return builder.build(); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java index d1c65f8a08..7d3caac78b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration.java @@ -16,6 +16,8 @@ package org.springframework.boot.autoconfigure.jms; +import java.time.Duration; + import javax.jms.ConnectionFactory; import javax.jms.Message; @@ -25,7 +27,10 @@ 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.ConditionalOnSingleCandidate; +import org.springframework.boot.autoconfigure.jms.JmsProperties.DeliveryMode; +import org.springframework.boot.autoconfigure.jms.JmsProperties.Template; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -68,38 +73,31 @@ public class JmsAutoConfiguration { @ConditionalOnMissingBean @ConditionalOnSingleCandidate(ConnectionFactory.class) public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) { - JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory); - jmsTemplate.setPubSubDomain(this.properties.isPubSubDomain()); - DestinationResolver destinationResolver = this.destinationResolver - .getIfUnique(); - if (destinationResolver != null) { - jmsTemplate.setDestinationResolver(destinationResolver); - } - MessageConverter messageConverter = this.messageConverter.getIfUnique(); - if (messageConverter != null) { - jmsTemplate.setMessageConverter(messageConverter); - } - JmsProperties.Template template = this.properties.getTemplate(); - if (template.getDefaultDestination() != null) { - jmsTemplate.setDefaultDestinationName(template.getDefaultDestination()); - } - if (template.getDeliveryDelay() != null) { - jmsTemplate.setDeliveryDelay(template.getDeliveryDelay().toMillis()); - } - jmsTemplate.setExplicitQosEnabled(template.determineQosEnabled()); - if (template.getDeliveryMode() != null) { - jmsTemplate.setDeliveryMode(template.getDeliveryMode().getValue()); - } - if (template.getPriority() != null) { - jmsTemplate.setPriority(template.getPriority()); - } - if (template.getTimeToLive() != null) { - jmsTemplate.setTimeToLive(template.getTimeToLive().toMillis()); - } - if (template.getReceiveTimeout() != null) { - jmsTemplate.setReceiveTimeout(template.getReceiveTimeout().toMillis()); - } - return jmsTemplate; + PropertyMapper map = PropertyMapper.get(); + JmsTemplate template = new JmsTemplate(connectionFactory); + template.setPubSubDomain(this.properties.isPubSubDomain()); + map.from(this.destinationResolver::getIfUnique).whenNonNull() + .to(template::setDestinationResolver); + map.from(this.messageConverter::getIfUnique).whenNonNull() + .to(template::setMessageConverter); + mapTemplateProperties(this.properties.getTemplate(), template); + return template; + } + + private void mapTemplateProperties(Template properties, JmsTemplate template) { + PropertyMapper map = PropertyMapper.get(); + map.from(properties::getDefaultDestination).whenNonNull() + .to(template::setDefaultDestinationName); + map.from(properties::getDeliveryDelay).whenNonNull().as(Duration::toMillis) + .to(template::setDeliveryDelay); + map.from(properties::determineQosEnabled).to(template::setExplicitQosEnabled); + map.from(properties::getDeliveryMode).whenNonNull().as(DeliveryMode::getValue) + .to(template::setDeliveryMode); + map.from(properties::getPriority).whenNonNull().to(template::setPriority); + map.from(properties::getTimeToLive).whenNonNull().as(Duration::toMillis) + .to(template::setTimeToLive); + map.from(properties::getReceiveTimeout).whenNonNull().as(Duration::toMillis) + .to(template::setReceiveTimeout); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/kafka/ConcurrentKafkaListenerContainerFactoryConfigurer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/kafka/ConcurrentKafkaListenerContainerFactoryConfigurer.java index e357d0b858..ca635c0250 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/kafka/ConcurrentKafkaListenerContainerFactoryConfigurer.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/kafka/ConcurrentKafkaListenerContainerFactoryConfigurer.java @@ -16,7 +16,10 @@ package org.springframework.boot.autoconfigure.kafka; +import java.time.Duration; + import org.springframework.boot.autoconfigure.kafka.KafkaProperties.Listener; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; import org.springframework.kafka.core.ConsumerFactory; import org.springframework.kafka.core.KafkaTemplate; @@ -65,41 +68,39 @@ public class ConcurrentKafkaListenerContainerFactoryConfigurer { /** * Configure the specified Kafka listener container factory. The factory can be * further tuned and default settings can be overridden. - * @param listenerContainerFactory the {@link ConcurrentKafkaListenerContainerFactory} - * instance to configure + * @param listenerFactory the {@link ConcurrentKafkaListenerContainerFactory} instance + * to configure * @param consumerFactory the {@link ConsumerFactory} to use */ public void configure( - ConcurrentKafkaListenerContainerFactory listenerContainerFactory, + ConcurrentKafkaListenerContainerFactory listenerFactory, ConsumerFactory consumerFactory) { - listenerContainerFactory.setConsumerFactory(consumerFactory); - if (this.messageConverter != null) { - listenerContainerFactory.setMessageConverter(this.messageConverter); - } - if (this.replyTemplate != null) { - listenerContainerFactory.setReplyTemplate(this.replyTemplate); - } - Listener container = this.properties.getListener(); - ContainerProperties containerProperties = listenerContainerFactory - .getContainerProperties(); - if (container.getAckMode() != null) { - containerProperties.setAckMode(container.getAckMode()); - } - if (container.getAckCount() != null) { - containerProperties.setAckCount(container.getAckCount()); - } - if (container.getAckTime() != null) { - containerProperties.setAckTime(container.getAckTime().toMillis()); - } - if (container.getPollTimeout() != null) { - containerProperties.setPollTimeout(container.getPollTimeout().toMillis()); - } - if (container.getConcurrency() != null) { - listenerContainerFactory.setConcurrency(container.getConcurrency()); - } - if (container.getType() == Listener.Type.BATCH) { - listenerContainerFactory.setBatchListener(true); - } + listenerFactory.setConsumerFactory(consumerFactory); + configureListenerFactory(listenerFactory); + configureContainer(listenerFactory.getContainerProperties()); + } + + private void configureListenerFactory( + ConcurrentKafkaListenerContainerFactory factory) { + PropertyMapper map = PropertyMapper.get(); + Listener properties = this.properties.getListener(); + map.from(properties::getConcurrency).whenNonNull().to(factory::setConcurrency); + map.from(() -> this.messageConverter).whenNonNull() + .to(factory::setMessageConverter); + map.from(() -> this.replyTemplate).whenNonNull().to(factory::setReplyTemplate); + map.from(properties::getType).whenEqualTo(Listener.Type.BATCH) + .toCall(() -> factory.setBatchListener(true)); + } + + private void configureContainer(ContainerProperties container) { + PropertyMapper map = PropertyMapper.get(); + Listener properties = this.properties.getListener(); + map.from(properties::getAckMode).whenNonNull().to(container::setAckMode); + map.from(properties::getAckCount).whenNonNull().to(container::setAckCount); + map.from(properties::getAckTime).whenNonNull().as(Duration::toMillis) + .to(container::setAckTime); + map.from(properties::getPollTimeout).whenNonNull().as(Duration::toMillis) + .to(container::setPollTimeout); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailSenderAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailSenderAutoConfiguration.java index 1417da0f65..afecc9f6a3 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailSenderAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailSenderAutoConfiguration.java @@ -16,6 +16,7 @@ package org.springframework.boot.autoconfigure.mail; +import java.nio.charset.Charset; import java.util.Map; import java.util.Properties; @@ -31,6 +32,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration.MailSenderCondition; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @@ -77,19 +79,16 @@ public class MailSenderAutoConfiguration { } private void applyProperties(JavaMailSenderImpl sender) { - sender.setHost(this.properties.getHost()); - if (this.properties.getPort() != null) { - sender.setPort(this.properties.getPort()); - } - sender.setUsername(this.properties.getUsername()); - sender.setPassword(this.properties.getPassword()); - sender.setProtocol(this.properties.getProtocol()); - if (this.properties.getDefaultEncoding() != null) { - sender.setDefaultEncoding(this.properties.getDefaultEncoding().name()); - } - if (!this.properties.getProperties().isEmpty()) { - sender.setJavaMailProperties(asProperties(this.properties.getProperties())); - } + PropertyMapper map = PropertyMapper.get(); + map.from(this.properties::getHost).to(sender::setHost); + map.from(this.properties::getPort).whenNonNull().to(sender::setPort); + map.from(this.properties::getUsername).to(sender::setUsername); + map.from(this.properties::getPassword).to(sender::setPassword); + map.from(this.properties::getProtocol).to(sender::setProtocol); + map.from(this.properties::getDefaultEncoding).whenNonNull().as(Charset::name) + .to(sender::setDefaultEncoding); + map.from(this.properties::getProperties).whenNot(Map::isEmpty) + .as(this::asProperties).to(sender::setJavaMailProperties); } private Properties asProperties(Map source) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisReactiveSessionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisReactiveSessionConfiguration.java index 076deae232..56ddce4386 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisReactiveSessionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisReactiveSessionConfiguration.java @@ -48,13 +48,10 @@ class RedisReactiveSessionConfiguration { static class SpringBootRedisWebSessionConfiguration extends RedisWebSessionConfiguration { - private SessionProperties sessionProperties; - @Autowired public void customize(SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties) { - this.sessionProperties = sessionProperties; - Duration timeout = this.sessionProperties.getTimeout(); + Duration timeout = sessionProperties.getTimeout(); if (timeout != null) { setMaxInactiveIntervalInSeconds((int) timeout.getSeconds()); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java index 333cbe68e3..e273c04d45 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java @@ -19,7 +19,6 @@ package org.springframework.boot.autoconfigure.thymeleaf; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; -import java.util.List; import javax.annotation.PostConstruct; @@ -48,15 +47,16 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; import org.springframework.boot.autoconfigure.template.TemplateLocation; +import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties.Reactive; import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain; import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; -import org.springframework.http.MediaType; import org.springframework.util.MimeType; import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter; @@ -263,27 +263,34 @@ public class ThymeleafAutoConfiguration { ISpringWebFluxTemplateEngine templateEngine) { ThymeleafReactiveViewResolver resolver = new ThymeleafReactiveViewResolver(); resolver.setTemplateEngine(templateEngine); - resolver.setDefaultCharset(this.properties.getEncoding()); - List mediaTypes = this.properties.getReactive().getMediaTypes(); - if (mediaTypes != null) { - resolver.setSupportedMediaTypes(mediaTypes); - } - resolver.setExcludedViewNames(this.properties.getExcludedViewNames()); - resolver.setViewNames(this.properties.getViewNames()); - if (this.properties.getReactive().getMaxChunkSize() > 0) { - resolver.setResponseMaxChunkSizeBytes( - this.properties.getReactive().getMaxChunkSize()); - } - resolver.setFullModeViewNames( - this.properties.getReactive().getFullModeViewNames()); - resolver.setChunkedModeViewNames( - this.properties.getReactive().getChunkedModeViewNames()); + mapProperties(this.properties, resolver); + mapReactiveProperties(this.properties.getReactive(), resolver); // This resolver acts as a fallback resolver (e.g. like a // InternalResourceViewResolver) so it needs to have low precedence resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 5); return resolver; } + private void mapProperties(ThymeleafProperties properties, + ThymeleafReactiveViewResolver resolver) { + PropertyMapper map = PropertyMapper.get(); + map.from(properties::getEncoding).to(resolver::setDefaultCharset); + resolver.setExcludedViewNames(properties.getExcludedViewNames()); + resolver.setViewNames(properties.getViewNames()); + } + + private void mapReactiveProperties(Reactive properties, + ThymeleafReactiveViewResolver resolver) { + PropertyMapper map = PropertyMapper.get(); + map.from(properties::getMediaTypes).whenNonNull() + .to(resolver::setSupportedMediaTypes); + map.from(properties::getMaxChunkSize).when((size) -> size > 0) + .to(resolver::setResponseMaxChunkSizeBytes); + map.from(properties::getFullModeViewNames).to(resolver::setFullModeViewNames); + map.from(properties::getChunkedModeViewNames) + .to(resolver::setChunkedModeViewNames); + } + } @Configuration diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java index 43b35d5513..7f2591f33f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java @@ -19,9 +19,9 @@ package org.springframework.boot.autoconfigure.web; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.boot.context.properties.bind.convert.DefaultDurationUnit; /** @@ -459,29 +459,23 @@ public class ResourceProperties { } public org.springframework.http.CacheControl toHttpCacheControl() { - org.springframework.http.CacheControl cacheControl = createCacheControl(); - callIfTrue(this.mustRevalidate, cacheControl, - org.springframework.http.CacheControl::mustRevalidate); - callIfTrue(this.noTransform, cacheControl, - org.springframework.http.CacheControl::noTransform); - callIfTrue(this.cachePublic, cacheControl, - org.springframework.http.CacheControl::cachePublic); - callIfTrue(this.cachePrivate, cacheControl, - org.springframework.http.CacheControl::cachePrivate); - callIfTrue(this.proxyRevalidate, cacheControl, - org.springframework.http.CacheControl::proxyRevalidate); - if (this.staleWhileRevalidate != null) { - cacheControl.staleWhileRevalidate( - this.staleWhileRevalidate.getSeconds(), TimeUnit.SECONDS); - } - if (this.staleIfError != null) { - cacheControl.staleIfError(this.staleIfError.getSeconds(), - TimeUnit.SECONDS); - } - if (this.sMaxAge != null) { - cacheControl.sMaxAge(this.sMaxAge.getSeconds(), TimeUnit.SECONDS); - } - return cacheControl; + PropertyMapper map = PropertyMapper.get(); + org.springframework.http.CacheControl control = createCacheControl(); + map.from(this::getMustRevalidate).whenTrue() + .toCall(control::mustRevalidate); + map.from(this::getNoTransform).whenTrue().toCall(control::noTransform); + map.from(this::getCachePublic).whenTrue().toCall(control::cachePublic); + map.from(this::getCachePrivate).whenTrue().toCall(control::cachePrivate); + map.from(this::getProxyRevalidate).whenTrue() + .toCall(control::proxyRevalidate); + map.from(this::getStaleWhileRevalidate).whenNonNull().to( + (duration) -> control.staleWhileRevalidate(duration.getSeconds(), + TimeUnit.SECONDS)); + map.from(this::getStaleIfError).whenNonNull().to((duration) -> control + .staleIfError(duration.getSeconds(), TimeUnit.SECONDS)); + map.from(this::getSMaxAge).whenNonNull().to((duration) -> control + .sMaxAge(duration.getSeconds(), TimeUnit.SECONDS)); + return control; } private org.springframework.http.CacheControl createCacheControl() { @@ -498,12 +492,6 @@ public class ResourceProperties { return org.springframework.http.CacheControl.empty(); } - private void callIfTrue(Boolean property, T instance, Consumer call) { - if (Boolean.TRUE.equals(property)) { - call.accept(instance); - } - } - } }