From 803c155e69720226a811349a2b25c8d802837598 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 2 Aug 2023 20:35:43 +0100 Subject: [PATCH] Order default customizers so that they can be overridden Closes gh-36674 --- .../HazelcastSessionConfiguration.java | 3 ++ .../session/MongoSessionConfiguration.java | 3 ++ .../session/RedisSessionConfiguration.java | 4 ++ ...essionAutoConfigurationHazelcastTests.java | 22 +++++++++ .../SessionAutoConfigurationMongoTests.java | 20 ++++++++ .../SessionAutoConfigurationRedisTests.java | 49 +++++++++++++++++++ 6 files changed, 101 insertions(+) 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 ed568e8b8344..4a3432467c1e 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.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 @@ 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 97d7c6fa9a8f..97910540f9eb 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.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 @@ 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 fefd83f5520e..71faf7798713 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.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 @@ ConfigureRedisAction configureRedisAction(RedisSessionProperties redisSessionPro } @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 556a38f8cc46..6ee21e160611 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.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 @@ void customSaveMode() { }); } + @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 @@ HazelcastInstance hazelcastInstance() { } + @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 6af94eb57415..ec221f78d6d4 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.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 @@ void mongoSessionStoreWithCustomizations() { .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 @@ private ContextConsumer validateSpringSessionUs }; } + @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 781b388fff9e..e98b88fc0a52 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.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 @@ void indexedRedisSessionWithCustomConfigureRedisActionBean() { } + @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 @@ public void configure(RedisConnection connection) { } + @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); + } + + } + }