diff --git a/pom.xml b/pom.xml index e6d868411f..6a0be5760d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-redis - 1.8.0.BUILD-SNAPSHOT + 1.8.0.DATAREDIS-501-SNAPSHOT Spring Data Redis diff --git a/src/main/java/org/springframework/data/redis/core/RedisTemplate.java b/src/main/java/org/springframework/data/redis/core/RedisTemplate.java index 7a9dcb9ade..f2b9677ce9 100644 --- a/src/main/java/org/springframework/data/redis/core/RedisTemplate.java +++ b/src/main/java/org/springframework/data/redis/core/RedisTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2015 the original author or authors. + * Copyright 2011-2016 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. @@ -26,6 +26,7 @@ import java.util.Set; import java.util.concurrent.TimeUnit; +import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.dao.DataAccessException; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.redis.RedisSystemException; @@ -75,13 +76,14 @@ * @param the Redis value type against which the template works * @see StringRedisTemplate */ -public class RedisTemplate extends RedisAccessor implements RedisOperations { +public class RedisTemplate extends RedisAccessor implements RedisOperations, BeanClassLoaderAware { private boolean enableTransactionSupport = false; private boolean exposeConnection = false; private boolean initialized = false; private boolean enableDefaultSerializer = true; - private RedisSerializer defaultSerializer = new JdkSerializationRedisSerializer(); + private RedisSerializer defaultSerializer; + private ClassLoader classLoader; private RedisSerializer keySerializer = null; private RedisSerializer valueSerializer = null; @@ -104,10 +106,19 @@ public class RedisTemplate extends RedisAccessor implements RedisOperation public RedisTemplate() {} public void afterPropertiesSet() { + super.afterPropertiesSet(); + boolean defaultUsed = false; + if (defaultSerializer == null) { + + defaultSerializer = new JdkSerializationRedisSerializer( + classLoader != null ? classLoader : this.getClass().getClassLoader()); + } + if (enableDefaultSerializer) { + if (keySerializer == null) { keySerializer = defaultSerializer; defaultUsed = true; @@ -1096,4 +1107,16 @@ public void setEnableTransactionSupport(boolean enableTransactionSupport) { this.enableTransactionSupport = enableTransactionSupport; } + /** + * Set the {@link ClassLoader} to be used for the default {@link JdkSerializationRedisSerializer} in case no other + * {@link RedisSerializer} is explicitly set as the default one. + * + * @param resourceLoader can be {@literal null}. + * @see org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader + * @since 1.8 + */ + @Override + public void setBeanClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } } diff --git a/src/test/java/org/springframework/data/redis/core/RedisTemplateUnitTests.java b/src/test/java/org/springframework/data/redis/core/RedisTemplateUnitTests.java index 9102f6ef42..9806bcaa11 100644 --- a/src/test/java/org/springframework/data/redis/core/RedisTemplateUnitTests.java +++ b/src/test/java/org/springframework/data/redis/core/RedisTemplateUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-2016 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. @@ -15,9 +15,14 @@ */ package org.springframework.data.redis.core; +import static org.hamcrest.core.Is.*; +import static org.hamcrest.core.IsNull.*; +import static org.junit.Assert.*; import static org.mockito.Matchers.*; import static org.mockito.Mockito.*; +import java.io.Serializable; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -25,6 +30,8 @@ import org.mockito.runners.MockitoJUnitRunner; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; +import org.springframework.instrument.classloading.ShadowingClassLoader; /** * @author Christoph Strobl @@ -32,14 +39,14 @@ @RunWith(MockitoJUnitRunner.class) public class RedisTemplateUnitTests { - private RedisTemplate template; + private RedisTemplate template; private @Mock RedisConnectionFactory connectionFactoryMock; private @Mock RedisConnection redisConnectionMock; @Before public void setUp() { - template = new RedisTemplate(); + template = new RedisTemplate(); template.setConnectionFactory(connectionFactoryMock); when(connectionFactoryMock.getConnection()).thenReturn(redisConnectionMock); @@ -66,4 +73,29 @@ public void slaveOfNoOneIsDelegatedToConnectionCorrectly() { verify(redisConnectionMock, times(1)).slaveOfNoOne(); } + /** + * @see DATAREDIS-501 + */ + @Test + public void templateShouldPassOnAndUseResoureLoaderClassLoaderToDefaultJdkSerializerWhenNotAlreadySet() { + + ShadowingClassLoader scl = new ShadowingClassLoader(ClassLoader.getSystemClassLoader()); + + template = new RedisTemplate(); + template.setConnectionFactory(connectionFactoryMock); + template.setBeanClassLoader(scl); + template.afterPropertiesSet(); + + when(redisConnectionMock.get(any(byte[].class))) + .thenReturn(new JdkSerializationRedisSerializer().serialize(new SomeArbitrarySeriaizableObject())); + + Object deserialized = template.opsForValue().get("spring"); + assertThat(deserialized, notNullValue()); + assertThat(deserialized.getClass().getClassLoader(), is((ClassLoader) scl)); + } + + static class SomeArbitrarySeriaizableObject implements Serializable { + private static final long serialVersionUID = -5973659324040506423L; + } + }