diff --git a/src/main/java/org/springframework/data/redis/cache/RedisCacheConfiguration.java b/src/main/java/org/springframework/data/redis/cache/RedisCacheConfiguration.java index baec542f3..214e1a0b3 100644 --- a/src/main/java/org/springframework/data/redis/cache/RedisCacheConfiguration.java +++ b/src/main/java/org/springframework/data/redis/cache/RedisCacheConfiguration.java @@ -26,6 +26,7 @@ import org.springframework.core.convert.converter.ConverterRegistry; import org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.format.support.DefaultFormattingConversionService; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -76,9 +77,9 @@ public class RedisCacheConfiguration { *
default prefix
*
[the actual cache name]
*
key serializer
- *
StringRedisSerializer.class
+ *
{@link org.springframework.data.redis.serializer.StringRedisSerializer}
*
value serializer
- *
JdkSerializationRedisSerializer.class
+ *
{@link org.springframework.data.redis.serializer.JdkSerializationRedisSerializer}
*
conversion service
*
{@link DefaultFormattingConversionService} with {@link #registerDefaultConverters(ConverterRegistry) default} * cache key converters
@@ -87,6 +88,33 @@ public class RedisCacheConfiguration { * @return new {@link RedisCacheConfiguration}. */ public static RedisCacheConfiguration defaultCacheConfig() { + return defaultCacheConfig(null); + } + + /** + * Create default {@link RedisCacheConfiguration} given {@link ClassLoader} using the following: + *
+ *
key expiration
+ *
eternal
+ *
cache null values
+ *
yes
+ *
prefix cache keys
+ *
yes
+ *
default prefix
+ *
[the actual cache name]
+ *
key serializer
+ *
{@link org.springframework.data.redis.serializer.StringRedisSerializer}
+ *
value serializer
+ *
{@link org.springframework.data.redis.serializer.JdkSerializationRedisSerializer}
+ *
conversion service
+ *
{@link DefaultFormattingConversionService} with {@link #registerDefaultConverters(ConverterRegistry) default} + * cache key converters
+ *
+ * + * @return new {@link RedisCacheConfiguration}. + * @since 2.1 + */ + public static RedisCacheConfiguration defaultCacheConfig(@Nullable ClassLoader classLoader) { DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(); @@ -94,7 +122,7 @@ public class RedisCacheConfiguration { return new RedisCacheConfiguration(Duration.ZERO, true, true, CacheKeyPrefix.simple(), SerializationPair.fromSerializer(RedisSerializer.string()), - SerializationPair.fromSerializer(RedisSerializer.java()), conversionService); + SerializationPair.fromSerializer(RedisSerializer.java(classLoader)), conversionService); } /** diff --git a/src/main/java/org/springframework/data/redis/serializer/JdkSerializationRedisSerializer.java b/src/main/java/org/springframework/data/redis/serializer/JdkSerializationRedisSerializer.java index 512ed8f99..f709f7815 100644 --- a/src/main/java/org/springframework/data/redis/serializer/JdkSerializationRedisSerializer.java +++ b/src/main/java/org/springframework/data/redis/serializer/JdkSerializationRedisSerializer.java @@ -51,7 +51,7 @@ public class JdkSerializationRedisSerializer implements RedisSerializer * @param classLoader * @since 1.7 */ - public JdkSerializationRedisSerializer(ClassLoader classLoader) { + public JdkSerializationRedisSerializer(@Nullable ClassLoader classLoader) { this(new SerializingConverter(), new DeserializingConverter(classLoader)); } diff --git a/src/main/java/org/springframework/data/redis/serializer/RedisSerializationContext.java b/src/main/java/org/springframework/data/redis/serializer/RedisSerializationContext.java index e6208adeb..9d931f771 100644 --- a/src/main/java/org/springframework/data/redis/serializer/RedisSerializationContext.java +++ b/src/main/java/org/springframework/data/redis/serializer/RedisSerializationContext.java @@ -87,6 +87,28 @@ public interface RedisSerializationContext { return just(SerializationPair.raw()); } + /** + * Creates a new {@link RedisSerializationContext} using {@link JdkSerializationRedisSerializer}. + * + * @return + * @since 2.1 + */ + static RedisSerializationContext java() { + return fromSerializer(RedisSerializer.java()); + } + + /** + * Creates a new {@link RedisSerializationContext} using {@link JdkSerializationRedisSerializer} given + * {@link ClassLoader}. + * + * @param classLoader the classloader to use. + * @return + * @since 2.1 + */ + static RedisSerializationContext java(ClassLoader classLoader) { + return fromSerializer(RedisSerializer.java(classLoader)); + } + /** * Creates a new {@link RedisSerializationContext} using a {@link StringRedisSerializer}. * diff --git a/src/main/java/org/springframework/data/redis/serializer/RedisSerializer.java b/src/main/java/org/springframework/data/redis/serializer/RedisSerializer.java index 6ad357e04..a5a2f9330 100644 --- a/src/main/java/org/springframework/data/redis/serializer/RedisSerializer.java +++ b/src/main/java/org/springframework/data/redis/serializer/RedisSerializer.java @@ -54,7 +54,19 @@ public interface RedisSerializer { * @since 2.1 */ static RedisSerializer java() { - return new JdkSerializationRedisSerializer(); + return java(null); + } + + /** + * Obtain a {@link RedisSerializer} using java serialization with the given {@link ClassLoader}.
+ * Note: Ensure that your domain objects are actually {@link java.io.Serializable serializable}. + * + * @param classLoader the classloader to use.. + * @return never {@literal null}. + * @since 2.1 + */ + static RedisSerializer java(@Nullable ClassLoader classLoader) { + return new JdkSerializationRedisSerializer(classLoader); } /** diff --git a/src/test/java/org/springframework/data/redis/cache/RedisCacheConfigurationUnitTests.java b/src/test/java/org/springframework/data/redis/cache/RedisCacheConfigurationUnitTests.java new file mode 100644 index 000000000..91e460beb --- /dev/null +++ b/src/test/java/org/springframework/data/redis/cache/RedisCacheConfigurationUnitTests.java @@ -0,0 +1,46 @@ +/* + * Copyright 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. + * 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.data.redis.cache; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.Test; +import org.springframework.beans.DirectFieldAccessor; +import org.springframework.instrument.classloading.ShadowingClassLoader; + +/** + * Unit tests for {@link RedisCacheConfiguration}. + * + * @author Mark Paluch + */ +public class RedisCacheConfigurationUnitTests { + + @Test // DATAREDIS-763 + public void shouldSetClassLoader() { + + ShadowingClassLoader classLoader = new ShadowingClassLoader(getClass().getClassLoader()); + + RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(classLoader); + + Object adapter = new DirectFieldAccessor(config.getValueSerializationPair().getReader()) + .getPropertyValue("serializer"); + Object deserializerConverter = new DirectFieldAccessor(adapter).getPropertyValue("deserializer"); + Object deserializer = new DirectFieldAccessor(deserializerConverter).getPropertyValue("deserializer"); + Object usedClassLoader = new DirectFieldAccessor(deserializer).getPropertyValue("classLoader"); + + assertThat(usedClassLoader).isSameAs(classLoader); + } +} diff --git a/src/test/java/org/springframework/data/redis/core/ReactiveOperationsTestParams.java b/src/test/java/org/springframework/data/redis/core/ReactiveOperationsTestParams.java index a0a1e5841..6b24ba7da 100644 --- a/src/test/java/org/springframework/data/redis/core/ReactiveOperationsTestParams.java +++ b/src/test/java/org/springframework/data/redis/core/ReactiveOperationsTestParams.java @@ -97,17 +97,18 @@ abstract public class ReactiveOperationsTestParams { poolingConfiguration); poolingConnectionFactory.afterPropertiesSet(); - JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer(); + ReactiveRedisTemplate objectTemplate = new ReactiveRedisTemplate<>(lettuceConnectionFactory, - RedisSerializationContext.fromSerializer(jdkSerializationRedisSerializer)); + RedisSerializationContext.java(ReactiveOperationsTestParams.class.getClassLoader())); ReactiveRedisTemplate pooledObjectTemplate = new ReactiveRedisTemplate<>(poolingConnectionFactory, - RedisSerializationContext.fromSerializer(jdkSerializationRedisSerializer)); + RedisSerializationContext.java()); StringRedisSerializer stringRedisSerializer = StringRedisSerializer.UTF_8; ReactiveRedisTemplate stringTemplate = new ReactiveRedisTemplate<>(lettuceConnectionFactory, RedisSerializationContext.fromSerializer(stringRedisSerializer)); + JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer(); GenericToStringSerializer longToStringSerializer = new GenericToStringSerializer(Long.class); ReactiveRedisTemplate longTemplate = new ReactiveRedisTemplate<>(lettuceConnectionFactory, RedisSerializationContext. newSerializationContext(jdkSerializationRedisSerializer)