Improve upgrade path for Spring Session

Commit b7e7bcf made `spring.session.store-type` explicit which means that
users of Spring Session in 1.3 have to set that property to restore the
auto-configuration support in 1.4.

This commit implicitly set the store type to redis if redis is present
and log a warning inviting the user to actually specify that in
configuration.

The entry in the auto-configuration report also mentions that such
arrangement is deprecated.

Closes gh-5838
This commit is contained in:
Stephane Nicoll 2016-05-13 11:19:02 +02:00
parent 72854745c5
commit 5deca28a9d
4 changed files with 52 additions and 7 deletions

View File

@ -16,6 +16,11 @@
package org.springframework.boot.autoconfigure.session;
import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@ -40,21 +45,34 @@ import org.springframework.session.data.redis.config.annotation.web.http.RedisHt
@Conditional(SessionCondition.class)
class RedisSessionConfiguration {
private static final Logger logger = LoggerFactory.getLogger(RedisSessionConfiguration.class);
@Configuration
public static class SpringBootRedisHttpSessionConfiguration
extends RedisHttpSessionConfiguration {
private SessionProperties sessionProperties;
@Autowired
public void customize(SessionProperties sessionProperties) {
Integer timeout = sessionProperties.getTimeout();
this.sessionProperties = sessionProperties;
Integer timeout = this.sessionProperties.getTimeout();
if (timeout != null) {
setMaxInactiveIntervalInSeconds(timeout);
}
SessionProperties.Redis redis = sessionProperties.getRedis();
SessionProperties.Redis redis = this.sessionProperties.getRedis();
setRedisNamespace(redis.getNamespace());
setRedisFlushMode(redis.getFlushMode());
}
@PostConstruct
public void validate() {
if (this.sessionProperties.getStoreType() == null) {
logger.warn("Spring Session store type is mandatory: set " +
"'spring.session.store-type=redis' in your configuration");
}
}
}
}

View File

@ -22,6 +22,7 @@ import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.ClassUtils;
/**
* General condition used with all session configuration classes.
@ -30,16 +31,24 @@ import org.springframework.core.type.AnnotationMetadata;
*/
class SessionCondition extends SpringBootCondition {
private static final boolean redisPresent = ClassUtils.isPresent(
"org.springframework.data.redis.core.RedisTemplate", SessionCondition.class.getClassLoader());
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
context.getEnvironment(), "spring.session.");
if (!resolver.containsProperty("store-type")) {
return ConditionOutcome.noMatch("Session store type not set");
}
StoreType sessionStoreType = SessionStoreMappings
.getType(((AnnotationMetadata) metadata).getClassName());
if (!resolver.containsProperty("store-type")) {
if (sessionStoreType == StoreType.REDIS && redisPresent) {
return ConditionOutcome.match("Session store type default to redis (deprecated)");
}
else {
return ConditionOutcome.noMatch("Session store type not set");
}
}
String value = resolver.getProperty("store-type").replace("-", "_").toUpperCase();
if (value.equals(sessionStoreType.name())) {
return ConditionOutcome.match("Session store type " + sessionStoreType);

View File

@ -34,9 +34,9 @@ final class SessionStoreMappings {
static {
Map<StoreType, Class<?>> mappings = new HashMap<StoreType, Class<?>>();
mappings.put(StoreType.JDBC, JdbcSessionConfiguration.class);
mappings.put(StoreType.MONGO, MongoSessionConfiguration.class);
mappings.put(StoreType.REDIS, RedisSessionConfiguration.class);
mappings.put(StoreType.MONGO, MongoSessionConfiguration.class);
mappings.put(StoreType.JDBC, JdbcSessionConfiguration.class);
mappings.put(StoreType.HAZELCAST, HazelcastSessionConfiguration.class);
mappings.put(StoreType.HASH_MAP, HashMapSessionConfiguration.class);
mappings.put(StoreType.NONE, NoOpSessionConfiguration.class);

View File

@ -24,10 +24,13 @@ import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.redis.RedisTestServer;
import org.springframework.boot.test.rule.OutputCapture;
import org.springframework.session.data.redis.RedisFlushMode;
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.Matchers.containsString;
/**
* Redis specific tests for {@link SessionAutoConfiguration}.
@ -37,13 +40,28 @@ import static org.assertj.core.api.Assertions.assertThat;
public class SessionAutoConfigurationRedisTests
extends AbstractSessionAutoConfigurationTests {
@Rule
public OutputCapture output = new OutputCapture();
@Rule
public final RedisTestServer redis = new RedisTestServer();
@Test
public void redisSessionStoreIsTheDefault() {
load(Collections.<Class<?>>singletonList(RedisAutoConfiguration.class));
validateSpringSessionUsesRedis();
this.output.expect(containsString("Spring Session store type is mandatory: set 'spring.session.store-type=redis' in your configuration"));
}
@Test
public void redisSessionStore() {
load(Collections.<Class<?>>singletonList(RedisAutoConfiguration.class),
"spring.session.store-type=redis");
validateSpringSessionUsesRedis();
this.output.expect(not(containsString("Spring Session store type is mandatory: set 'spring.session.store-type=redis' in your configuration")));
}
private void validateSpringSessionUsesRedis() {
RedisOperationsSessionRepository repository = validateSessionRepository(
RedisOperationsSessionRepository.class);
assertThat(repository.getSessionCreatedChannelPrefix())