From 954a40f5d1b872453dca384954881259aa53dfa7 Mon Sep 17 00:00:00 2001 From: Vedran Pavic Date: Fri, 16 Sep 2022 13:08:54 +0200 Subject: [PATCH] Simplify expired session cleanup jobs At present, RedisIndexedHttpSessionConfiguration and JdbcHttpSessionConfiguration include [at]EnableScheduling annotated inner configuration classes that configure expired session cleanup jobs. This approach silently opts in users into general purpose task scheduling support provided by Spring Framework, which isn't something a library should do. Ideally, session cleanup jobs should only require a single thread dedicated to their execution and also one that doesn't compete for resources with general purpose task scheduling. This commit updates RedisIndexedSessionRepository and JdbcIndexedSessionRepository to have them manage their own ThreadPoolTaskScheduler for purposes of running expired session cleanup jobs. Closes gh-2136 --- .../redis/RedisIndexedSessionRepository.java | 57 ++++++++++++++++++- .../http/EnableRedisIndexedHttpSession.java | 2 +- .../RedisIndexedHttpSessionConfiguration.java | 29 +--------- .../RedisIndexedSessionRepositoryTests.java | 22 ++++++- ...sIndexedHttpSessionConfigurationTests.java | 6 +- .../jdbc/JdbcIndexedSessionRepository.java | 56 +++++++++++++++++- .../web/http/EnableJdbcHttpSession.java | 2 +- .../http/JdbcHttpSessionConfiguration.java | 29 +--------- .../JdbcIndexedSessionRepositoryTests.java | 20 +++++++ .../JdbcHttpSessionConfigurationTests.java | 10 ++-- 10 files changed, 162 insertions(+), 71 deletions(-) diff --git a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/RedisIndexedSessionRepository.java b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/RedisIndexedSessionRepository.java index 60e82ed0..4b4e9b83 100644 --- a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/RedisIndexedSessionRepository.java +++ b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/RedisIndexedSessionRepository.java @@ -27,6 +27,8 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.core.NestedExceptionUtils; @@ -38,6 +40,10 @@ import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.util.ByteUtils; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.scheduling.support.CronExpression; +import org.springframework.scheduling.support.CronTrigger; import org.springframework.session.DelegatingIndexResolver; import org.springframework.session.FindByIndexNameSessionRepository; import org.springframework.session.FlushMode; @@ -249,12 +255,18 @@ import org.springframework.util.Assert; * @since 2.2.0 */ public class RedisIndexedSessionRepository - implements FindByIndexNameSessionRepository, MessageListener { + implements FindByIndexNameSessionRepository, MessageListener, + InitializingBean, DisposableBean { private static final Log logger = LogFactory.getLog(RedisIndexedSessionRepository.class); private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT"; + /** + * The default cron expression used for expired session cleanup job. + */ + public static final String DEFAULT_CLEANUP_CRON = "0 * * * * *"; + /** * The default Redis database used by Spring Session. */ @@ -309,6 +321,10 @@ public class RedisIndexedSessionRepository private SaveMode saveMode = SaveMode.ON_SET_ATTRIBUTE; + private String cleanupCron = DEFAULT_CLEANUP_CRON; + + private ThreadPoolTaskScheduler taskScheduler; + /** * Creates a new instance. For an example, refer to the class level javadoc. * @param sessionRedisOperations the {@link RedisOperations} to use for managing the @@ -322,6 +338,28 @@ public class RedisIndexedSessionRepository configureSessionChannels(); } + @Override + public void afterPropertiesSet() { + if (!Scheduled.CRON_DISABLED.equals(this.cleanupCron)) { + this.taskScheduler = createTaskScheduler(); + this.taskScheduler.initialize(); + this.taskScheduler.schedule(this::cleanUpExpiredSessions, new CronTrigger(this.cleanupCron)); + } + } + + private static ThreadPoolTaskScheduler createTaskScheduler() { + ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); + taskScheduler.setThreadNamePrefix("spring-session-"); + return taskScheduler; + } + + @Override + public void destroy() { + if (this.taskScheduler != null) { + this.taskScheduler.destroy(); + } + } + /** * Sets the {@link ApplicationEventPublisher} that is used to publish * {@link SessionDestroyedEvent}. The default is to not publish a @@ -382,6 +420,21 @@ public class RedisIndexedSessionRepository this.saveMode = saveMode; } + /** + * Set the cleanup cron expression. + * @param cleanupCron the cleanup cron expression + * @since 3.0.0 + * @see CronExpression + * @see Scheduled#CRON_DISABLED + */ + public void setCleanupCron(String cleanupCron) { + Assert.notNull(cleanupCron, "cleanupCron must not be null"); + if (!Scheduled.CRON_DISABLED.equals(cleanupCron)) { + Assert.isTrue(CronExpression.isValidExpression(cleanupCron), "cleanupCron must be valid"); + } + this.cleanupCron = cleanupCron; + } + /** * Sets the database index to use. Defaults to {@link #DEFAULT_DATABASE}. * @param database the database index to use @@ -420,7 +473,7 @@ public class RedisIndexedSessionRepository } } - public void cleanupExpiredSessions() { + public void cleanUpExpiredSessions() { this.expirationPolicy.cleanExpiredSessions(); } diff --git a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/EnableRedisIndexedHttpSession.java b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/EnableRedisIndexedHttpSession.java index 8be4a5be..a90b836b 100644 --- a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/EnableRedisIndexedHttpSession.java +++ b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/EnableRedisIndexedHttpSession.java @@ -106,6 +106,6 @@ public @interface EnableRedisIndexedHttpSession { * The cron expression for expired session cleanup job. By default runs every minute. * @return the session cleanup cron expression */ - String cleanupCron() default RedisIndexedHttpSessionConfiguration.DEFAULT_CLEANUP_CRON; + String cleanupCron() default RedisIndexedSessionRepository.DEFAULT_CLEANUP_CRON; } diff --git a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisIndexedHttpSessionConfiguration.java b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisIndexedHttpSessionConfiguration.java index 1635c17a..e8a65bca 100644 --- a/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisIndexedHttpSessionConfiguration.java +++ b/spring-session-data-redis/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisIndexedHttpSessionConfiguration.java @@ -41,9 +41,6 @@ import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.listener.ChannelTopic; import org.springframework.data.redis.listener.PatternTopic; import org.springframework.data.redis.listener.RedisMessageListenerContainer; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.scheduling.annotation.SchedulingConfigurer; -import org.springframework.scheduling.config.ScheduledTaskRegistrar; import org.springframework.session.IndexResolver; import org.springframework.session.Session; import org.springframework.session.data.redis.RedisIndexedSessionRepository; @@ -68,9 +65,7 @@ public class RedisIndexedHttpSessionConfiguration extends AbstractRedisHttpSessionConfiguration implements EmbeddedValueResolverAware, ImportAware { - static final String DEFAULT_CLEANUP_CRON = "0 * * * * *"; - - private String cleanupCron = DEFAULT_CLEANUP_CRON; + private String cleanupCron = RedisIndexedSessionRepository.DEFAULT_CLEANUP_CRON; private ConfigureRedisAction configureRedisAction = new ConfigureNotifyKeyspaceEventsAction(); @@ -102,6 +97,7 @@ public class RedisIndexedHttpSessionConfiguration } sessionRepository.setFlushMode(getFlushMode()); sessionRepository.setSaveMode(getSaveMode()); + sessionRepository.setCleanupCron(this.cleanupCron); int database = resolveDatabase(); sessionRepository.setDatabase(database); getSessionRepositoryCustomizers() @@ -247,25 +243,4 @@ public class RedisIndexedHttpSessionConfiguration } - /** - * Configuration of scheduled job for cleaning up expired sessions. - */ - @EnableScheduling - @Configuration(proxyBeanMethods = false) - class SessionCleanupConfiguration implements SchedulingConfigurer { - - private final RedisIndexedSessionRepository sessionRepository; - - SessionCleanupConfiguration(RedisIndexedSessionRepository sessionRepository) { - this.sessionRepository = sessionRepository; - } - - @Override - public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { - taskRegistrar.addCronTask(this.sessionRepository::cleanupExpiredSessions, - RedisIndexedHttpSessionConfiguration.this.cleanupCron); - } - - } - } diff --git a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/RedisIndexedSessionRepositoryTests.java b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/RedisIndexedSessionRepositoryTests.java index 5b6c22fa..825f1ca2 100644 --- a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/RedisIndexedSessionRepositoryTests.java +++ b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/RedisIndexedSessionRepositoryTests.java @@ -44,6 +44,7 @@ import org.springframework.data.redis.core.BoundValueOperations; import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.session.FindByIndexNameSessionRepository; import org.springframework.session.FlushMode; import org.springframework.session.MapSession; @@ -451,7 +452,7 @@ class RedisIndexedSessionRepositoryTests { Set expiredIds = new HashSet<>(Arrays.asList("expired-key1", "expired-key2")); given(this.boundSetOperations.members()).willReturn(expiredIds); - this.redisRepository.cleanupExpiredSessions(); + this.redisRepository.cleanUpExpiredSessions(); for (Object id : expiredIds) { String expiredKey = "spring:session:sessions:" + id; @@ -744,6 +745,25 @@ class RedisIndexedSessionRepositoryTests { .withMessage("flushMode cannot be null"); } + @Test + void setCleanupCronNull() { + assertThatIllegalArgumentException().isThrownBy(() -> this.redisRepository.setCleanupCron(null)) + .withMessage("cleanupCron must not be null"); + } + + @Test + void setCleanupCronInvalid() { + assertThatIllegalArgumentException().isThrownBy(() -> this.redisRepository.setCleanupCron("test")) + .withMessage("cleanupCron must be valid"); + } + + @Test + void setCleanupCronDisabled() { + this.redisRepository.setCleanupCron(Scheduled.CRON_DISABLED); + this.redisRepository.afterPropertiesSet(); + assertThat(this.redisRepository).extracting("taskScheduler").isNull(); + } + @Test void changeRedisNamespace() { String namespace = "foo:bar"; diff --git a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisIndexedHttpSessionConfigurationTests.java b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisIndexedHttpSessionConfigurationTests.java index d9b96d63..8d41058f 100644 --- a/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisIndexedHttpSessionConfigurationTests.java +++ b/spring-session-data-redis/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisIndexedHttpSessionConfigurationTests.java @@ -117,10 +117,8 @@ class RedisIndexedHttpSessionConfigurationTests { void customCleanupCronAnnotation() { registerAndRefresh(RedisConfig.class, CustomCleanupCronExpressionAnnotationConfiguration.class); - RedisIndexedHttpSessionConfiguration configuration = this.context - .getBean(RedisIndexedHttpSessionConfiguration.class); - assertThat(configuration).isNotNull(); - assertThat(ReflectionTestUtils.getField(configuration, "cleanupCron")).isEqualTo(CLEANUP_CRON_EXPRESSION); + RedisIndexedSessionRepository sessionRepository = this.context.getBean(RedisIndexedSessionRepository.class); + assertThat(sessionRepository).extracting("cleanupCron").isEqualTo(CLEANUP_CRON_EXPRESSION); } @Test diff --git a/spring-session-jdbc/src/main/java/org/springframework/session/jdbc/JdbcIndexedSessionRepository.java b/spring-session-jdbc/src/main/java/org/springframework/session/jdbc/JdbcIndexedSessionRepository.java index e6f3df39..16f9eab2 100644 --- a/spring-session-jdbc/src/main/java/org/springframework/session/jdbc/JdbcIndexedSessionRepository.java +++ b/spring-session-jdbc/src/main/java/org/springframework/session/jdbc/JdbcIndexedSessionRepository.java @@ -34,6 +34,8 @@ import java.util.stream.Collectors; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.support.GenericConversionService; @@ -48,6 +50,10 @@ import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.support.lob.DefaultLobHandler; import org.springframework.jdbc.support.lob.LobCreator; import org.springframework.jdbc.support.lob.LobHandler; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.scheduling.support.CronExpression; +import org.springframework.scheduling.support.CronTrigger; import org.springframework.session.DelegatingIndexResolver; import org.springframework.session.FindByIndexNameSessionRepository; import org.springframework.session.FlushMode; @@ -130,14 +136,19 @@ import org.springframework.util.StringUtils; * @author Craig Andrews * @since 2.2.0 */ -public class JdbcIndexedSessionRepository - implements FindByIndexNameSessionRepository { +public class JdbcIndexedSessionRepository implements + FindByIndexNameSessionRepository, InitializingBean, DisposableBean { /** * The default name of database table used by Spring Session to store sessions. */ public static final String DEFAULT_TABLE_NAME = "SPRING_SESSION"; + /** + * The default cron expression used for expired session cleanup job. + */ + public static final String DEFAULT_CLEANUP_CRON = "0 * * * * *"; + private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT"; private static final String CREATE_SESSION_QUERY = """ @@ -241,6 +252,10 @@ public class JdbcIndexedSessionRepository private SaveMode saveMode = SaveMode.ON_SET_ATTRIBUTE; + private String cleanupCron = DEFAULT_CLEANUP_CRON; + + private ThreadPoolTaskScheduler taskScheduler; + /** * Create a new {@link JdbcIndexedSessionRepository} instance which uses the provided * {@link JdbcOperations} and {@link TransactionOperations} to manage sessions. @@ -255,6 +270,28 @@ public class JdbcIndexedSessionRepository prepareQueries(); } + @Override + public void afterPropertiesSet() { + if (!Scheduled.CRON_DISABLED.equals(this.cleanupCron)) { + this.taskScheduler = createTaskScheduler(); + this.taskScheduler.initialize(); + this.taskScheduler.schedule(this::cleanUpExpiredSessions, new CronTrigger(this.cleanupCron)); + } + } + + private static ThreadPoolTaskScheduler createTaskScheduler() { + ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); + taskScheduler.setThreadNamePrefix("spring-session-"); + return taskScheduler; + } + + @Override + public void destroy() { + if (this.taskScheduler != null) { + this.taskScheduler.destroy(); + } + } + /** * Set the name of database table used to store sessions. * @param tableName the database table name @@ -397,6 +434,21 @@ public class JdbcIndexedSessionRepository this.saveMode = saveMode; } + /** + * Set the cleanup cron expression. + * @param cleanupCron the cleanup cron expression + * @since 3.0.0 + * @see CronExpression + * @see Scheduled#CRON_DISABLED + */ + public void setCleanupCron(String cleanupCron) { + Assert.notNull(cleanupCron, "cleanupCron must not be null"); + if (!Scheduled.CRON_DISABLED.equals(cleanupCron)) { + Assert.isTrue(CronExpression.isValidExpression(cleanupCron), "cleanupCron must be valid"); + } + this.cleanupCron = cleanupCron; + } + @Override public JdbcSession createSession() { MapSession delegate = new MapSession(); diff --git a/spring-session-jdbc/src/main/java/org/springframework/session/jdbc/config/annotation/web/http/EnableJdbcHttpSession.java b/spring-session-jdbc/src/main/java/org/springframework/session/jdbc/config/annotation/web/http/EnableJdbcHttpSession.java index 2f7698ea..d60753ed 100644 --- a/spring-session-jdbc/src/main/java/org/springframework/session/jdbc/config/annotation/web/http/EnableJdbcHttpSession.java +++ b/spring-session-jdbc/src/main/java/org/springframework/session/jdbc/config/annotation/web/http/EnableJdbcHttpSession.java @@ -96,7 +96,7 @@ public @interface EnableJdbcHttpSession { * @return the session cleanup cron expression * @since 2.0.0 */ - String cleanupCron() default JdbcHttpSessionConfiguration.DEFAULT_CLEANUP_CRON; + String cleanupCron() default JdbcIndexedSessionRepository.DEFAULT_CLEANUP_CRON; /** * Flush mode for the sessions. The default is {@code ON_SAVE} which only updates the 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 bbc7eee2..b1a30d3a 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 @@ -43,9 +43,6 @@ import org.springframework.jdbc.support.MetaDataAccessException; import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator; import org.springframework.jdbc.support.lob.DefaultLobHandler; import org.springframework.jdbc.support.lob.LobHandler; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.scheduling.annotation.SchedulingConfigurer; -import org.springframework.scheduling.config.ScheduledTaskRegistrar; import org.springframework.session.FlushMode; import org.springframework.session.IndexResolver; import org.springframework.session.MapSession; @@ -80,13 +77,11 @@ import org.springframework.util.StringValueResolver; public class JdbcHttpSessionConfiguration extends SpringHttpSessionConfiguration implements BeanClassLoaderAware, EmbeddedValueResolverAware, ImportAware { - static final String DEFAULT_CLEANUP_CRON = "0 * * * * *"; - private Integer maxInactiveIntervalInSeconds = MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS; private String tableName = JdbcIndexedSessionRepository.DEFAULT_TABLE_NAME; - private String cleanupCron = DEFAULT_CLEANUP_CRON; + private String cleanupCron = JdbcIndexedSessionRepository.DEFAULT_CLEANUP_CRON; private FlushMode flushMode = FlushMode.ON_SAVE; @@ -126,6 +121,7 @@ public class JdbcHttpSessionConfiguration extends SpringHttpSessionConfiguration sessionRepository.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds); sessionRepository.setFlushMode(this.flushMode); sessionRepository.setSaveMode(this.saveMode); + sessionRepository.setCleanupCron(this.cleanupCron); if (this.indexResolver != null) { sessionRepository.setIndexResolver(this.indexResolver); } @@ -281,25 +277,4 @@ public class JdbcHttpSessionConfiguration extends SpringHttpSessionConfiguration return conversionService; } - /** - * Configuration of scheduled job for cleaning up expired sessions. - */ - @EnableScheduling - @Configuration(proxyBeanMethods = false) - class SessionCleanupConfiguration implements SchedulingConfigurer { - - private final JdbcIndexedSessionRepository sessionRepository; - - SessionCleanupConfiguration(JdbcIndexedSessionRepository sessionRepository) { - this.sessionRepository = sessionRepository; - } - - @Override - public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { - taskRegistrar.addCronTask(this.sessionRepository::cleanUpExpiredSessions, - JdbcHttpSessionConfiguration.this.cleanupCron); - } - - } - } diff --git a/spring-session-jdbc/src/test/java/org/springframework/session/jdbc/JdbcIndexedSessionRepositoryTests.java b/spring-session-jdbc/src/test/java/org/springframework/session/jdbc/JdbcIndexedSessionRepositoryTests.java index 859bcb8f..e9392d03 100644 --- a/spring-session-jdbc/src/test/java/org/springframework/session/jdbc/JdbcIndexedSessionRepositoryTests.java +++ b/spring-session-jdbc/src/test/java/org/springframework/session/jdbc/JdbcIndexedSessionRepositoryTests.java @@ -38,6 +38,7 @@ import org.springframework.jdbc.core.PreparedStatementSetter; import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.support.lob.DefaultLobHandler; import org.springframework.jdbc.support.lob.TemporaryLobCreator; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.AuthorityUtils; @@ -243,6 +244,25 @@ class JdbcIndexedSessionRepositoryTests { .withMessage("saveMode must not be null"); } + @Test + void setCleanupCronNull() { + assertThatIllegalArgumentException().isThrownBy(() -> this.repository.setCleanupCron(null)) + .withMessage("cleanupCron must not be null"); + } + + @Test + void setCleanupCronInvalid() { + assertThatIllegalArgumentException().isThrownBy(() -> this.repository.setCleanupCron("test")) + .withMessage("cleanupCron must be valid"); + } + + @Test + void setCleanupCronDisabled() { + this.repository.setCleanupCron(Scheduled.CRON_DISABLED); + this.repository.afterPropertiesSet(); + assertThat(this.repository).extracting("taskScheduler").isNull(); + } + @Test void createSessionDefaultMaxInactiveInterval() { JdbcSession session = this.repository.createSession(); 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 27d3857f..b2df1bd6 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 @@ -136,18 +136,16 @@ class JdbcHttpSessionConfigurationTests { void customCleanupCronAnnotation() { registerAndRefresh(DataSourceConfiguration.class, CustomCleanupCronExpressionAnnotationConfiguration.class); - JdbcHttpSessionConfiguration configuration = this.context.getBean(JdbcHttpSessionConfiguration.class); - assertThat(configuration).isNotNull(); - assertThat(ReflectionTestUtils.getField(configuration, "cleanupCron")).isEqualTo(CLEANUP_CRON_EXPRESSION); + JdbcIndexedSessionRepository repository = this.context.getBean(JdbcIndexedSessionRepository.class); + assertThat(repository).extracting("cleanupCron").isEqualTo(CLEANUP_CRON_EXPRESSION); } @Test void customCleanupCronSetter() { registerAndRefresh(DataSourceConfiguration.class, CustomCleanupCronExpressionSetterConfiguration.class); - JdbcHttpSessionConfiguration configuration = this.context.getBean(JdbcHttpSessionConfiguration.class); - assertThat(configuration).isNotNull(); - assertThat(ReflectionTestUtils.getField(configuration, "cleanupCron")).isEqualTo(CLEANUP_CRON_EXPRESSION); + JdbcIndexedSessionRepository repository = this.context.getBean(JdbcIndexedSessionRepository.class); + assertThat(repository).extracting("cleanupCron").isEqualTo(CLEANUP_CRON_EXPRESSION); } @Test