DATAMONGO-348 - Added serialization support for lazy-loading for DBRefs.

This commit is contained in:
Thomas Darimont
2013-11-04 22:23:26 +01:00
committed by Oliver Gierke
parent df1c4496dc
commit 8fb390ee88
2 changed files with 80 additions and 3 deletions

View File

@@ -15,6 +15,10 @@
*/
package org.springframework.data.mongodb.core.convert;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInterceptor;
@@ -150,7 +154,8 @@ public class DefaultDbRefResolver implements DbRefResolver {
*
* @author Thomas Darimont
*/
static class LazyLoadingInterceptor implements MethodInterceptor, org.springframework.cglib.proxy.MethodInterceptor {
static class LazyLoadingInterceptor implements MethodInterceptor, org.springframework.cglib.proxy.MethodInterceptor,
Serializable {
private final DbRefResolverCallback callback;
private final MongoPersistentProperty property;
@@ -194,12 +199,33 @@ public class DefaultDbRefResolver implements DbRefResolver {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
ensureResolved();
return method.invoke(result, args);
}
private void ensureResolved() {
if (!resolved) {
this.result = resolve();
this.resolved = true;
}
}
return method.invoke(result, args);
private void writeObject(ObjectOutputStream out) throws IOException {
ensureResolved();
out.writeObject(this.result);
}
private void readObject(ObjectInputStream in) throws IOException {
try {
this.resolved = true; // Object is guaranteed to be resolved after serializations
this.result = in.readObject();
} catch (ClassNotFoundException e) {
throw new LazyLoadingException("Could not deserialize result", e);
}
}
/**

View File

@@ -21,6 +21,7 @@ import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import static org.springframework.data.mongodb.core.convert.LazyLoadingTestUtils.*;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
@@ -42,6 +43,7 @@ import org.springframework.data.mongodb.core.MongoExceptionTranslator;
import org.springframework.data.mongodb.core.convert.MappingMongoConverterUnitTests.Person;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.util.SerializationUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
@@ -256,6 +258,35 @@ public class DbRefMappingMongoConverterUnitTests {
assertThat(result.dbRefToConcreteTypeWithPersistenceConstructorWithoutDefaultConstructor.getValue(), is(value));
}
/**
* @see DATAMONGO-348
*/
@Test
public void lazyLoadingProxyForSerializableLazyDbRefOnConcreteType() {
String id = "42";
String value = "bubu";
MappingMongoConverter converterSpy = spy(converter);
doReturn(new BasicDBObject("_id", id).append("value", value)).when(converterSpy).readRef((DBRef) any());
BasicDBObject dbo = new BasicDBObject();
SerializableClassWithLazyDbRefs lazyDbRefs = new SerializableClassWithLazyDbRefs();
lazyDbRefs.dbRefToSerializableTarget = new SerializableLazyDbRefTarget(id, value);
converterSpy.write(lazyDbRefs, dbo);
SerializableClassWithLazyDbRefs result = converterSpy.read(SerializableClassWithLazyDbRefs.class, dbo);
SerializableClassWithLazyDbRefs deserializedResult = (SerializableClassWithLazyDbRefs) transport(result);
assertThat(deserializedResult.dbRefToSerializableTarget.getId(), is(id));
assertProxyIsResolved(deserializedResult.dbRefToSerializableTarget, true);
assertThat(deserializedResult.dbRefToSerializableTarget.getValue(), is(value));
}
private Object transport(Object result) {
return SerializationUtils.deserialize(SerializationUtils.serialize(result));
}
class MapDBRef {
@org.springframework.data.mongodb.core.mapping.DBRef Map<String, MapDBRefVal> map;
}
@@ -278,7 +309,16 @@ public class DbRefMappingMongoConverterUnitTests {
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) LazyDbRefTargetWithPeristenceConstructorWithoutDefaultConstructor dbRefToConcreteTypeWithPersistenceConstructorWithoutDefaultConstructor;
}
static class LazyDbRefTarget {
static class SerializableClassWithLazyDbRefs implements Serializable {
private static final long serialVersionUID = 1L;
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) SerializableLazyDbRefTarget dbRefToSerializableTarget;
}
static class LazyDbRefTarget implements Serializable {
private static final long serialVersionUID = 1L;
@Id String id;
String value;
@@ -336,4 +376,15 @@ public class DbRefMappingMongoConverterUnitTests {
super(id.toString(), value.toString());
}
}
static class SerializableLazyDbRefTarget extends LazyDbRefTarget implements Serializable {
public SerializableLazyDbRefTarget() {}
public SerializableLazyDbRefTarget(String id, String value) {
super(id, value);
}
private static final long serialVersionUID = 1L;
}
}