Skip to content

Commit 77630d0

Browse files
mp911dechristophstrobl
authored andcommitted
DATAREDIS-427 - Allow construction of customized JdkSerializationRedisSerializer.
We now allow constructing JdkSerializationRedisSerializer using an own class loader and by specifying custom converters. Using an own class-loader: new JdkSerializationRedisSerializer(classLoader) Using own converters (Serializer/Deserializer): new JdkSerializationRedisSerializer(new SerializingConverter(), new DeserializingConverter(new DefaultDeserializer(classLoader))) Original Pull Request: #179
1 parent 648e35a commit 77630d0

File tree

3 files changed

+128
-5
lines changed

3 files changed

+128
-5
lines changed

src/main/java/org/springframework/data/redis/serializer/JdkSerializationRedisSerializer.java

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2013 the original author or authors.
2+
* Copyright 2011-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,17 +18,53 @@
1818
import org.springframework.core.convert.converter.Converter;
1919
import org.springframework.core.serializer.support.DeserializingConverter;
2020
import org.springframework.core.serializer.support.SerializingConverter;
21+
import org.springframework.util.Assert;
2122

2223
/**
23-
* Java Serialization Redis serializer. Delegates to the default (Java based) serializer in Spring 3.
24+
* Java Serialization Redis serializer. Delegates to the default (Java based) {@link DefaultSerializer serializer} and
25+
* {@link DefaultDeserializer}. This {@link RedisSerializer serializer} can be constructed with either custom
26+
* {@link ClassLoader} or own {@link Converter converters}.
2427
*
2528
* @author Mark Pollack
2629
* @author Costin Leau
30+
* @author Mark Paluch
2731
*/
2832
public class JdkSerializationRedisSerializer implements RedisSerializer<Object> {
2933

30-
private Converter<Object, byte[]> serializer = new SerializingConverter();
31-
private Converter<byte[], Object> deserializer = new DeserializingConverter();
34+
private final Converter<Object, byte[]> serializer;
35+
private final Converter<byte[], Object> deserializer;
36+
37+
/**
38+
* Creates a new {@link JdkSerializationRedisSerializer} using the default class loader.
39+
*/
40+
public JdkSerializationRedisSerializer() {
41+
this(new SerializingConverter(), new DeserializingConverter());
42+
}
43+
44+
/**
45+
* Creates a new {@link JdkSerializationRedisSerializer} using a {@link ClassLoader}.
46+
*
47+
* @param classLoader
48+
*/
49+
public JdkSerializationRedisSerializer(ClassLoader classLoader) {
50+
this(new SerializingConverter(), new DeserializingConverter(classLoader));
51+
}
52+
53+
/**
54+
* Creates a new {@link JdkSerializationRedisSerializer} using a {@link Converter converters} to serialize and
55+
* deserialize objects.
56+
*
57+
* @param serializer must not be {@literal null}
58+
* @param deserializer must not be {@literal null}
59+
*/
60+
public JdkSerializationRedisSerializer(Converter<Object, byte[]> serializer, Converter<byte[], Object> deserializer) {
61+
62+
Assert.notNull("Serializer must not be null!");
63+
Assert.notNull("Deserializer must not be null!");
64+
65+
this.serializer = serializer;
66+
this.deserializer = deserializer;
67+
}
3268

3369
public Object deserialize(byte[] bytes) {
3470
if (SerializationUtils.isEmpty(bytes)) {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2016 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.data.redis.serializer;
18+
19+
import java.io.Serializable;
20+
21+
/**
22+
* @author Mark Paluch
23+
*/
24+
public class SerializableDomainClass implements Serializable {
25+
26+
}

src/test/java/org/springframework/data/redis/serializer/SimpleRedisSerializerTests.java

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2013 the original author or authors.
2+
* Copyright 2011-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,9 +15,13 @@
1515
*/
1616
package org.springframework.data.redis.serializer;
1717

18+
import static org.hamcrest.CoreMatchers.*;
1819
import static org.junit.Assert.*;
1920

21+
import java.io.IOException;
22+
import java.io.InputStream;
2023
import java.io.Serializable;
24+
import java.net.URL;
2125
import java.util.UUID;
2226

2327
import org.junit.After;
@@ -26,9 +30,11 @@
2630
import org.springframework.data.redis.Address;
2731
import org.springframework.data.redis.Person;
2832
import org.springframework.oxm.xstream.XStreamMarshaller;
33+
import org.springframework.util.StreamUtils;
2934

3035
/**
3136
* @author Jennifer Hickey
37+
* @author Mark Paluch
3238
*/
3339
public class SimpleRedisSerializerTests {
3440

@@ -119,6 +125,22 @@ private void verifySerializedObjects(Object... objects) {
119125
}
120126
}
121127

128+
@Test
129+
public void jdkSerializerShouldUseCustomClassLoader() throws ClassNotFoundException {
130+
131+
ClassLoader customClassLoader = new CustomClassLoader();
132+
133+
JdkSerializationRedisSerializer serializer = new JdkSerializationRedisSerializer(customClassLoader);
134+
SerializableDomainClass domainClass = new SerializableDomainClass();
135+
136+
byte[] serialized = serializer.serialize(domainClass);
137+
Object deserialized = serializer.deserialize(serialized);
138+
139+
assertThat(deserialized.getClass().getName(), is(equalTo(SerializableDomainClass.class.getName())));
140+
assertThat(deserialized, is(not(instanceOf(SerializableDomainClass.class))));
141+
assertThat(deserialized.getClass().getClassLoader(), is(equalTo(customClassLoader)));
142+
}
143+
122144
@Test
123145
public void testStringEncodedSerialization() {
124146
String value = UUID.randomUUID().toString();
@@ -157,4 +179,43 @@ public void testJsonSerializer() throws Exception {
157179
assertEquals(p1, serializer.deserialize(serializer.serialize(p1)));
158180
}
159181

182+
/**
183+
* Custom class loader that loads class files from the test's class path. This {@link ClassLoader} does not delegate
184+
* to a parent class loader to truly load classes that are defined by this class loader and not interfere with any
185+
* parent class loader. The class loader uses simple class definition which is fine for the test but do not use this
186+
* as sample for production class loaders.
187+
*/
188+
private static class CustomClassLoader extends ClassLoader {
189+
190+
public CustomClassLoader() {
191+
super(null);
192+
}
193+
194+
@Override
195+
protected Class<?> findClass(String name) throws ClassNotFoundException {
196+
197+
URL resource = SimpleRedisSerializerTests.class.getResource("/" + name.replace('.', '/') + ".class");
198+
199+
InputStream is = null;
200+
try {
201+
202+
is = resource.openStream();
203+
byte[] bytes = StreamUtils.copyToByteArray(is);
204+
return defineClass(name, bytes, 0, bytes.length);
205+
} catch (IOException o_O) {
206+
throw new ClassNotFoundException("Cannot read class file", o_O);
207+
} finally {
208+
209+
if (is != null) {
210+
try {
211+
is.close();
212+
} catch (IOException e) {
213+
// ignore
214+
}
215+
}
216+
}
217+
218+
}
219+
220+
}
160221
}

0 commit comments

Comments
 (0)