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 ed568e8b83..4a3432467c 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 @@ -27,6 +27,8 @@ 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.core.Ordered; +import org.springframework.core.annotation.Order; import org.springframework.session.SessionRepository; import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository; @@ -49,6 +51,7 @@ import org.springframework.session.hazelcast.config.annotation.web.http.Hazelcas class HazelcastSessionConfiguration { @Bean + @Order(Ordered.HIGHEST_PRECEDENCE) SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( SessionProperties sessionProperties, HazelcastSessionProperties hazelcastSessionProperties, ServerProperties serverProperties) { 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 97d7c6fa9a..97910540f9 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 @@ -25,6 +25,8 @@ 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.core.Ordered; +import org.springframework.core.annotation.Order; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.session.SessionRepository; import org.springframework.session.config.SessionRepositoryCustomizer; @@ -47,6 +49,7 @@ import org.springframework.session.data.mongo.config.annotation.web.http.MongoHt class MongoSessionConfiguration { @Bean + @Order(Ordered.HIGHEST_PRECEDENCE) SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( SessionProperties sessionProperties, MongoSessionProperties mongoSessionProperties, ServerProperties serverProperties) { 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 fefd83f552..71faf77987 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 @@ -27,6 +27,8 @@ import org.springframework.boot.context.properties.source.InvalidConfigurationPr import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.session.SessionRepository; @@ -61,6 +63,7 @@ class RedisSessionConfiguration { static class DefaultRedisSessionConfiguration { @Bean + @Order(Ordered.HIGHEST_PRECEDENCE) SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties, ServerProperties serverProperties) { @@ -98,6 +101,7 @@ class RedisSessionConfiguration { } @Bean + @Order(Ordered.HIGHEST_PRECEDENCE) SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties, ServerProperties serverProperties) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationHazelcastTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationHazelcastTests.java index 556a38f8cc..6ee21e1606 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationHazelcastTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationHazelcastTests.java @@ -31,6 +31,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.session.FlushMode; import org.springframework.session.SaveMode; +import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.data.mongo.MongoIndexedSessionRepository; import org.springframework.session.data.redis.RedisIndexedSessionRepository; import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository; @@ -112,6 +113,17 @@ class SessionAutoConfigurationHazelcastTests extends AbstractSessionAutoConfigur }); } + @Test + void whenTheUserDefinesTheirOwnSessionRepositoryCustomizerThenDefaultConfigurationIsOverwritten() { + this.contextRunner.withUserConfiguration(CustomizerConfiguration.class) + .withPropertyValues("spring.session.hazelcast.save-mode=on-get-attribute") + .run((context) -> { + HazelcastIndexedSessionRepository repository = validateSessionRepository(context, + HazelcastIndexedSessionRepository.class); + assertThat(repository).hasFieldOrPropertyWithValue("saveMode", SaveMode.ALWAYS); + }); + } + @Configuration(proxyBeanMethods = false) static class HazelcastConfiguration { @@ -127,4 +139,14 @@ class SessionAutoConfigurationHazelcastTests extends AbstractSessionAutoConfigur } + @Configuration(proxyBeanMethods = false) + static class CustomizerConfiguration { + + @Bean + SessionRepositoryCustomizer sessionRepositoryCustomizer() { + return (repository) -> repository.setSaveMode(SaveMode.ALWAYS); + } + + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationMongoTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationMongoTests.java index 6af94eb574..ec221f78d6 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationMongoTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/session/SessionAutoConfigurationMongoTests.java @@ -32,6 +32,9 @@ import org.springframework.boot.test.context.assertj.AssertableWebApplicationCon import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.testsupport.testcontainers.DockerImageNames; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.data.mongo.MongoIndexedSessionRepository; import org.springframework.session.data.redis.RedisIndexedSessionRepository; import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository; @@ -75,6 +78,13 @@ class SessionAutoConfigurationMongoTests extends AbstractSessionAutoConfiguratio .run(validateSpringSessionUsesMongo("foo")); } + @Test + void whenTheUserDefinesTheirOwnSessionRepositoryCustomizerThenDefaultConfigurationIsOverwritten() { + this.contextRunner.withUserConfiguration(CustomizerConfiguration.class) + .withPropertyValues("spring.session.mongodb.collection-name=foo") + .run(validateSpringSessionUsesMongo("customized")); + } + private ContextConsumer validateSpringSessionUsesMongo(String collectionName) { return validateSpringSessionUsesMongo(collectionName, new ServerProperties().getServlet().getSession().getTimeout()); @@ -90,4 +100,14 @@ class SessionAutoConfigurationMongoTests extends AbstractSessionAutoConfiguratio }; } + @Configuration(proxyBeanMethods = false) + static class CustomizerConfiguration { + + @Bean + SessionRepositoryCustomizer sessionRepositoryCustomizer() { + return (repository) -> repository.setCollectionName("customized"); + } + + } + } 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 781b388fff..e98b88fc0a 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 @@ -32,10 +32,13 @@ import org.springframework.boot.test.context.assertj.AssertableWebApplicationCon import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.testsupport.testcontainers.RedisContainer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.session.FlushMode; import org.springframework.session.SaveMode; +import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.data.mongo.MongoIndexedSessionRepository; import org.springframework.session.data.redis.RedisIndexedSessionRepository; import org.springframework.session.data.redis.RedisSessionRepository; @@ -165,6 +168,32 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio } + @Test + void whenTheUserDefinesTheirOwnSessionRepositoryCustomizerThenDefaultConfigurationIsOverwritten() { + this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class)) + .withUserConfiguration(CustomizerConfiguration.class) + .withPropertyValues("spring.session.redis.flush-mode=immediate", + "spring.data.redis.host=" + redis.getHost(), "spring.data.redis.port=" + redis.getFirstMappedPort()) + .run((context) -> { + RedisSessionRepository repository = validateSessionRepository(context, RedisSessionRepository.class); + assertThat(repository).hasFieldOrPropertyWithValue("flushMode", FlushMode.ON_SAVE); + }); + } + + @Test + void whenIndexedAndTheUserDefinesTheirOwnSessionRepositoryCustomizerThenDefaultConfigurationIsOverwritten() { + this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class)) + .withUserConfiguration(IndexedCustomizerConfiguration.class) + .withPropertyValues("spring.session.redis.repository-type=indexed", + "spring.session.redis.flush-mode=immediate", "spring.data.redis.host=" + redis.getHost(), + "spring.data.redis.port=" + redis.getFirstMappedPort()) + .run((context) -> { + RedisIndexedSessionRepository repository = validateSessionRepository(context, + RedisIndexedSessionRepository.class); + assertThat(repository).hasFieldOrPropertyWithValue("flushMode", FlushMode.ON_SAVE); + }); + } + private ContextConsumer validateSpringSessionUsesDefaultRedis(String keyNamespace, FlushMode flushMode, SaveMode saveMode) { return (context) -> { @@ -213,4 +242,24 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio } + @Configuration(proxyBeanMethods = false) + static class CustomizerConfiguration { + + @Bean + SessionRepositoryCustomizer sessionRepositoryCustomizer() { + return (repository) -> repository.setFlushMode(FlushMode.ON_SAVE); + } + + } + + @Configuration(proxyBeanMethods = false) + static class IndexedCustomizerConfiguration { + + @Bean + SessionRepositoryCustomizer sessionRepositoryCustomizer() { + return (repository) -> repository.setFlushMode(FlushMode.ON_SAVE); + } + + } + }