Add support for configuring Spring Session SaveMode

See gh-17514
pull/17538/head
Vedran Pavic 5 years ago committed by Stephane Nicoll
parent b7d349db83
commit e073792448

@ -59,6 +59,7 @@ class HazelcastSessionConfiguration {
}
setSessionMapName(hazelcastSessionProperties.getMapName());
setFlushMode(hazelcastSessionProperties.getFlushMode());
setSaveMode(hazelcastSessionProperties.getSaveMode());
}
}

@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.session;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.session.FlushMode;
import org.springframework.session.SaveMode;
/**
* Configuration properties for Hazelcast backed Spring Session.
@ -38,6 +39,12 @@ public class HazelcastSessionProperties {
*/
private FlushMode flushMode = FlushMode.ON_SAVE;
/**
* Sessions save mode. Determines how session changes are tracked and saved to the
* session store.
*/
private SaveMode saveMode = SaveMode.ON_SET_ATTRIBUTE;
public String getMapName() {
return this.mapName;
}
@ -54,4 +61,12 @@ public class HazelcastSessionProperties {
this.flushMode = flushMode;
}
public SaveMode getSaveMode() {
return this.saveMode;
}
public void setSaveMode(SaveMode saveMode) {
this.saveMode = saveMode;
}
}

@ -67,6 +67,7 @@ class JdbcSessionConfiguration {
}
setTableName(jdbcSessionProperties.getTableName());
setCleanupCron(jdbcSessionProperties.getCleanupCron());
setSaveMode(jdbcSessionProperties.getSaveMode());
}
}

@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-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.
@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.session;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceInitializationMode;
import org.springframework.session.SaveMode;
/**
* Configuration properties for JDBC backed Spring Session.
@ -55,6 +56,12 @@ public class JdbcSessionProperties {
*/
private DataSourceInitializationMode initializeSchema = DataSourceInitializationMode.EMBEDDED;
/**
* Sessions save mode. Determines how session changes are tracked and saved to the
* session store.
*/
private SaveMode saveMode = SaveMode.ON_SET_ATTRIBUTE;
public String getSchema() {
return this.schema;
}
@ -87,4 +94,12 @@ public class JdbcSessionProperties {
this.initializeSchema = initializeSchema;
}
public SaveMode getSaveMode() {
return this.saveMode;
}
public void setSaveMode(SaveMode saveMode) {
this.saveMode = saveMode;
}
}

@ -53,6 +53,7 @@ class RedisReactiveSessionConfiguration {
setMaxInactiveIntervalInSeconds((int) timeout.getSeconds());
}
setRedisNamespace(redisSessionProperties.getNamespace());
setSaveMode(redisSessionProperties.getSaveMode());
}
}

@ -76,6 +76,7 @@ class RedisSessionConfiguration {
setRedisNamespace(redisSessionProperties.getNamespace());
setFlushMode(redisSessionProperties.getFlushMode());
setCleanupCron(redisSessionProperties.getCleanupCron());
setSaveMode(redisSessionProperties.getSaveMode());
}
}

@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.session;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.session.FlushMode;
import org.springframework.session.SaveMode;
/**
* Configuration properties for Redis backed Spring Session.
@ -51,6 +52,12 @@ public class RedisSessionProperties {
*/
private String cleanupCron = DEFAULT_CLEANUP_CRON;
/**
* Sessions save mode. Determines how session changes are tracked and saved to the
* session store.
*/
private SaveMode saveMode = SaveMode.ON_SET_ATTRIBUTE;
public String getNamespace() {
return this.namespace;
}
@ -83,6 +90,14 @@ public class RedisSessionProperties {
this.configureAction = configureAction;
}
public SaveMode getSaveMode() {
return this.saveMode;
}
public void setSaveMode(SaveMode saveMode) {
this.saveMode = saveMode;
}
/**
* Strategies for configuring and validating Redis.
*/

