diff --git a/spring-data-redis/pom.xml b/spring-data-redis/pom.xml index 82f335124..abe27e7e4 100644 --- a/spring-data-redis/pom.xml +++ b/spring-data-redis/pom.xml @@ -13,8 +13,10 @@ + "[3.0.0, 4.0.0)" 03122010 1.5.2-SNAPSHOT + "[1.0.0,2.0.0)" @@ -78,6 +80,13 @@ runtime + + org.springframework + spring-oxm + ${org.springframework.version} + + + javax.annotation jsr250-api @@ -90,6 +99,13 @@ test + + com.thoughtworks.xstream + xstream + 1.3 + test + + junit junit diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/JdkSerializationRedisSerializer.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/JdkSerializationRedisSerializer.java index 303a73ace..202c9203d 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/JdkSerializationRedisSerializer.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/JdkSerializationRedisSerializer.java @@ -18,7 +18,6 @@ package org.springframework.data.keyvalue.redis.serializer; import org.springframework.core.convert.converter.Converter; import org.springframework.core.serializer.support.DeserializingConverter; import org.springframework.core.serializer.support.SerializingConverter; -import org.springframework.data.keyvalue.redis.UncategorizedRedisException; /** * Java Serialization Redis serializer. @@ -38,7 +37,7 @@ public class JdkSerializationRedisSerializer implements RedisSerializer try { return deserializer.convert(bytes); } catch (Exception ex) { - throw new UncategorizedRedisException("Cannot deserialize", ex); + throw new SerializationException("Cannot deserialize", ex); } } @@ -47,7 +46,7 @@ public class JdkSerializationRedisSerializer implements RedisSerializer try { return serializer.convert(object); } catch (Exception ex) { - throw new UncategorizedRedisException("Cannot serialize", ex); + throw new SerializationException("Cannot serialize", ex); } } } \ No newline at end of file diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/OxmSerializer.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/OxmSerializer.java new file mode 100644 index 000000000..74ddec929 --- /dev/null +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/OxmSerializer.java @@ -0,0 +1,101 @@ +/* + * Copyright 2011 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.keyvalue.redis.serializer; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.oxm.Marshaller; +import org.springframework.oxm.Unmarshaller; +import org.springframework.util.Assert; + +/** + * Serializer adapter on top of Spring's O/X Mapping. + * Delegates serialization/deserialization to OXM {@link Marshaller} and + * {@link Unmarshaller}. + * + * Note:Null objects are serialized as empty arrays. + * + * @author Costin Leau + */ +public class OxmSerializer implements InitializingBean, RedisSerializer { + + private Marshaller marshaller; + private Unmarshaller unmarshaller; + + public OxmSerializer() { + } + + public OxmSerializer(Marshaller marshaller, Unmarshaller unmarshaller) { + this.marshaller = marshaller; + this.unmarshaller = unmarshaller; + + afterPropertiesSet(); + } + + @Override + public void afterPropertiesSet() { + Assert.notNull(marshaller, "non-null marshaller required"); + Assert.notNull(unmarshaller, "non-null unmarshaller required"); + } + + /** + * @param marshaller The marshaller to set. + */ + public void setMarshaller(Marshaller marshaller) { + this.marshaller = marshaller; + } + + /** + * @param unmarshaller The unmarshaller to set. + */ + public void setUnmarshaller(Unmarshaller unmarshaller) { + this.unmarshaller = unmarshaller; + } + + @Override + public Object deserialize(byte[] bytes) throws SerializationException { + if (SerializerUtils.isEmpty(bytes)) { + return null; + } + + try { + return unmarshaller.unmarshal(new StreamSource(new ByteArrayInputStream(bytes))); + } catch (Exception ex) { + throw new SerializationException("Cannot deserialize bytes", ex); + } + } + + @Override + public byte[] serialize(Object t) throws SerializationException { + if (t == null) { + return SerializerUtils.EMPTY_ARRAY; + } + + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + StreamResult result = new StreamResult(stream); + try { + marshaller.marshal(t, result); + } catch (Exception ex) { + throw new SerializationException("Cannot serialize object", ex); + } + return stream.toByteArray(); + } +} \ No newline at end of file diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/RedisSerializer.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/RedisSerializer.java index 89ddd5e31..910a4333c 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/RedisSerializer.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/RedisSerializer.java @@ -31,7 +31,7 @@ public interface RedisSerializer { * @param t object to serialize * @return the equivalent binary data */ - byte[] serialize(T t); + byte[] serialize(T t) throws SerializationException; /** * Deserialize an object from the given binary data. @@ -39,5 +39,5 @@ public interface RedisSerializer { * @param bytes object binary representation * @return the equivalent object instance */ - T deserialize(byte[] bytes); + T deserialize(byte[] bytes) throws SerializationException; } diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/SerializationException.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/SerializationException.java new file mode 100644 index 000000000..215b8ece1 --- /dev/null +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/SerializationException.java @@ -0,0 +1,45 @@ +/* + * Copyright 2011 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.keyvalue.redis.serializer; + +import org.springframework.core.NestedRuntimeException; + +/** + * Generic exception indicating a serialization/deserialization error. + * + * @author Costin Leau + */ +public class SerializationException extends NestedRuntimeException { + + /** + * Constructs a new SerializationException instance. + * + * @param msg + * @param cause + */ + public SerializationException(String msg, Throwable cause) { + super(msg, cause); + } + + /** + * Constructs a new SerializationException instance. + * + * @param msg + */ + public SerializationException(String msg) { + super(msg); + } +} diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/SerializerUtils.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/SerializerUtils.java index d78954b9e..aee3832b6 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/SerializerUtils.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/serializer/SerializerUtils.java @@ -21,6 +21,7 @@ package org.springframework.data.keyvalue.redis.serializer; * @author Costin Leau */ abstract class SerializerUtils { + static final byte[] EMPTY_ARRAY = new byte[0]; static boolean isEmpty(byte[] data) { return (data == null || data.length == 0); diff --git a/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/serializer/SimpleRedisSerializerTests.java b/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/serializer/SimpleRedisSerializerTests.java index c053bd703..3c82b3f6d 100644 --- a/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/serializer/SimpleRedisSerializerTests.java +++ b/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/serializer/SimpleRedisSerializerTests.java @@ -25,8 +25,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.data.keyvalue.redis.Address; import org.springframework.data.keyvalue.redis.Person; -import org.springframework.data.keyvalue.redis.serializer.RedisSerializer; -import org.springframework.data.keyvalue.redis.serializer.JdkSerializationRedisSerializer; +import org.springframework.oxm.xstream.XStreamMarshaller; public class SimpleRedisSerializerTests { @@ -139,4 +138,17 @@ public class SimpleRedisSerializerTests { assertEquals(p1, serializer.deserialize(serializer.serialize(p1))); assertEquals(p1, serializer.deserialize(serializer.serialize(p1))); } + + @Test + public void testOxmSerializer() throws Exception { + XStreamMarshaller xstream = new XStreamMarshaller(); + xstream.afterPropertiesSet(); + + OxmSerializer serializer = new OxmSerializer(xstream, xstream); + + String value = UUID.randomUUID().toString(); + Person p1 = new Person(value, value, 1, new Address(value, 2)); + assertEquals(p1, serializer.deserialize(serializer.serialize(p1))); + assertEquals(p1, serializer.deserialize(serializer.serialize(p1))); + } } \ No newline at end of file diff --git a/spring-data-redis/template.mf b/spring-data-redis/template.mf index a37ef7cbb..6adb8d8ca 100644 --- a/spring-data-redis/template.mf +++ b/spring-data-redis/template.mf @@ -5,24 +5,23 @@ Bundle-ManifestVersion: 2 Import-Package: sun.reflect;version="0";resolution:=optional Import-Template: - org.springframework.beans.*;version="[3.0.0, 4.0.0)", - org.springframework.context.*;version="[3.0.0, 4.0.0)", - org.springframework.core.*;version="[3.0.0, 4.0.0)", - org.springframework.dao.*;version="[3.0.0, 4.0.0)", - org.springframework.scheduling.*;version="[3.0.0, 4.0.0)", - org.springframework.util.*;version="[3.0.0, 4.0.0)", - org.springframework.data.core.*;version="[1.0.0, 2.0.0)", - org.springframework.data.*;version="[1.0.0, 2.0.0)", - org.springframework.data.persistence.*;version="[1.0.0, 2.0.0)", - org.springframework.data.document.*;version="[1.0.0, 2.0.0)", + org.springframework.beans.*;version=${spring.range}, + org.springframework.context.*;version=${spring.range}, + org.springframework.core.*;version=${spring.range}, + org.springframework.dao.*;version=${spring.range}, + org.springframework.scheduling.*;resolution:="optional";version=${spring.range}, + org.springframework.util.*;version=${spring.range}, + org.springframework.oxm.*;resolution:="optional";version=${spring.range}, + org.springframework.transaction.support.*;version=${spring.range}, org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional, org.apache.commons.logging.*;version="[1.1.1, 2.0.0)", + org.springframework.data.keyvalue.*;version=${version}, org.w3c.dom.*;version="0", + javax.xml.transform.*;resolution:="optional";version="0", org.jredis.*;version="[1.0.0, 2.0.0)", org.jredis.ri.alphazero.*;version="[1.0.0, 2.0.0)", - org.springframework.commons.serializer.*;version="[1.0.0, 2.0.0)", - org.springframework.transaction.support.*;version="[3.0.0, 4.0.0)", - redis.clients.jedis.*;version="[1.0.0, 2.0.0)", - redis.clients.util.*;version="[1.0.0, 2.0.0)", + redis.clients.jedis.*;version=${jedis.range}, + redis.clients.util.*;version=${jedis.range}, org.apache.commons.pool.impl.*;version="[1.0.0, 3.0.0)" +