From ad8753923a4d9478b5a1393d95eaacc3cb2d8082 Mon Sep 17 00:00:00 2001 From: Vedran Pavic Date: Mon, 26 Sep 2022 10:07:29 +0200 Subject: [PATCH 1/2] Rework Spring Session auto-configuration to use customizers This commit reworks Spring Session auto-configuration to avoid extending Spring Session's configuration classes. Instead, those configuration classes are now imported and customizations are applied using dedicated (Reactive)SessionRepositoryCustomizer beans. See gh-32554 --- .../HazelcastSessionConfiguration.java | 34 +++++----- .../session/JdbcSessionConfiguration.java | 32 +++++----- .../MongoReactiveSessionConfiguration.java | 29 +++++---- .../session/MongoSessionConfiguration.java | 29 +++++---- .../RedisReactiveSessionConfiguration.java | 31 +++++---- .../session/RedisSessionConfiguration.java | 63 ++++++++++--------- .../SessionAutoConfigurationJdbcTests.java | 25 +++----- .../SessionAutoConfigurationRedisTests.java | 5 +- 8 files changed, 133 insertions(+), 115 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/HazelcastSessionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/HazelcastSessionConfiguration.java index 48e604bd7d..6e6e9dd78f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/HazelcastSessionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/HazelcastSessionConfiguration.java @@ -16,18 +16,19 @@ package org.springframework.boot.autoconfigure.session; -import java.time.Duration; - import com.hazelcast.core.HazelcastInstance; -import org.springframework.beans.factory.annotation.Autowired; 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.web.ServerProperties; 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; import org.springframework.session.SessionRepository; +import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository; import org.springframework.session.hazelcast.config.annotation.web.http.HazelcastHttpSessionConfiguration; @@ -47,19 +48,22 @@ import org.springframework.session.hazelcast.config.annotation.web.http.Hazelcas class HazelcastSessionConfiguration { @Configuration(proxyBeanMethods = false) - public static class SpringBootHazelcastHttpSessionConfiguration extends HazelcastHttpSessionConfiguration { + @Import(HazelcastHttpSessionConfiguration.class) + static class SpringBootHazelcastHttpSessionConfiguration { - @Autowired - public void customize(SessionProperties sessionProperties, - HazelcastSessionProperties hazelcastSessionProperties, ServerProperties serverProperties) { - Duration timeout = sessionProperties - .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout()); - if (timeout != null) { - setMaxInactiveIntervalInSeconds((int) timeout.getSeconds()); - } - setSessionMapName(hazelcastSessionProperties.getMapName()); - setFlushMode(hazelcastSessionProperties.getFlushMode()); - setSaveMode(hazelcastSessionProperties.getSaveMode()); + @Bean + SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( + SessionProperties sessionProperties, HazelcastSessionProperties hazelcastSessionProperties, + ServerProperties serverProperties) { + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + return (sessionRepository) -> { + map.from(sessionProperties + .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) + .to((timeout) -> sessionRepository.setDefaultMaxInactiveInterval((int) timeout.getSeconds())); + map.from(hazelcastSessionProperties::getMapName).to(sessionRepository::setSessionMapName); + map.from(hazelcastSessionProperties::getFlushMode).to(sessionRepository::setFlushMode); + map.from(hazelcastSessionProperties::getSaveMode).to(sessionRepository::setSaveMode); + }; } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java index a34505193e..e531514411 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java @@ -16,18 +16,16 @@ package org.springframework.boot.autoconfigure.session; -import java.time.Duration; - import javax.sql.DataSource; import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.annotation.Autowired; 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.sql.init.OnDatabaseInitializationCondition; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; @@ -35,6 +33,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.session.SessionRepository; +import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.jdbc.JdbcIndexedSessionRepository; import org.springframework.session.jdbc.config.annotation.SpringSessionDataSource; import org.springframework.session.jdbc.config.annotation.web.http.JdbcHttpSessionConfiguration; @@ -65,20 +64,23 @@ class JdbcSessionConfiguration { } @Configuration(proxyBeanMethods = false) - static class SpringBootJdbcHttpSessionConfiguration extends JdbcHttpSessionConfiguration { + @Import(JdbcHttpSessionConfiguration.class) + static class SpringBootJdbcHttpSessionConfiguration { - @Autowired - void customize(SessionProperties sessionProperties, JdbcSessionProperties jdbcSessionProperties, + @Bean + SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( + SessionProperties sessionProperties, JdbcSessionProperties jdbcSessionProperties, ServerProperties serverProperties) { - Duration timeout = sessionProperties - .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout()); - if (timeout != null) { - setMaxInactiveIntervalInSeconds((int) timeout.getSeconds()); - } - setTableName(jdbcSessionProperties.getTableName()); - setCleanupCron(jdbcSessionProperties.getCleanupCron()); - setFlushMode(jdbcSessionProperties.getFlushMode()); - setSaveMode(jdbcSessionProperties.getSaveMode()); + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + return (sessionRepository) -> { + map.from(sessionProperties + .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) + .to((timeout) -> sessionRepository.setDefaultMaxInactiveInterval((int) timeout.getSeconds())); + map.from(jdbcSessionProperties::getTableName).to(sessionRepository::setTableName); + map.from(jdbcSessionProperties::getFlushMode).to(sessionRepository::setFlushMode); + map.from(jdbcSessionProperties::getSaveMode).to(sessionRepository::setSaveMode); + map.from(jdbcSessionProperties::getCleanupCron).to(sessionRepository::setCleanupCron); + }; } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoReactiveSessionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoReactiveSessionConfiguration.java index 52297472fe..6aabfbda9d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoReactiveSessionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoReactiveSessionConfiguration.java @@ -16,17 +16,18 @@ package org.springframework.boot.autoconfigure.session; -import java.time.Duration; - -import org.springframework.beans.factory.annotation.Autowired; 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.web.ServerProperties; 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; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.session.ReactiveSessionRepository; +import org.springframework.session.config.ReactiveSessionRepositoryCustomizer; import org.springframework.session.data.mongo.ReactiveMongoSessionRepository; import org.springframework.session.data.mongo.config.annotation.web.reactive.ReactiveMongoWebSessionConfiguration; @@ -35,6 +36,7 @@ import org.springframework.session.data.mongo.config.annotation.web.reactive.Rea * * @author Andy Wilkinson * @author Weix Sun + * @author Vedran Pavic */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass({ ReactiveMongoOperations.class, ReactiveMongoSessionRepository.class }) @@ -44,17 +46,20 @@ import org.springframework.session.data.mongo.config.annotation.web.reactive.Rea class MongoReactiveSessionConfiguration { @Configuration(proxyBeanMethods = false) - static class SpringBootReactiveMongoWebSessionConfiguration extends ReactiveMongoWebSessionConfiguration { + @Import(ReactiveMongoWebSessionConfiguration.class) + static class SpringBootMongoWebSessionConfiguration { - @Autowired - void customize(SessionProperties sessionProperties, MongoSessionProperties mongoSessionProperties, + @Bean + ReactiveSessionRepositoryCustomizer springBootSessionRepositoryCustomizer( + SessionProperties sessionProperties, MongoSessionProperties mongoSessionProperties, ServerProperties serverProperties) { - Duration timeout = sessionProperties - .determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout()); - if (timeout != null) { - setMaxInactiveIntervalInSeconds((int) timeout.getSeconds()); - } - setCollectionName(mongoSessionProperties.getCollectionName()); + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + return (sessionRepository) -> { + map.from(sessionProperties + .determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout())) + .to((timeout) -> sessionRepository.setMaxInactiveIntervalInSeconds((int) timeout.getSeconds())); + map.from(mongoSessionProperties::getCollectionName).to(sessionRepository::setCollectionName); + }; } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoSessionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoSessionConfiguration.java index c18ec78989..85a9c5865b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoSessionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoSessionConfiguration.java @@ -16,17 +16,18 @@ package org.springframework.boot.autoconfigure.session; -import java.time.Duration; - -import org.springframework.beans.factory.annotation.Autowired; 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.web.ServerProperties; 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; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.session.SessionRepository; +import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.data.mongo.MongoIndexedSessionRepository; import org.springframework.session.data.mongo.config.annotation.web.http.MongoHttpSessionConfiguration; @@ -35,6 +36,7 @@ import org.springframework.session.data.mongo.config.annotation.web.http.MongoHt * * @author EddĂș MelĂ©ndez * @author Stephane Nicoll + * @author Vedran Pavic */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass({ MongoOperations.class, MongoIndexedSessionRepository.class }) @@ -44,17 +46,20 @@ import org.springframework.session.data.mongo.config.annotation.web.http.MongoHt class MongoSessionConfiguration { @Configuration(proxyBeanMethods = false) - public static class SpringBootMongoHttpSessionConfiguration extends MongoHttpSessionConfiguration { + @Import(MongoHttpSessionConfiguration.class) + static class SpringBootMongoHttpSessionConfiguration { - @Autowired - public void customize(SessionProperties sessionProperties, MongoSessionProperties mongoSessionProperties, + @Bean + SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( + SessionProperties sessionProperties, MongoSessionProperties mongoSessionProperties, ServerProperties serverProperties) { - Duration timeout = sessionProperties - .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout()); - if (timeout != null) { - setMaxInactiveIntervalInSeconds((int) timeout.getSeconds()); - } - setCollectionName(mongoSessionProperties.getCollectionName()); + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + return (sessionRepository) -> { + map.from(sessionProperties + .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) + .to((timeout) -> sessionRepository.setMaxInactiveIntervalInSeconds((int) timeout.getSeconds())); + map.from(mongoSessionProperties::getCollectionName).to(sessionRepository::setCollectionName); + }; } } 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 0a55481bf8..a4b41ccef0 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 @@ -16,17 +16,18 @@ package org.springframework.boot.autoconfigure.session; -import java.time.Duration; - -import org.springframework.beans.factory.annotation.Autowired; 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.web.ServerProperties; 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; import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory; import org.springframework.session.ReactiveSessionRepository; +import org.springframework.session.config.ReactiveSessionRepositoryCustomizer; import org.springframework.session.data.redis.ReactiveRedisSessionRepository; import org.springframework.session.data.redis.config.annotation.web.server.RedisWebSessionConfiguration; @@ -35,6 +36,7 @@ import org.springframework.session.data.redis.config.annotation.web.server.Redis * * @author Andy Wilkinson * @author Weix Sun + * @author Vedran Pavic */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass({ ReactiveRedisConnectionFactory.class, ReactiveRedisSessionRepository.class }) @@ -44,18 +46,21 @@ import org.springframework.session.data.redis.config.annotation.web.server.Redis class RedisReactiveSessionConfiguration { @Configuration(proxyBeanMethods = false) - static class SpringBootRedisWebSessionConfiguration extends RedisWebSessionConfiguration { + @Import(RedisWebSessionConfiguration.class) + static class SpringBootRedisWebSessionConfiguration { - @Autowired - void customize(SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties, + @Bean + ReactiveSessionRepositoryCustomizer springBootSessionRepositoryCustomizer( + SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties, ServerProperties serverProperties) { - Duration timeout = sessionProperties - .determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout()); - if (timeout != null) { - setMaxInactiveIntervalInSeconds((int) timeout.getSeconds()); - } - setRedisNamespace(redisSessionProperties.getNamespace()); - setSaveMode(redisSessionProperties.getSaveMode()); + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + return (sessionRepository) -> { + map.from(sessionProperties + .determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout())) + .to((timeout) -> sessionRepository.setDefaultMaxInactiveInterval((int) timeout.getSeconds())); + map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace); + map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode); + }; } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionConfiguration.java index 6c47e9c3bd..8d1aee67dd 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionConfiguration.java @@ -16,22 +16,23 @@ package org.springframework.boot.autoconfigure.session; -import java.time.Duration; - -import org.springframework.beans.factory.annotation.Autowired; 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.web.ServerProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.session.SessionRepository; +import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.data.redis.RedisIndexedSessionRepository; +import org.springframework.session.data.redis.RedisSessionRepository; import org.springframework.session.data.redis.config.ConfigureNotifyKeyspaceEventsAction; import org.springframework.session.data.redis.config.ConfigureRedisAction; import org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration; @@ -59,10 +60,12 @@ class RedisSessionConfiguration { static class DefaultRedisSessionConfiguration { @Configuration(proxyBeanMethods = false) - static class SpringBootRedisHttpSessionConfiguration extends RedisHttpSessionConfiguration { + @Import(RedisHttpSessionConfiguration.class) + static class SpringBootRedisHttpSessionConfiguration { - @Autowired - void customize(SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties, + @Bean + SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( + SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties, ServerProperties serverProperties) { String cleanupCron = redisSessionProperties.getCleanupCron(); if (cleanupCron != null) { @@ -71,14 +74,15 @@ class RedisSessionConfiguration { "Cron-based cleanup is only supported when spring.session.redis.repository-type is set to " + "indexed."); } - Duration timeout = sessionProperties - .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout()); - if (timeout != null) { - setMaxInactiveIntervalInSeconds((int) timeout.getSeconds()); - } - setRedisNamespace(redisSessionProperties.getNamespace()); - setFlushMode(redisSessionProperties.getFlushMode()); - setSaveMode(redisSessionProperties.getSaveMode()); + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + return (sessionRepository) -> { + map.from(sessionProperties + .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) + .to(sessionRepository::setDefaultMaxInactiveInterval); + map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace); + map.from(redisSessionProperties::getFlushMode).to(sessionRepository::setFlushMode); + map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode); + }; } } @@ -99,23 +103,24 @@ class RedisSessionConfiguration { } @Configuration(proxyBeanMethods = false) - static class SpringBootRedisIndexedHttpSessionConfiguration extends RedisIndexedHttpSessionConfiguration { + @Import(RedisIndexedHttpSessionConfiguration.class) + static class SpringBootRedisIndexedHttpSessionConfiguration { - private static final String DEFAULT_CLEANUP_CRON = "0 * * * * *"; - - @Autowired - void customize(SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties, + @Bean + SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( + SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties, ServerProperties serverProperties) { - Duration timeout = sessionProperties - .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout()); - if (timeout != null) { - setMaxInactiveIntervalInSeconds((int) timeout.getSeconds()); - } - setRedisNamespace(redisSessionProperties.getNamespace()); - setFlushMode(redisSessionProperties.getFlushMode()); - setSaveMode(redisSessionProperties.getSaveMode()); - String cleanupCron = redisSessionProperties.getCleanupCron(); - setCleanupCron((cleanupCron != null) ? cleanupCron : DEFAULT_CLEANUP_CRON); + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + return (sessionRepository) -> { + map.from(sessionProperties + .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) + .to((timeout) -> sessionRepository + .setDefaultMaxInactiveInterval((int) timeout.getSeconds())); + map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace); + map.from(redisSessionProperties::getFlushMode).to(sessionRepository::setFlushMode); + map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode); + map.from(redisSessionProperties::getCleanupCron).to(sessionRepository::setCleanupCron); + }; } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationJdbcTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationJdbcTests.java index bbcd80d2d7..5e2a5781a7 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationJdbcTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationJdbcTests.java @@ -28,7 +28,6 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration; import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration; -import org.springframework.boot.autoconfigure.session.JdbcSessionConfiguration.SpringBootJdbcHttpSessionConfiguration; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer; import org.springframework.boot.sql.init.DatabaseInitializationMode; @@ -86,12 +85,10 @@ class SessionAutoConfigurationJdbcTests extends AbstractSessionAutoConfiguration assertThat(repository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval", (int) new ServerProperties().getServlet().getSession().getTimeout().getSeconds()); assertThat(repository).hasFieldOrPropertyWithValue("tableName", "SPRING_SESSION"); + assertThat(repository).hasFieldOrPropertyWithValue("cleanupCron", "0 * * * * *"); assertThat(context.getBean(JdbcSessionProperties.class).getInitializeSchema()) .isEqualTo(DatabaseInitializationMode.EMBEDDED); assertThat(context.getBean(JdbcOperations.class).queryForList("select * from SPRING_SESSION")).isEmpty(); - SpringBootJdbcHttpSessionConfiguration configuration = context - .getBean(SpringBootJdbcHttpSessionConfiguration.class); - assertThat(configuration).hasFieldOrPropertyWithValue("cleanupCron", "0 * * * * *"); } @Test @@ -142,29 +139,27 @@ class SessionAutoConfigurationJdbcTests extends AbstractSessionAutoConfiguration void customCleanupCron() { this.contextRunner.withPropertyValues("spring.session.jdbc.cleanup-cron=0 0 12 * * *").run((context) -> { assertThat(context.getBean(JdbcSessionProperties.class).getCleanupCron()).isEqualTo("0 0 12 * * *"); - SpringBootJdbcHttpSessionConfiguration configuration = context - .getBean(SpringBootJdbcHttpSessionConfiguration.class); - assertThat(configuration).hasFieldOrPropertyWithValue("cleanupCron", "0 0 12 * * *"); + JdbcIndexedSessionRepository repository = validateSessionRepository(context, + JdbcIndexedSessionRepository.class); + assertThat(repository).hasFieldOrPropertyWithValue("cleanupCron", "0 0 12 * * *"); }); } @Test void customFlushMode() { this.contextRunner.withPropertyValues("spring.session.jdbc.flush-mode=immediate").run((context) -> { - assertThat(context.getBean(JdbcSessionProperties.class).getFlushMode()).isEqualTo(FlushMode.IMMEDIATE); - SpringBootJdbcHttpSessionConfiguration configuration = context - .getBean(SpringBootJdbcHttpSessionConfiguration.class); - assertThat(configuration).hasFieldOrPropertyWithValue("flushMode", FlushMode.IMMEDIATE); + JdbcIndexedSessionRepository repository = validateSessionRepository(context, + JdbcIndexedSessionRepository.class); + assertThat(repository).hasFieldOrPropertyWithValue("flushMode", FlushMode.IMMEDIATE); }); } @Test void customSaveMode() { this.contextRunner.withPropertyValues("spring.session.jdbc.save-mode=on-get-attribute").run((context) -> { - assertThat(context.getBean(JdbcSessionProperties.class).getSaveMode()).isEqualTo(SaveMode.ON_GET_ATTRIBUTE); - SpringBootJdbcHttpSessionConfiguration configuration = context - .getBean(SpringBootJdbcHttpSessionConfiguration.class); - assertThat(configuration).hasFieldOrPropertyWithValue("saveMode", SaveMode.ON_GET_ATTRIBUTE); + JdbcIndexedSessionRepository repository = validateSessionRepository(context, + JdbcIndexedSessionRepository.class); + assertThat(repository).hasFieldOrPropertyWithValue("saveMode", SaveMode.ON_GET_ATTRIBUTE); }); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationRedisTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationRedisTests.java index f27fec99e5..83747008e6 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationRedisTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationRedisTests.java @@ -25,7 +25,6 @@ import org.testcontainers.junit.jupiter.Testcontainers; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; -import org.springframework.boot.autoconfigure.session.RedisSessionConfiguration.IndexedRedisSessionConfiguration.SpringBootRedisIndexedHttpSessionConfiguration; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException; import org.springframework.boot.test.context.FilteredClassLoader; @@ -191,9 +190,7 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio assertThat(repository).hasFieldOrPropertyWithValue("namespace", keyNamespace); assertThat(repository).hasFieldOrPropertyWithValue("flushMode", flushMode); assertThat(repository).hasFieldOrPropertyWithValue("saveMode", saveMode); - SpringBootRedisIndexedHttpSessionConfiguration configuration = context - .getBean(SpringBootRedisIndexedHttpSessionConfiguration.class); - assertThat(configuration).hasFieldOrPropertyWithValue("cleanupCron", cleanupCron); + assertThat(repository).hasFieldOrPropertyWithValue("cleanupCron", cleanupCron); }; } From 7e47d3bbd6aadbcf38a0f84b993f3c35f56a2c76 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 6 Oct 2022 20:59:59 +0100 Subject: [PATCH 2/2] Polish "Rework Spring Session auto-configuration to use customizers" See gh-32554 --- .../HazelcastSessionConfiguration.java | 32 +++----- .../session/JdbcSessionConfiguration.java | 34 ++++---- .../MongoReactiveSessionConfiguration.java | 28 +++---- .../session/MongoSessionConfiguration.java | 28 +++---- .../RedisReactiveSessionConfiguration.java | 30 +++---- .../session/RedisSessionConfiguration.java | 80 ++++++++----------- 6 files changed, 95 insertions(+), 137 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/HazelcastSessionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/HazelcastSessionConfiguration.java index 6e6e9dd78f..c196f4f52c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/HazelcastSessionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/HazelcastSessionConfiguration.java @@ -45,27 +45,21 @@ import org.springframework.session.hazelcast.config.annotation.web.http.Hazelcas @ConditionalOnMissingBean(SessionRepository.class) @ConditionalOnBean(HazelcastInstance.class) @EnableConfigurationProperties(HazelcastSessionProperties.class) +@Import(HazelcastHttpSessionConfiguration.class) class HazelcastSessionConfiguration { - @Configuration(proxyBeanMethods = false) - @Import(HazelcastHttpSessionConfiguration.class) - static class SpringBootHazelcastHttpSessionConfiguration { - - @Bean - SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( - SessionProperties sessionProperties, HazelcastSessionProperties hazelcastSessionProperties, - ServerProperties serverProperties) { - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - return (sessionRepository) -> { - map.from(sessionProperties - .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) - .to((timeout) -> sessionRepository.setDefaultMaxInactiveInterval((int) timeout.getSeconds())); - map.from(hazelcastSessionProperties::getMapName).to(sessionRepository::setSessionMapName); - map.from(hazelcastSessionProperties::getFlushMode).to(sessionRepository::setFlushMode); - map.from(hazelcastSessionProperties::getSaveMode).to(sessionRepository::setSaveMode); - }; - } - + @Bean + SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( + SessionProperties sessionProperties, HazelcastSessionProperties hazelcastSessionProperties, + ServerProperties serverProperties) { + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + return (sessionRepository) -> { + map.from(sessionProperties.determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) + .to((timeout) -> sessionRepository.setDefaultMaxInactiveInterval((int) timeout.getSeconds())); + map.from(hazelcastSessionProperties::getMapName).to(sessionRepository::setSessionMapName); + map.from(hazelcastSessionProperties::getFlushMode).to(sessionRepository::setFlushMode); + map.from(hazelcastSessionProperties::getSaveMode).to(sessionRepository::setSaveMode); + }; } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java index e531514411..3253f38b59 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java @@ -50,7 +50,7 @@ import org.springframework.session.jdbc.config.annotation.web.http.JdbcHttpSessi @ConditionalOnMissingBean(SessionRepository.class) @ConditionalOnBean(DataSource.class) @EnableConfigurationProperties(JdbcSessionProperties.class) -@Import(DatabaseInitializationDependencyConfigurer.class) +@Import({ DatabaseInitializationDependencyConfigurer.class, JdbcHttpSessionConfiguration.class }) class JdbcSessionConfiguration { @Bean @@ -63,25 +63,19 @@ class JdbcSessionConfiguration { return new JdbcSessionDataSourceScriptDatabaseInitializer(dataSourceToInitialize, properties); } - @Configuration(proxyBeanMethods = false) - @Import(JdbcHttpSessionConfiguration.class) - static class SpringBootJdbcHttpSessionConfiguration { - - @Bean - SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( - SessionProperties sessionProperties, JdbcSessionProperties jdbcSessionProperties, - ServerProperties serverProperties) { - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - return (sessionRepository) -> { - map.from(sessionProperties - .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) - .to((timeout) -> sessionRepository.setDefaultMaxInactiveInterval((int) timeout.getSeconds())); - map.from(jdbcSessionProperties::getTableName).to(sessionRepository::setTableName); - map.from(jdbcSessionProperties::getFlushMode).to(sessionRepository::setFlushMode); - map.from(jdbcSessionProperties::getSaveMode).to(sessionRepository::setSaveMode); - map.from(jdbcSessionProperties::getCleanupCron).to(sessionRepository::setCleanupCron); - }; - } + @Bean + SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( + SessionProperties sessionProperties, JdbcSessionProperties jdbcSessionProperties, + ServerProperties serverProperties) { + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + return (sessionRepository) -> { + map.from(sessionProperties.determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) + .to((timeout) -> sessionRepository.setDefaultMaxInactiveInterval((int) timeout.getSeconds())); + map.from(jdbcSessionProperties::getTableName).to(sessionRepository::setTableName); + map.from(jdbcSessionProperties::getFlushMode).to(sessionRepository::setFlushMode); + map.from(jdbcSessionProperties::getSaveMode).to(sessionRepository::setSaveMode); + map.from(jdbcSessionProperties::getCleanupCron).to(sessionRepository::setCleanupCron); + }; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoReactiveSessionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoReactiveSessionConfiguration.java index 6aabfbda9d..241d88a290 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoReactiveSessionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoReactiveSessionConfiguration.java @@ -43,25 +43,19 @@ import org.springframework.session.data.mongo.config.annotation.web.reactive.Rea @ConditionalOnMissingBean(ReactiveSessionRepository.class) @ConditionalOnBean(ReactiveMongoOperations.class) @EnableConfigurationProperties(MongoSessionProperties.class) +@Import(ReactiveMongoWebSessionConfiguration.class) class MongoReactiveSessionConfiguration { - @Configuration(proxyBeanMethods = false) - @Import(ReactiveMongoWebSessionConfiguration.class) - static class SpringBootMongoWebSessionConfiguration { - - @Bean - ReactiveSessionRepositoryCustomizer springBootSessionRepositoryCustomizer( - SessionProperties sessionProperties, MongoSessionProperties mongoSessionProperties, - ServerProperties serverProperties) { - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - return (sessionRepository) -> { - map.from(sessionProperties - .determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout())) - .to((timeout) -> sessionRepository.setMaxInactiveIntervalInSeconds((int) timeout.getSeconds())); - map.from(mongoSessionProperties::getCollectionName).to(sessionRepository::setCollectionName); - }; - } - + @Bean + ReactiveSessionRepositoryCustomizer springBootSessionRepositoryCustomizer( + SessionProperties sessionProperties, MongoSessionProperties mongoSessionProperties, + ServerProperties serverProperties) { + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + return (sessionRepository) -> { + map.from(sessionProperties.determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout())) + .to((timeout) -> sessionRepository.setMaxInactiveIntervalInSeconds((int) timeout.getSeconds())); + map.from(mongoSessionProperties::getCollectionName).to(sessionRepository::setCollectionName); + }; } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoSessionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoSessionConfiguration.java index 85a9c5865b..e7426f19b5 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoSessionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoSessionConfiguration.java @@ -43,25 +43,19 @@ import org.springframework.session.data.mongo.config.annotation.web.http.MongoHt @ConditionalOnMissingBean(SessionRepository.class) @ConditionalOnBean(MongoOperations.class) @EnableConfigurationProperties(MongoSessionProperties.class) +@Import(MongoHttpSessionConfiguration.class) class MongoSessionConfiguration { - @Configuration(proxyBeanMethods = false) - @Import(MongoHttpSessionConfiguration.class) - static class SpringBootMongoHttpSessionConfiguration { - - @Bean - SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( - SessionProperties sessionProperties, MongoSessionProperties mongoSessionProperties, - ServerProperties serverProperties) { - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - return (sessionRepository) -> { - map.from(sessionProperties - .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) - .to((timeout) -> sessionRepository.setMaxInactiveIntervalInSeconds((int) timeout.getSeconds())); - map.from(mongoSessionProperties::getCollectionName).to(sessionRepository::setCollectionName); - }; - } - + @Bean + SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( + SessionProperties sessionProperties, MongoSessionProperties mongoSessionProperties, + ServerProperties serverProperties) { + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + return (sessionRepository) -> { + map.from(sessionProperties.determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) + .to((timeout) -> sessionRepository.setMaxInactiveIntervalInSeconds((int) timeout.getSeconds())); + map.from(mongoSessionProperties::getCollectionName).to(sessionRepository::setCollectionName); + }; } } 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 a4b41ccef0..b0063c13a8 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 @@ -43,26 +43,20 @@ import org.springframework.session.data.redis.config.annotation.web.server.Redis @ConditionalOnMissingBean(ReactiveSessionRepository.class) @ConditionalOnBean(ReactiveRedisConnectionFactory.class) @EnableConfigurationProperties(RedisSessionProperties.class) +@Import(RedisWebSessionConfiguration.class) class RedisReactiveSessionConfiguration { - @Configuration(proxyBeanMethods = false) - @Import(RedisWebSessionConfiguration.class) - static class SpringBootRedisWebSessionConfiguration { - - @Bean - ReactiveSessionRepositoryCustomizer springBootSessionRepositoryCustomizer( - SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties, - ServerProperties serverProperties) { - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - return (sessionRepository) -> { - map.from(sessionProperties - .determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout())) - .to((timeout) -> sessionRepository.setDefaultMaxInactiveInterval((int) timeout.getSeconds())); - map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace); - map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode); - }; - } - + @Bean + ReactiveSessionRepositoryCustomizer springBootSessionRepositoryCustomizer( + SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties, + ServerProperties serverProperties) { + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + return (sessionRepository) -> { + map.from(sessionProperties.determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout())) + .to((timeout) -> sessionRepository.setDefaultMaxInactiveInterval((int) timeout.getSeconds())); + map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace); + map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode); + }; } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionConfiguration.java index 8d1aee67dd..929f0ea1cc 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionConfiguration.java @@ -57,40 +57,35 @@ class RedisSessionConfiguration { @Configuration(proxyBeanMethods = false) @ConditionalOnProperty(prefix = "spring.session.redis", name = "repository-type", havingValue = "default", matchIfMissing = true) + @Import(RedisHttpSessionConfiguration.class) static class DefaultRedisSessionConfiguration { - @Configuration(proxyBeanMethods = false) - @Import(RedisHttpSessionConfiguration.class) - static class SpringBootRedisHttpSessionConfiguration { - - @Bean - SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( - SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties, - ServerProperties serverProperties) { - String cleanupCron = redisSessionProperties.getCleanupCron(); - if (cleanupCron != null) { - throw new InvalidConfigurationPropertyValueException("spring.session.redis.cleanup-cron", - cleanupCron, - "Cron-based cleanup is only supported when spring.session.redis.repository-type is set to " - + "indexed."); - } - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - return (sessionRepository) -> { - map.from(sessionProperties - .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) - .to(sessionRepository::setDefaultMaxInactiveInterval); - map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace); - map.from(redisSessionProperties::getFlushMode).to(sessionRepository::setFlushMode); - map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode); - }; + @Bean + SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( + SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties, + ServerProperties serverProperties) { + String cleanupCron = redisSessionProperties.getCleanupCron(); + if (cleanupCron != null) { + throw new InvalidConfigurationPropertyValueException("spring.session.redis.cleanup-cron", cleanupCron, + "Cron-based cleanup is only supported when spring.session.redis.repository-type is set to " + + "indexed."); } - + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + return (sessionRepository) -> { + map.from(sessionProperties + .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) + .to(sessionRepository::setDefaultMaxInactiveInterval); + map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace); + map.from(redisSessionProperties::getFlushMode).to(sessionRepository::setFlushMode); + map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode); + }; } } @Configuration(proxyBeanMethods = false) @ConditionalOnProperty(prefix = "spring.session.redis", name = "repository-type", havingValue = "indexed") + @Import(RedisIndexedHttpSessionConfiguration.class) static class IndexedRedisSessionConfiguration { @Bean @@ -102,27 +97,20 @@ class RedisSessionConfiguration { }; } - @Configuration(proxyBeanMethods = false) - @Import(RedisIndexedHttpSessionConfiguration.class) - static class SpringBootRedisIndexedHttpSessionConfiguration { - - @Bean - SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( - SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties, - ServerProperties serverProperties) { - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - return (sessionRepository) -> { - map.from(sessionProperties - .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) - .to((timeout) -> sessionRepository - .setDefaultMaxInactiveInterval((int) timeout.getSeconds())); - map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace); - map.from(redisSessionProperties::getFlushMode).to(sessionRepository::setFlushMode); - map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode); - map.from(redisSessionProperties::getCleanupCron).to(sessionRepository::setCleanupCron); - }; - } - + @Bean + SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( + SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties, + ServerProperties serverProperties) { + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); + return (sessionRepository) -> { + map.from(sessionProperties + .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) + .to((timeout) -> sessionRepository.setDefaultMaxInactiveInterval((int) timeout.getSeconds())); + map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace); + map.from(redisSessionProperties::getFlushMode).to(sessionRepository::setFlushMode); + map.from(redisSessionProperties::getSaveMode).to(sessionRepository::setSaveMode); + map.from(redisSessionProperties::getCleanupCron).to(sessionRepository::setCleanupCron); + }; } }