Merge pull request #10818 from vpavic:align-session-2.0

* pr/10818:
  Add support for configuring Spring Session cleanup cron
pull/10818/merge
Stephane Nicoll 7 years ago
commit 944216e11f

@ -68,6 +68,7 @@ class JdbcSessionConfiguration {
setMaxInactiveIntervalInSeconds(timeout); setMaxInactiveIntervalInSeconds(timeout);
} }
setTableName(jdbcSessionProperties.getTableName()); setTableName(jdbcSessionProperties.getTableName());
setCleanupCron(jdbcSessionProperties.getCleanupCron());
} }
} }

@ -33,6 +33,8 @@ public class JdbcSessionProperties {
private static final String DEFAULT_TABLE_NAME = "SPRING_SESSION"; private static final String DEFAULT_TABLE_NAME = "SPRING_SESSION";
private static final String DEFAULT_CLEANUP_CRON = "0 * * * * *";
/** /**
* Path to the SQL file to use to initialize the database schema. * Path to the SQL file to use to initialize the database schema.
*/ */
@ -43,6 +45,11 @@ public class JdbcSessionProperties {
*/ */
private String tableName = DEFAULT_TABLE_NAME; private String tableName = DEFAULT_TABLE_NAME;
/**
* Cron expression for expired session cleanup job.
*/
private String cleanupCron = DEFAULT_CLEANUP_CRON;
/** /**
* Database schema initialization mode. * Database schema initialization mode.
*/ */
@ -64,6 +71,14 @@ public class JdbcSessionProperties {
this.tableName = tableName; this.tableName = tableName;
} }
public String getCleanupCron() {
return this.cleanupCron;
}
public void setCleanupCron(String cleanupCron) {
this.cleanupCron = cleanupCron;
}
public DataSourceInitializationMode getInitializeSchema() { public DataSourceInitializationMode getInitializeSchema() {
return this.initializeSchema; return this.initializeSchema;
} }

@ -62,6 +62,7 @@ class RedisSessionConfiguration {
} }
setRedisNamespace(redisSessionProperties.getNamespace()); setRedisNamespace(redisSessionProperties.getNamespace());
setRedisFlushMode(redisSessionProperties.getFlushMode()); setRedisFlushMode(redisSessionProperties.getFlushMode());
setCleanupCron(redisSessionProperties.getCleanupCron());
} }
} }

@ -28,6 +28,8 @@ import org.springframework.session.data.redis.RedisFlushMode;
@ConfigurationProperties(prefix = "spring.session.redis") @ConfigurationProperties(prefix = "spring.session.redis")
public class RedisSessionProperties { public class RedisSessionProperties {
private static final String DEFAULT_CLEANUP_CRON = "0 * * * * *";
/** /**
* Namespace for keys used to store sessions. * Namespace for keys used to store sessions.
*/ */
@ -38,6 +40,11 @@ public class RedisSessionProperties {
*/ */
private RedisFlushMode flushMode = RedisFlushMode.ON_SAVE; private RedisFlushMode flushMode = RedisFlushMode.ON_SAVE;
/**
* Cron expression for expired session cleanup job.
*/
private String cleanupCron = DEFAULT_CLEANUP_CRON;
public String getNamespace() { public String getNamespace() {
return this.namespace; return this.namespace;
} }
@ -54,4 +61,12 @@ public class RedisSessionProperties {
this.flushMode = flushMode; this.flushMode = flushMode;
} }
public String getCleanupCron() {
return this.cleanupCron;
}
public void setCleanupCron(String cleanupCron) {
this.cleanupCron = cleanupCron;
}
} }