@ -25,6 +25,7 @@ import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext;
import org.springframework.boot.test.context.runner.ContextConsumer;
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
import org.springframework.session.SaveMode;
import org.springframework.session.data.mongo.ReactiveMongoOperationsSessionRepository;
import org.springframework.session.data.redis.ReactiveRedisOperationsSessionRepository;
@ -47,7 +48,7 @@ class ReactiveSessionAutoConfigurationRedisTests extends AbstractSessionAutoConf
this.contextRunner.withPropertyValues("spring.session.store-type=redis")
.withConfiguration(
AutoConfigurations.of(RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class))
.run(validateSpringSessionUsesRedis("spring:session:"));
.run(validateSpringSessionUsesRedis("spring:session:", SaveMode.ON_SET_ATTRIBUTE));
}
@Test
@ -55,7 +56,7 @@ class ReactiveSessionAutoConfigurationRedisTests extends AbstractSessionAutoConf
this.contextRunner.withClassLoader(new FilteredClassLoader(ReactiveMongoOperationsSessionRepository.class))
.withConfiguration(
AutoConfigurations.of(RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class))
.run(validateSpringSessionUsesRedis("spring:session:"));
.run(validateSpringSessionUsesRedis("spring:session:", SaveMode.ON_SET_ATTRIBUTE));
}
@Test
@ -63,15 +64,18 @@ class ReactiveSessionAutoConfigurationRedisTests extends AbstractSessionAutoConf
this.contextRunner
.withConfiguration(
AutoConfigurations.of(RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class))
.withPropertyValues("spring.session.store-type=redis", "spring.session.redis.namespace=foo")
.run(validateSpringSessionUsesRedis("foo:"));
.withPropertyValues("spring.session.store-type=redis", "spring.session.redis.namespace=foo",
"spring.session.redis.save-mode=on-get-attribute")
.run(validateSpringSessionUsesRedis("foo:", SaveMode.ON_GET_ATTRIBUTE));
}
private ContextConsumer<AssertableReactiveWebApplicationContext> validateSpringSessionUsesRedis(String namespace) {
private ContextConsumer<AssertableReactiveWebApplicationContext> validateSpringSessionUsesRedis(String namespace,
SaveMode saveMode) {
return (context) -> {
ReactiveRedisOperationsSessionRepository repository = validateSessionRepository(context,
ReactiveRedisOperationsSessionRepository.class);
assertThat(repository).hasFieldOrPropertyWithValue("namespace", namespace);
assertThat(repository).hasFieldOrPropertyWithValue("saveMode", saveMode);
};
}

@ -27,6 +27,7 @@ import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.FlushMode;
import org.springframework.session.SaveMode;
import org.springframework.session.data.mongo.MongoOperationsSessionRepository;
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
import org.springframework.session.hazelcast.HazelcastSessionRepository;
@ -88,6 +89,16 @@ class SessionAutoConfigurationHazelcastTests extends AbstractSessionAutoConfigur
});
}
@Test
void customSaveMode() {
this.contextRunner.withPropertyValues("spring.session.store-type=hazelcast",
"spring.session.hazelcast.save-mode=on-get-attribute").run((context) -> {
HazelcastSessionRepository repository = validateSessionRepository(context,
HazelcastSessionRepository.class);
assertThat(repository).hasFieldOrPropertyWithValue("saveMode", SaveMode.ON_GET_ATTRIBUTE);
});
}
@Configuration(proxyBeanMethods = false)
static class HazelcastConfiguration {

@ -30,6 +30,7 @@ import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.session.SaveMode;
import org.springframework.session.data.mongo.MongoOperationsSessionRepository;
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
import org.springframework.session.hazelcast.HazelcastSessionRepository;
@ -129,4 +130,17 @@ class SessionAutoConfigurationJdbcTests extends AbstractSessionAutoConfiguration
});
}
@Test
void customSaveMode() {
this.contextRunner
.withPropertyValues("spring.session.store-type=jdbc", "spring.session.jdbc.save-mode=on-get-attribute")
.run((context) -> {
assertThat(context.getBean(JdbcSessionProperties.class).getSaveMode())
.isEqualTo(SaveMode.ON_GET_ATTRIBUTE);
SpringBootJdbcHttpSessionConfiguration configuration = context
.getBean(SpringBootJdbcHttpSessionConfiguration.class);
assertThat(configuration).hasFieldOrPropertyWithValue("saveMode", SaveMode.ON_GET_ATTRIBUTE);
});
}
}

@ -33,6 +33,7 @@ import org.springframework.boot.testsupport.testcontainers.RedisContainer;
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.data.mongo.MongoOperationsSessionRepository;
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
import org.springframework.session.data.redis.config.ConfigureNotifyKeyspaceEventsAction;
@ -64,8 +65,8 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio
.withPropertyValues("spring.session.store-type=redis",
"spring.redis.port=" + redis.getFirstMappedPort())
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
.run(validateSpringSessionUsesRedis("spring:session:event:0:created:", FlushMode.ON_SAVE,
"0 * * * * *"));
.run(validateSpringSessionUsesRedis("spring:session:event:0:created:", FlushMode.ON_SAVE, "0 * * * * *",
SaveMode.ON_SET_ATTRIBUTE));
}
@Test
@ -75,8 +76,8 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio
JdbcOperationsSessionRepository.class, MongoOperationsSessionRepository.class))
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
.withPropertyValues("spring.redis.port=" + redis.getFirstMappedPort())
.run(validateSpringSessionUsesRedis("spring:session:event:0:created:", FlushMode.ON_SAVE,
"0 * * * * *"));
.run(validateSpringSessionUsesRedis("spring:session:event:0:created:", FlushMode.ON_SAVE, "0 * * * * *",
SaveMode.ON_SET_ATTRIBUTE));
}
@Test
@ -84,8 +85,10 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
.withPropertyValues("spring.session.store-type=redis", "spring.session.redis.namespace=foo",
"spring.session.redis.flush-mode=immediate", "spring.session.redis.cleanup-cron=0 0 12 * * *",
"spring.session.redis.save-mode=on-get-attribute",
"spring.redis.port=" + redis.getFirstMappedPort())
.run(validateSpringSessionUsesRedis("foo:event:0:created:", FlushMode.IMMEDIATE, "0 0 12 * * *"));
.run(validateSpringSessionUsesRedis("foo:event:0:created:", FlushMode.IMMEDIATE, "0 0 12 * * *",
SaveMode.ON_GET_ATTRIBUTE));
}
@Test
@ -116,7 +119,7 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio
}
private ContextConsumer<AssertableWebApplicationContext> validateSpringSessionUsesRedis(
String sessionCreatedChannelPrefix, FlushMode flushMode, String cleanupCron) {
String sessionCreatedChannelPrefix, FlushMode flushMode, String cleanupCron, SaveMode saveMode) {
return (context) -> {
RedisOperationsSessionRepository repository = validateSessionRepository(context,
RedisOperationsSessionRepository.class);
@ -125,6 +128,7 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio
SpringBootRedisHttpSessionConfiguration configuration = context
.getBean(SpringBootRedisHttpSessionConfiguration.class);
assertThat(configuration).hasFieldOrPropertyWithValue("cleanupCron", cleanupCron);
assertThat(repository).hasFieldOrPropertyWithValue("saveMode", saveMode);
};
}

Loading…
Cancel
Save