From df3e4c5bc14a0a53f9b0178a0ad9f791589b400d Mon Sep 17 00:00:00 2001 From: Vedran Pavic Date: Fri, 30 Aug 2019 23:29:57 +0200 Subject: [PATCH] Add support for customizing session repository before initialization This commit adds support for customizing session repository implementations (both SessionRepository and ReactiveSessionRepository) before initialization by introducing SessionRepositoryCustomizer and ReactiveSessionRepositoryCustomizer strategies. Resolves: #1499 --- .../ReactiveSessionRepositoryCustomizer.java | 38 +++++++++++++++++++ .../config/SessionRepositoryCustomizer.java | 38 +++++++++++++++++++ .../http/RedisHttpSessionConfiguration.java | 13 +++++++ .../server/RedisWebSessionConfiguration.java | 13 +++++++ .../RedisHttpSessionConfigurationTests.java | 31 +++++++++++++++ .../RedisWebSessionConfigurationTests.java | 29 ++++++++++++++ .../HazelcastHttpSessionConfiguration.java | 13 +++++++ ...azelcastHttpSessionConfigurationTests.java | 28 ++++++++++++++ .../http/JdbcHttpSessionConfiguration.java | 13 +++++++ .../JdbcHttpSessionConfigurationTests.java | 28 ++++++++++++++ 10 files changed, 244 insertions(+) create mode 100644 spring-session-core/src/main/java/org/springframework/session/config/ReactiveSessionRepositoryCustomizer.java create mode 100644 spring-session-core/src/main/java/org/springframework/session/config/SessionRepositoryCustomizer.java diff --git a/spring-session-core/src/main/java/org/springframework/session/config/ReactiveSessionRepositoryCustomizer.java b/spring-session-core/src/main/java/org/springframework/session/config/ReactiveSessionRepositoryCustomizer.java new file mode 100644 index 00000000..c5402a23 --- /dev/null +++ b/spring-session-core/src/main/java/org/springframework/session/config/ReactiveSessionRepositoryCustomizer.java @@ -0,0 +1,38 @@ +/* + * Copyright 2014-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.session.config; + +import org.springframework.session.ReactiveSessionRepository; + +/** + * Strategy that can be used to customize the {@link ReactiveSessionRepository} before it + * is fully initialized, in particular to tune its configuration. + * + * @param the {@link ReactiveSessionRepository} type + * @author Vedran Pavic + * @since 2.2.0 + */ +@FunctionalInterface +public interface ReactiveSessionRepositoryCustomizer { + + /** + * Customize the {@link ReactiveSessionRepository}. + * @param sessionRepository the {@link ReactiveSessionRepository} to customize + */ + void customize(T sessionRepository); + +} diff --git a/spring-session-core/src/main/java/org/springframework/session/config/SessionRepositoryCustomizer.java b/spring-session-core/src/main/java/org/springframework/session/config/SessionRepositoryCustomizer.java new file mode 100644 index 00000000..486d76b4 --- /dev/null +++ b/spring-session-core/src/main/java/org/springframework/session/config/SessionRepositoryCustomizer.java @@ -0,0 +1,38 @@ +/* + * Copyright 2014-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.session.config; + +import org.springframework.session.SessionRepository; + +/** + * Strategy that can be used to customize the {@link SessionRepository} before it is fully + * initialized, in particular to tune its configuration. + * + * @param the {@link SessionRepository} type + * @author Vedran Pavic + * @since 2.2.0 + */ +@FunctionalInterface +public interface SessionRepositoryCustomizer { + + /** + * Customize the {@link SessionRepository}. + * @param sessionRepository the {@link SessionRepository} to customize + */ + void customize(T sessionRepository); + +} diff --git a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java index 8b55db36..4b69204d 100644 --- a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java +++ b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java @@ -18,8 +18,10 @@ package org.springframework.session.data.redis.config.annotation.web.http; import java.util.Arrays; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.concurrent.Executor; +import java.util.stream.Collectors; import org.apache.commons.logging.LogFactory; @@ -51,6 +53,7 @@ import org.springframework.scheduling.config.ScheduledTaskRegistrar; import org.springframework.session.FlushMode; import org.springframework.session.MapSession; import org.springframework.session.SaveMode; +import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration; import org.springframework.session.data.redis.RedisFlushMode; import org.springframework.session.data.redis.RedisOperationsSessionRepository; @@ -103,6 +106,8 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio private Executor redisSubscriptionExecutor; + private List> sessionRepositoryCustomizers; + private ClassLoader classLoader; private StringValueResolver embeddedValueResolver; @@ -123,6 +128,8 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio sessionRepository.setSaveMode(this.saveMode); int database = resolveDatabase(); sessionRepository.setDatabase(database); + this.sessionRepositoryCustomizers + .forEach((sessionRepositoryCustomizer) -> sessionRepositoryCustomizer.customize(sessionRepository)); return sessionRepository; } @@ -221,6 +228,12 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio this.redisSubscriptionExecutor = redisSubscriptionExecutor; } + @Autowired(required = false) + public void setSessionRepositoryCustomizer( + ObjectProvider> sessionRepositoryCustomizers) { + this.sessionRepositoryCustomizers = sessionRepositoryCustomizers.orderedStream().collect(Collectors.toList()); + } + @Override public void setBeanClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; diff --git a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/server/RedisWebSessionConfiguration.java b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/server/RedisWebSessionConfiguration.java index 937d630f..31bfa991 100644 --- a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/server/RedisWebSessionConfiguration.java +++ b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/server/RedisWebSessionConfiguration.java @@ -16,7 +16,9 @@ package org.springframework.session.data.redis.config.annotation.web.server; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.ObjectProvider; @@ -36,6 +38,7 @@ import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.session.MapSession; import org.springframework.session.SaveMode; +import org.springframework.session.config.ReactiveSessionRepositoryCustomizer; import org.springframework.session.config.annotation.web.server.SpringWebSessionConfiguration; import org.springframework.session.data.redis.ReactiveRedisOperationsSessionRepository; import org.springframework.session.data.redis.RedisFlushMode; @@ -68,6 +71,8 @@ public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration private RedisSerializer defaultRedisSerializer; + private List> sessionRepositoryCustomizers; + private ClassLoader classLoader; private StringValueResolver embeddedValueResolver; @@ -82,6 +87,8 @@ public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration sessionRepository.setRedisKeyNamespace(this.redisNamespace); } sessionRepository.setSaveMode(this.saveMode); + this.sessionRepositoryCustomizers + .forEach((sessionRepositoryCustomizer) -> sessionRepositoryCustomizer.customize(sessionRepository)); return sessionRepository; } @@ -120,6 +127,12 @@ public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration this.defaultRedisSerializer = defaultRedisSerializer; } + @Autowired(required = false) + public void setSessionRepositoryCustomizer( + ObjectProvider> sessionRepositoryCustomizers) { + this.sessionRepositoryCustomizers = sessionRepositoryCustomizers.orderedStream().collect(Collectors.toList()); + } + @Override public void setBeanClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; diff --git a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationTests.java b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationTests.java index 0d10bc91..23a3f1e3 100644 --- a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationTests.java +++ b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationTests.java @@ -29,6 +29,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.core.annotation.Order; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisOperations; @@ -36,6 +37,7 @@ import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.mock.env.MockEnvironment; import org.springframework.session.FlushMode; import org.springframework.session.SaveMode; +import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.data.redis.RedisFlushMode; import org.springframework.session.data.redis.RedisOperationsSessionRepository; import org.springframework.session.data.redis.config.annotation.SpringSessionRedisConnectionFactory; @@ -57,6 +59,8 @@ import static org.mockito.Mockito.mock; @SuppressWarnings("deprecation") class RedisHttpSessionConfigurationTests { + private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 600; + private static final String CLEANUP_CRON_EXPRESSION = "0 0 * * * *"; private AnnotationConfigApplicationContext context; @@ -238,6 +242,15 @@ class RedisHttpSessionConfigurationTests { assertThat(beans).containsKeys("springSessionRedisMessageListenerContainer", "redisMessageListenerContainer"); } + @Test + void sessionRepositoryCustomizer() { + registerAndRefresh(RedisConfig.class, SessionRepositoryCustomizerConfiguration.class); + RedisOperationsSessionRepository sessionRepository = this.context + .getBean(RedisOperationsSessionRepository.class); + assertThat(sessionRepository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval", + MAX_INACTIVE_INTERVAL_IN_SECONDS); + } + private void registerAndRefresh(Class... annotatedClasses) { this.context.register(annotatedClasses); this.context.refresh(); @@ -416,4 +429,22 @@ class RedisHttpSessionConfigurationTests { } + @EnableRedisHttpSession + static class SessionRepositoryCustomizerConfiguration { + + @Bean + @Order(0) + public SessionRepositoryCustomizer sessionRepositoryCustomizerOne() { + return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(0); + } + + @Bean + @Order(1) + public SessionRepositoryCustomizer sessionRepositoryCustomizerTwo() { + return (sessionRepository) -> sessionRepository + .setDefaultMaxInactiveInterval(MAX_INACTIVE_INTERVAL_IN_SECONDS); + } + + } + } diff --git a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/server/RedisWebSessionConfigurationTests.java b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/server/RedisWebSessionConfigurationTests.java index dee91312..94ea22e2 100644 --- a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/server/RedisWebSessionConfigurationTests.java +++ b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/server/RedisWebSessionConfigurationTests.java @@ -25,11 +25,13 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; +import org.springframework.core.annotation.Order; import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory; import org.springframework.data.redis.core.ReactiveRedisOperations; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.session.SaveMode; +import org.springframework.session.config.ReactiveSessionRepositoryCustomizer; import org.springframework.session.data.redis.ReactiveRedisOperationsSessionRepository; import org.springframework.session.data.redis.config.annotation.SpringSessionRedisConnectionFactory; import org.springframework.session.data.redis.config.annotation.SpringSessionRedisOperations; @@ -222,6 +224,15 @@ class RedisWebSessionConfigurationTests { "serializer")).isEqualTo(redisSerializer); } + @Test + void sessionRepositoryCustomizer() { + registerAndRefresh(RedisConfig.class, SessionRepositoryCustomizerConfiguration.class); + ReactiveRedisOperationsSessionRepository sessionRepository = this.context + .getBean(ReactiveRedisOperationsSessionRepository.class); + assertThat(sessionRepository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval", + MAX_INACTIVE_INTERVAL_IN_SECONDS); + } + private void registerAndRefresh(Class... annotatedClasses) { this.context.register(annotatedClasses); this.context.refresh(); @@ -348,4 +359,22 @@ class RedisWebSessionConfigurationTests { } + @EnableRedisWebSession + static class SessionRepositoryCustomizerConfiguration { + + @Bean + @Order(0) + public ReactiveSessionRepositoryCustomizer sessionRepositoryCustomizerOne() { + return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(0); + } + + @Bean + @Order(1) + public ReactiveSessionRepositoryCustomizer sessionRepositoryCustomizerTwo() { + return (sessionRepository) -> sessionRepository + .setDefaultMaxInactiveInterval(MAX_INACTIVE_INTERVAL_IN_SECONDS); + } + + } + } diff --git a/spring-session-hazelcast/src/main/java/org/springframework/session/hazelcast/config/annotation/web/http/HazelcastHttpSessionConfiguration.java b/spring-session-hazelcast/src/main/java/org/springframework/session/hazelcast/config/annotation/web/http/HazelcastHttpSessionConfiguration.java index 3141f341..a13ae963 100644 --- a/spring-session-hazelcast/src/main/java/org/springframework/session/hazelcast/config/annotation/web/http/HazelcastHttpSessionConfiguration.java +++ b/spring-session-hazelcast/src/main/java/org/springframework/session/hazelcast/config/annotation/web/http/HazelcastHttpSessionConfiguration.java @@ -16,7 +16,9 @@ package org.springframework.session.hazelcast.config.annotation.web.http; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import com.hazelcast.core.HazelcastInstance; @@ -31,6 +33,7 @@ import org.springframework.core.type.AnnotationMetadata; import org.springframework.session.FlushMode; import org.springframework.session.MapSession; import org.springframework.session.SaveMode; +import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration; import org.springframework.session.hazelcast.HazelcastFlushMode; import org.springframework.session.hazelcast.HazelcastSessionRepository; @@ -63,6 +66,8 @@ public class HazelcastHttpSessionConfiguration extends SpringHttpSessionConfigur private ApplicationEventPublisher applicationEventPublisher; + private List> sessionRepositoryCustomizers; + @Bean public HazelcastSessionRepository sessionRepository() { HazelcastSessionRepository sessionRepository = new HazelcastSessionRepository(this.hazelcastInstance); @@ -73,6 +78,8 @@ public class HazelcastHttpSessionConfiguration extends SpringHttpSessionConfigur sessionRepository.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds); sessionRepository.setFlushMode(this.flushMode); sessionRepository.setSaveMode(this.saveMode); + this.sessionRepositoryCustomizers + .forEach((sessionRepositoryCustomizer) -> sessionRepositoryCustomizer.customize(sessionRepository)); return sessionRepository; } @@ -113,6 +120,12 @@ public class HazelcastHttpSessionConfiguration extends SpringHttpSessionConfigur this.applicationEventPublisher = applicationEventPublisher; } + @Autowired(required = false) + public void setSessionRepositoryCustomizer( + ObjectProvider> sessionRepositoryCustomizers) { + this.sessionRepositoryCustomizers = sessionRepositoryCustomizers.orderedStream().collect(Collectors.toList()); + } + @Override @SuppressWarnings("deprecation") public void setImportMetadata(AnnotationMetadata importMetadata) { diff --git a/spring-session-hazelcast/src/test/java/org/springframework/session/hazelcast/config/annotation/web/http/HazelcastHttpSessionConfigurationTests.java b/spring-session-hazelcast/src/test/java/org/springframework/session/hazelcast/config/annotation/web/http/HazelcastHttpSessionConfigurationTests.java index abfb3f33..8353563d 100644 --- a/spring-session-hazelcast/src/test/java/org/springframework/session/hazelcast/config/annotation/web/http/HazelcastHttpSessionConfigurationTests.java +++ b/spring-session-hazelcast/src/test/java/org/springframework/session/hazelcast/config/annotation/web/http/HazelcastHttpSessionConfigurationTests.java @@ -26,8 +26,10 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; +import org.springframework.core.annotation.Order; import org.springframework.session.FlushMode; import org.springframework.session.SaveMode; +import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.hazelcast.HazelcastFlushMode; import org.springframework.session.hazelcast.HazelcastSessionRepository; import org.springframework.session.hazelcast.config.annotation.SpringSessionHazelcastInstance; @@ -222,6 +224,14 @@ class HazelcastHttpSessionConfigurationTests { .withMessageContaining("expected single matching bean but found 2"); } + @Test + void sessionRepositoryCustomizer() { + registerAndRefresh(SessionRepositoryCustomizerConfiguration.class); + HazelcastSessionRepository sessionRepository = this.context.getBean(HazelcastSessionRepository.class); + assertThat(sessionRepository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval", + MAX_INACTIVE_INTERVAL_IN_SECONDS); + } + private void registerAndRefresh(Class... annotatedClasses) { this.context.register(annotatedClasses); this.context.refresh(); @@ -421,4 +431,22 @@ class HazelcastHttpSessionConfigurationTests { } + @EnableHazelcastHttpSession + static class SessionRepositoryCustomizerConfiguration extends BaseConfiguration { + + @Bean + @Order(0) + public SessionRepositoryCustomizer sessionRepositoryCustomizerOne() { + return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(0); + } + + @Bean + @Order(1) + public SessionRepositoryCustomizer sessionRepositoryCustomizerTwo() { + return (sessionRepository) -> sessionRepository + .setDefaultMaxInactiveInterval(MAX_INACTIVE_INTERVAL_IN_SECONDS); + } + + } + } diff --git a/spring-session-jdbc/src/main/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfiguration.java b/spring-session-jdbc/src/main/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfiguration.java index 33c7d30b..3bb21a52 100644 --- a/spring-session-jdbc/src/main/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfiguration.java +++ b/spring-session-jdbc/src/main/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfiguration.java @@ -16,7 +16,9 @@ package org.springframework.session.jdbc.config.annotation.web.http; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.sql.DataSource; @@ -45,6 +47,7 @@ import org.springframework.scheduling.config.ScheduledTaskRegistrar; import org.springframework.session.FlushMode; import org.springframework.session.MapSession; import org.springframework.session.SaveMode; +import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration; import org.springframework.session.jdbc.JdbcOperationsSessionRepository; import org.springframework.session.jdbc.config.annotation.SpringSessionDataSource; @@ -98,6 +101,8 @@ public class JdbcHttpSessionConfiguration extends SpringHttpSessionConfiguration private ConversionService conversionService; + private List> sessionRepositoryCustomizers; + private ClassLoader classLoader; private StringValueResolver embeddedValueResolver; @@ -133,6 +138,8 @@ public class JdbcHttpSessionConfiguration extends SpringHttpSessionConfiguration else { sessionRepository.setConversionService(createConversionServiceWithBeanClassLoader(this.classLoader)); } + this.sessionRepositoryCustomizers + .forEach((sessionRepositoryCustomizer) -> sessionRepositoryCustomizer.customize(sessionRepository)); return sessionRepository; } @@ -205,6 +212,12 @@ public class JdbcHttpSessionConfiguration extends SpringHttpSessionConfiguration this.conversionService = conversionService; } + @Autowired(required = false) + public void setSessionRepositoryCustomizer( + ObjectProvider> sessionRepositoryCustomizers) { + this.sessionRepositoryCustomizers = sessionRepositoryCustomizers.orderedStream().collect(Collectors.toList()); + } + @Override public void setBeanClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; diff --git a/spring-session-jdbc/src/test/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfigurationTests.java b/spring-session-jdbc/src/test/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfigurationTests.java index 96318d16..e7d4f9e3 100644 --- a/spring-session-jdbc/src/test/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfigurationTests.java +++ b/spring-session-jdbc/src/test/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfigurationTests.java @@ -27,12 +27,14 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.core.annotation.Order; import org.springframework.core.convert.ConversionService; import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.support.lob.LobHandler; import org.springframework.mock.env.MockEnvironment; import org.springframework.session.FlushMode; import org.springframework.session.SaveMode; +import org.springframework.session.config.SessionRepositoryCustomizer; import org.springframework.session.jdbc.JdbcOperationsSessionRepository; import org.springframework.session.jdbc.config.annotation.SpringSessionDataSource; import org.springframework.test.util.ReflectionTestUtils; @@ -274,6 +276,14 @@ class JdbcHttpSessionConfigurationTests { assertThat(ReflectionTestUtils.getField(configuration, "tableName")).isEqualTo("custom_session_table"); } + @Test + void sessionRepositoryCustomizer() { + registerAndRefresh(DataSourceConfiguration.class, SessionRepositoryCustomizerConfiguration.class); + JdbcOperationsSessionRepository sessionRepository = this.context.getBean(JdbcOperationsSessionRepository.class); + assertThat(sessionRepository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval", + MAX_INACTIVE_INTERVAL_IN_SECONDS); + } + private void registerAndRefresh(Class... annotatedClasses) { this.context.register(annotatedClasses); this.context.refresh(); @@ -473,4 +483,22 @@ class JdbcHttpSessionConfigurationTests { } + @EnableJdbcHttpSession + static class SessionRepositoryCustomizerConfiguration { + + @Bean + @Order(0) + public SessionRepositoryCustomizer sessionRepositoryCustomizerOne() { + return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(0); + } + + @Bean + @Order(1) + public SessionRepositoryCustomizer sessionRepositoryCustomizerTwo() { + return (sessionRepository) -> sessionRepository + .setDefaultMaxInactiveInterval(MAX_INACTIVE_INTERVAL_IN_SECONDS); + } + + } + }