@ -25,6 +25,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
import org.springframework.boot.autoconfigure.session.JdbcSessionConfiguration.SpringBootJdbcHttpSessionConfiguration;
import org.springframework.boot.jdbc.DataSourceInitializationMode; import org.springframework.boot.jdbc.DataSourceInitializationMode;
import org.springframework.boot.test.context.HideClassesClassLoader; import org.springframework.boot.test.context.HideClassesClassLoader;
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext; import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
@ -82,7 +83,10 @@ public class SessionAutoConfigurationJdbcTests
.isEqualTo(DataSourceInitializationMode.EMBEDDED); .isEqualTo(DataSourceInitializationMode.EMBEDDED);
assertThat(context.getBean(JdbcOperations.class) assertThat(context.getBean(JdbcOperations.class)
.queryForList("select * from SPRING_SESSION")).isEmpty(); .queryForList("select * from SPRING_SESSION")).isEmpty();
SpringBootJdbcHttpSessionConfiguration configuration = context
.getBean(SpringBootJdbcHttpSessionConfiguration.class);
assertThat(new DirectFieldAccessor(configuration).getPropertyValue("cleanupCron"))
.isEqualTo("0 * * * * *");
} }
@Test @Test
@ -114,10 +118,9 @@ public class SessionAutoConfigurationJdbcTests
@Test @Test
public void customTableName() { public void customTableName() {
this.contextRunner this.contextRunner.withPropertyValues("spring.session.store-type=jdbc",
.withPropertyValues("spring.session.store-type=jdbc", "spring.session.jdbc.table-name=FOO_BAR",
"spring.session.jdbc.table-name=FOO_BAR", "spring.session.jdbc.schema=classpath:session/custom-schema-h2.sql")
"spring.session.jdbc.schema=classpath:session/custom-schema-h2.sql")
.run((context) -> { .run((context) -> {
JdbcOperationsSessionRepository repository = validateSessionRepository( JdbcOperationsSessionRepository repository = validateSessionRepository(
context, JdbcOperationsSessionRepository.class); context, JdbcOperationsSessionRepository.class);
@ -131,4 +134,20 @@ public class SessionAutoConfigurationJdbcTests
}); });
} }
@Test
public void customCleanupCron() {
this.contextRunner
.withPropertyValues("spring.session.store-type=jdbc",
"spring.session.jdbc.cleanup-cron=0 0 12 * * *")
.run((context) -> {
assertThat(
context.getBean(JdbcSessionProperties.class).getCleanupCron())
.isEqualTo("0 0 12 * * *");
SpringBootJdbcHttpSessionConfiguration configuration = context
.getBean(SpringBootJdbcHttpSessionConfiguration.class);
assertThat(new DirectFieldAccessor(configuration)
.getPropertyValue("cleanupCron")).isEqualTo("0 0 12 * * *");
});
}
} }

@ -22,6 +22,7 @@ import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.DirectFieldAccessor;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.session.RedisSessionConfiguration.SpringBootRedisHttpSessionConfiguration;
import org.springframework.boot.test.context.HideClassesClassLoader; import org.springframework.boot.test.context.HideClassesClassLoader;
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext; import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.boot.test.context.runner.ContextConsumer;
@ -39,6 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* Redis specific tests for {@link SessionAutoConfiguration}. * Redis specific tests for {@link SessionAutoConfiguration}.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Vedran Pavic
*/ */
public class SessionAutoConfigurationRedisTests public class SessionAutoConfigurationRedisTests
extends AbstractSessionAutoConfigurationTests { extends AbstractSessionAutoConfigurationTests {
@ -54,7 +56,7 @@ public class SessionAutoConfigurationRedisTests
this.contextRunner.withPropertyValues("spring.session.store-type=redis") this.contextRunner.withPropertyValues("spring.session.store-type=redis")
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class)) .withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
.run(validateSpringSessionUsesRedis("spring:session:event:created:", .run(validateSpringSessionUsesRedis("spring:session:event:created:",
RedisFlushMode.ON_SAVE)); RedisFlushMode.ON_SAVE, "0 * * * * *"));
} }
@Test @Test
@ -66,7 +68,7 @@ public class SessionAutoConfigurationRedisTests
MongoOperationsSessionRepository.class)) MongoOperationsSessionRepository.class))
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class)) .withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
.run(validateSpringSessionUsesRedis("spring:session:event:created:", .run(validateSpringSessionUsesRedis("spring:session:event:created:",
RedisFlushMode.ON_SAVE)); RedisFlushMode.ON_SAVE, "0 * * * * *"));
} }
@Test @Test
@ -75,13 +77,15 @@ public class SessionAutoConfigurationRedisTests
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class)) .withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
.withPropertyValues("spring.session.store-type=redis", .withPropertyValues("spring.session.store-type=redis",
"spring.session.redis.namespace=foo", "spring.session.redis.namespace=foo",
"spring.session.redis.flush-mode=immediate") "spring.session.redis.flush-mode=immediate",
"spring.session.redis.cleanup-cron=0 0 12 * * *")
.run(validateSpringSessionUsesRedis("spring:session:foo:event:created:", .run(validateSpringSessionUsesRedis("spring:session:foo:event:created:",
RedisFlushMode.IMMEDIATE)); RedisFlushMode.IMMEDIATE, "0 0 12 * * *"));
} }
private ContextConsumer<AssertableWebApplicationContext> validateSpringSessionUsesRedis( private ContextConsumer<AssertableWebApplicationContext> validateSpringSessionUsesRedis(
String sessionCreatedChannelPrefix, RedisFlushMode flushMode) { String sessionCreatedChannelPrefix, RedisFlushMode flushMode,
String cleanupCron) {
return (context) -> { return (context) -> {
RedisOperationsSessionRepository repository = validateSessionRepository( RedisOperationsSessionRepository repository = validateSessionRepository(
context, RedisOperationsSessionRepository.class); context, RedisOperationsSessionRepository.class);
@ -89,6 +93,10 @@ public class SessionAutoConfigurationRedisTests
.isEqualTo(sessionCreatedChannelPrefix); .isEqualTo(sessionCreatedChannelPrefix);
assertThat(new DirectFieldAccessor(repository) assertThat(new DirectFieldAccessor(repository)
.getPropertyValue("redisFlushMode")).isEqualTo(flushMode); .getPropertyValue("redisFlushMode")).isEqualTo(flushMode);
SpringBootRedisHttpSessionConfiguration configuration = context
.getBean(SpringBootRedisHttpSessionConfiguration.class);
assertThat(new DirectFieldAccessor(configuration)
.getPropertyValue("cleanupCron")).isEqualTo(cleanupCron);
}; };
} }

