From 5ecf390932eca1f84bc284de144b60195c20abde Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Tue, 13 Sep 2016 10:31:03 -0500 Subject: [PATCH] Add spring.session.cleanup.cron.expression Fixes gh-616 --- .../RedisOperationsSessionRepository.java | 2 +- .../http/RedisHttpSessionConfiguration.java | 10 +++ .../jdbc/JdbcOperationsSessionRepository.java | 2 +- .../http/JdbcHttpSessionConfiguration.java | 9 +++ ...tpSessionConfigurationCustomCronTests.java | 80 ++++++++++++++++++ ...tpSessionConfigurationCustomCronTests.java | 81 +++++++++++++++++++ ...on-cleanup-cron-expression-oops.properties | 1 + 7 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 spring-session/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationCustomCronTests.java create mode 100644 spring-session/src/test/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfigurationCustomCronTests.java create mode 100644 spring-session/src/test/resources/spring-session-cleanup-cron-expression-oops.properties diff --git a/spring-session/src/main/java/org/springframework/session/data/redis/RedisOperationsSessionRepository.java b/spring-session/src/main/java/org/springframework/session/data/redis/RedisOperationsSessionRepository.java index 5d0e43b..a87a902 100644 --- a/spring-session/src/main/java/org/springframework/session/data/redis/RedisOperationsSessionRepository.java +++ b/spring-session/src/main/java/org/springframework/session/data/redis/RedisOperationsSessionRepository.java @@ -393,7 +393,7 @@ public class RedisOperationsSessionRepository implements } } - @Scheduled(cron = "0 * * * * *") + @Scheduled(cron = "${spring.session.cleanup.cron.expression:0 * * * * *}") public void cleanupExpiredSessions() { this.expirationPolicy.cleanExpiredSessions(); } diff --git a/spring-session/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java b/spring-session/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java index f2d221c..8e44d4f 100644 --- a/spring-session/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java +++ b/spring-session/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java @@ -27,6 +27,7 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportAware; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.type.AnnotationMetadata; import org.springframework.data.redis.connection.RedisConnection; @@ -200,6 +201,15 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio this.redisSubscriptionExecutor = redisSubscriptionExecutor; } + /** + * Property placeholder to process the @Scheduled annotation. + * @return the {@link PropertySourcesPlaceholderConfigurer} to use + */ + @Bean + public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + /** * Ensures that Redis is configured to send keyspace notifications. This is important * to ensure that expiration and deletion of sessions trigger SessionDestroyedEvents. diff --git a/spring-session/src/main/java/org/springframework/session/jdbc/JdbcOperationsSessionRepository.java b/spring-session/src/main/java/org/springframework/session/jdbc/JdbcOperationsSessionRepository.java index a1d38dc..7654ccb 100644 --- a/spring-session/src/main/java/org/springframework/session/jdbc/JdbcOperationsSessionRepository.java +++ b/spring-session/src/main/java/org/springframework/session/jdbc/JdbcOperationsSessionRepository.java @@ -561,7 +561,7 @@ public class JdbcOperationsSessionRepository implements return sessionMap; } - @Scheduled(cron = "0 * * * * *") + @Scheduled(cron = "${spring.session.cleanup.cron.expression:0 * * * * *}") public void cleanUpExpiredSessions() { int deletedCount = this.transactionOperations.execute(new TransactionCallback() { diff --git a/spring-session/src/main/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfiguration.java b/spring-session/src/main/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfiguration.java index ccda244..d59e305 100644 --- a/spring-session/src/main/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfiguration.java +++ b/spring-session/src/main/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfiguration.java @@ -26,6 +26,7 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportAware; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.GenericConversionService; @@ -190,4 +191,12 @@ public class JdbcHttpSessionConfiguration extends SpringHttpSessionConfiguration .getNumber("maxInactiveIntervalInSeconds"); } + /** + * Property placeholder to process the @Scheduled annotation. + * @return the {@link PropertySourcesPlaceholderConfigurer} to use + */ + @Bean + public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } } diff --git a/spring-session/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationCustomCronTests.java b/spring-session/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationCustomCronTests.java new file mode 100644 index 0000000..ff6ca9a --- /dev/null +++ b/spring-session/src/test/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfigurationCustomCronTests.java @@ -0,0 +1,80 @@ +/* + * Copyright 2014-2016 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 + * + * http://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.data.redis.config.annotation.web.http; + +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.connection.RedisConnectionFactory; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +/** + * @author Rob Winch + * + */ +public class RedisHttpSessionConfigurationCustomCronTests { + + AnnotationConfigApplicationContext context; + + @Before + public void setup() { + this.context = new AnnotationConfigApplicationContext(); + } + + @After + public void closeContext() { + if (this.context != null) { + this.context.close(); + } + } + + @Test + public void overrideCron() { + this.context.register(Config.class); + + assertThatThrownBy(new ThrowingCallable() { + public void call() throws Throwable { + RedisHttpSessionConfigurationCustomCronTests.this.context.refresh(); + } + }).hasStackTraceContaining( + "Encountered invalid @Scheduled method 'cleanupExpiredSessions': Cron expression must consist of 6 fields (found 1 in \"oops\")"); + } + + @EnableRedisHttpSession + @Configuration + @PropertySource("classpath:spring-session-cleanup-cron-expression-oops.properties") + static class Config { + @Bean + public RedisConnectionFactory connectionFactory() { + RedisConnectionFactory factory = mock(RedisConnectionFactory.class); + RedisConnection connection = mock(RedisConnection.class); + given(factory.getConnection()).willReturn(connection); + + return factory; + } + } +} diff --git a/spring-session/src/test/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfigurationCustomCronTests.java b/spring-session/src/test/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfigurationCustomCronTests.java new file mode 100644 index 0000000..67ea095 --- /dev/null +++ b/spring-session/src/test/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfigurationCustomCronTests.java @@ -0,0 +1,81 @@ +/* + * Copyright 2014-2016 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 + * + * http://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.jdbc.config.annotation.web.http; + +import javax.sql.DataSource; + +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.transaction.PlatformTransactionManager; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; + +/** + * @author Rob Winch + * + */ +public class JdbcHttpSessionConfigurationCustomCronTests { + + AnnotationConfigApplicationContext context; + + @Before + public void setup() { + this.context = new AnnotationConfigApplicationContext(); + } + + @After + public void closeContext() { + if (this.context != null) { + this.context.close(); + } + } + + @Test + public void overrideCron() { + this.context.register(Config.class); + + assertThatThrownBy(new ThrowingCallable() { + public void call() throws Throwable { + JdbcHttpSessionConfigurationCustomCronTests.this.context.refresh(); + } + }).hasStackTraceContaining( + "Encountered invalid @Scheduled method 'cleanUpExpiredSessions': Cron expression must consist of 6 fields (found 1 in \"oops\")"); + } + + @EnableJdbcHttpSession + @Configuration + @PropertySource("classpath:spring-session-cleanup-cron-expression-oops.properties") + static class Config { + @Bean + public DataSource dataSource() { + return mock(DataSource.class); + } + + @Bean + public PlatformTransactionManager transactionManager() { + return mock(PlatformTransactionManager.class); + } + } +} diff --git a/spring-session/src/test/resources/spring-session-cleanup-cron-expression-oops.properties b/spring-session/src/test/resources/spring-session-cleanup-cron-expression-oops.properties new file mode 100644 index 0000000..17db1ef --- /dev/null +++ b/spring-session/src/test/resources/spring-session-cleanup-cron-expression-oops.properties @@ -0,0 +1 @@ +spring.session.cleanup.cron.expression=oops \ No newline at end of file