Update Redis configuration to use bean classloader

Spring Session 2.0 made changes to Redis configuration facilities so that the `RedisTemplate` used by `RedisOperationsSessionRepository` isn't exposed as a bean anymore. This has a consequence that bean `ClassLoader` isn't applied automatically which causes issues in Spring Boot applications that use DevTools.

This commit restores the previous behavior by updating Redis configuration classes to implement `BeanClassLoaderAware` callback and apply the application `ClassLoader` to `RedisTemplate`. The analogous change was made to reactive Redis configuration.

Closes gh-968
This commit is contained in:
Vedran Pavic
2018-01-18 21:36:28 +01:00
parent d0ee9fd16a
commit ffa1bca898
2 changed files with 35 additions and 20 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2018 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.
@@ -23,6 +23,7 @@ import java.util.concurrent.Executor;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
@@ -70,7 +71,8 @@ import org.springframework.util.StringValueResolver;
@Configuration
@EnableScheduling
public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguration
implements EmbeddedValueResolverAware, ImportAware, SchedulingConfigurer {
implements BeanClassLoaderAware, EmbeddedValueResolverAware, ImportAware,
SchedulingConfigurer {
static final String DEFAULT_CLEANUP_CRON = "0 * * * * *";
@@ -94,12 +96,13 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
private Executor redisSubscriptionExecutor;
private ClassLoader classLoader;
private StringValueResolver embeddedValueResolver;
@Bean
public RedisOperationsSessionRepository sessionRepository() {
RedisTemplate<Object, Object> redisTemplate = createRedisTemplate(
this.redisConnectionFactory, this.defaultRedisSerializer);
RedisTemplate<Object, Object> redisTemplate = createRedisTemplate();
RedisOperationsSessionRepository sessionRepository = new RedisOperationsSessionRepository(
redisTemplate);
sessionRepository.setApplicationEventPublisher(this.applicationEventPublisher);
@@ -205,6 +208,11 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
this.redisSubscriptionExecutor = redisSubscriptionExecutor;
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
this.embeddedValueResolver = resolver;
@@ -235,16 +243,15 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
this.cleanupCron);
}
private static RedisTemplate<Object, Object> createRedisTemplate(
RedisConnectionFactory redisConnectionFactory,
RedisSerializer<Object> defaultRedisSerializer) {
private RedisTemplate<Object, Object> createRedisTemplate() {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
if (defaultRedisSerializer != null) {
redisTemplate.setDefaultSerializer(defaultRedisSerializer);
if (this.defaultRedisSerializer != null) {
redisTemplate.setDefaultSerializer(this.defaultRedisSerializer);
}
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setConnectionFactory(this.redisConnectionFactory);
redisTemplate.setBeanClassLoader(this.classLoader);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2018 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.session.data.redis.config.annotation.web.server;
import java.util.Map;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.EmbeddedValueResolverAware;
@@ -53,11 +54,7 @@ import org.springframework.web.server.session.WebSessionManager;
*/
@Configuration
public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration
implements EmbeddedValueResolverAware, ImportAware {
private static final RedisSerializer<String> keySerializer = new StringRedisSerializer();
private static final RedisSerializer<Object> valueSerializer = new JdkSerializationRedisSerializer();
implements BeanClassLoaderAware, EmbeddedValueResolverAware, ImportAware {
private Integer maxInactiveIntervalInSeconds = MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS;
@@ -67,12 +64,15 @@ public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration
private ReactiveRedisConnectionFactory redisConnectionFactory;
private ClassLoader classLoader;
private StringValueResolver embeddedValueResolver;
@Bean
public ReactiveRedisOperationsSessionRepository sessionRepository() {
ReactiveRedisTemplate<String, Object> reactiveRedisTemplate = createReactiveRedisTemplate();
ReactiveRedisOperationsSessionRepository sessionRepository = new ReactiveRedisOperationsSessionRepository(
createDefaultTemplate(this.redisConnectionFactory));
reactiveRedisTemplate);
sessionRepository
.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
if (StringUtils.hasText(this.redisNamespace)) {
@@ -107,6 +107,11 @@ public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration
this.redisConnectionFactory = redisConnectionFactoryToUse;
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
this.embeddedValueResolver = resolver;
@@ -127,12 +132,15 @@ public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration
this.redisFlushMode = attributes.getEnum("redisFlushMode");
}
private static ReactiveRedisTemplate<String, Object> createDefaultTemplate(
ReactiveRedisConnectionFactory connectionFactory) {
private ReactiveRedisTemplate<String, Object> createReactiveRedisTemplate() {
RedisSerializer<String> keySerializer = new StringRedisSerializer();
RedisSerializer<Object> valueSerializer = new JdkSerializationRedisSerializer(
this.classLoader);
RedisSerializationContext<String, Object> serializationContext = RedisSerializationContext
.<String, Object>newSerializationContext(valueSerializer)
.key(keySerializer).hashKey(keySerializer).build();
return new ReactiveRedisTemplate<>(connectionFactory, serializationContext);
return new ReactiveRedisTemplate<>(this.redisConnectionFactory,
serializationContext);
}
}