@ -425,6 +425,7 @@ content into your application; rather pick only the properties that you need.
spring.session.hazelcast.map-name=spring:session:sessions # Name of the map used to store sessions. spring.session.hazelcast.map-name=spring:session:sessions # Name of the map used to store sessions.
# SPRING SESSION JDBC ({sc-spring-boot-autoconfigure}/session/JdbcSessionProperties.{sc-ext}[JdbcSessionProperties]) # SPRING SESSION JDBC ({sc-spring-boot-autoconfigure}/session/JdbcSessionProperties.{sc-ext}[JdbcSessionProperties])
spring.session.jdbc.cleanup-cron=0 * * * * * # Cron expression for expired session cleanup job.
spring.session.jdbc.initialize-schema=embedded # Database schema initialization mode. spring.session.jdbc.initialize-schema=embedded # Database schema initialization mode.
spring.session.jdbc.schema=classpath:org/springframework/session/jdbc/schema-@@platform@@.sql # Path to the SQL file to use to initialize the database schema. spring.session.jdbc.schema=classpath:org/springframework/session/jdbc/schema-@@platform@@.sql # Path to the SQL file to use to initialize the database schema.
spring.session.jdbc.table-name=SPRING_SESSION # Name of database table used to store sessions. spring.session.jdbc.table-name=SPRING_SESSION # Name of database table used to store sessions.
@ -433,6 +434,7 @@ content into your application; rather pick only the properties that you need.
spring.session.mongodb.collection-name=sessions # Collection name used to store sessions. spring.session.mongodb.collection-name=sessions # Collection name used to store sessions.
# SPRING SESSION REDIS ({sc-spring-boot-autoconfigure}/session/RedisSessionProperties.{sc-ext}[RedisSessionProperties]) # SPRING SESSION REDIS ({sc-spring-boot-autoconfigure}/session/RedisSessionProperties.{sc-ext}[RedisSessionProperties])
spring.session.redis.cleanup-cron=0 * * * * * # Cron expression for expired session cleanup job.
spring.session.redis.flush-mode=on-save # Sessions flush mode. spring.session.redis.flush-mode=on-save # Sessions flush mode.
spring.session.redis.namespace= # Namespace for keys used to store sessions. spring.session.redis.namespace= # Namespace for keys used to store sessions.

Loading…
Cancel
Save