Browse Source

DATAMONGO-880 - Minor polishing in lazy-loading area.

Took the change to add @since tags to the types introduced for lazy loading. Polished JavaDoc where necessary. Removed methods solely existing for testing purposes and use reflection in tests to minimize the API being published.
pull/131/merge
Oliver Gierke 12 years ago
parent
commit
a09183d2eb
  1. 8
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java
  2. 54
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java
  3. 9
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java
  4. 6
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java
  5. 7
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingTestUtils.java

8
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2014 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.
@ -24,10 +24,16 @@ import com.mongodb.DBRef; @@ -24,10 +24,16 @@ import com.mongodb.DBRef;
* Used to resolve associations annotated with {@link org.springframework.data.mongodb.core.mapping.DBRef}.
*
* @author Thomas Darimont
* @author Oliver Gierke
* @since 1.4
*/
public interface DbRefResolver {
/**
* Resolves the given {@link DBRef} into an object of the given {@link MongoPersistentProperty}'s type. The method
* might return a proxy object for the {@link DBRef} or resolve it immediately. In both cases the
* {@link DbRefResolverCallback} will be used to obtain the actual backing object.
*
* @param property will never be {@literal null}.
* @param dbref the {@link DBRef} to resolve.
* @param callback will never be {@literal null}.

54
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java

@ -51,6 +51,7 @@ import com.mongodb.DBRef; @@ -51,6 +51,7 @@ import com.mongodb.DBRef;
*
* @author Thomas Darimont
* @author Oliver Gierke
* @since 1.4
*/
public class DefaultDbRefResolver implements DbRefResolver {
@ -109,7 +110,7 @@ public class DefaultDbRefResolver implements DbRefResolver { @@ -109,7 +110,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
* eventually resolve the value of the property.
*
* @param property must not be {@literal null}.
* @param dbref
* @param dbref can be {@literal null}.
* @param callback must not be {@literal null}.
* @return
*/
@ -144,7 +145,9 @@ public class DefaultDbRefResolver implements DbRefResolver { @@ -144,7 +145,9 @@ public class DefaultDbRefResolver implements DbRefResolver {
}
/**
* @param property
* Returns whether the property shall be resolved lazily.
*
* @param property must not be {@literal null}.
* @return
*/
private boolean isLazyDbRef(MongoPersistentProperty property) {
@ -157,12 +160,12 @@ public class DefaultDbRefResolver implements DbRefResolver { @@ -157,12 +160,12 @@ public class DefaultDbRefResolver implements DbRefResolver {
* guaranteed to be performed only once.
*
* @author Thomas Darimont
* @author Oliver Gierke
*/
static class LazyLoadingInterceptor implements MethodInterceptor, org.springframework.cglib.proxy.MethodInterceptor,
Serializable {
private static final Method initializeMethod;
private static final Method toDBRefMethod;
private static final Method INITIALIZE_METHOD, TO_DBREF_METHOD;
private final DbRefResolverCallback callback;
private final MongoPersistentProperty property;
@ -174,8 +177,8 @@ public class DefaultDbRefResolver implements DbRefResolver { @@ -174,8 +177,8 @@ public class DefaultDbRefResolver implements DbRefResolver {
static {
try {
initializeMethod = LazyLoadingProxy.class.getMethod("initialize");
toDBRefMethod = LazyLoadingProxy.class.getMethod("toDBRef");
INITIALIZE_METHOD = LazyLoadingProxy.class.getMethod("initialize");
TO_DBREF_METHOD = LazyLoadingProxy.class.getMethod("toDBRef");
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -186,7 +189,7 @@ public class DefaultDbRefResolver implements DbRefResolver { @@ -186,7 +189,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
* {@link PersistenceExceptionTranslator} and {@link DbRefResolverCallback}.
*
* @param property must not be {@literal null}.
* @param dbref
* @param dbref can be {@literal null}.
* @param callback must not be {@literal null}.
*/
public LazyLoadingInterceptor(MongoPersistentProperty property, DBRef dbref,
@ -209,11 +212,11 @@ public class DefaultDbRefResolver implements DbRefResolver { @@ -209,11 +212,11 @@ public class DefaultDbRefResolver implements DbRefResolver {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
if (invocation.getMethod().equals(initializeMethod)) {
if (invocation.getMethod().equals(INITIALIZE_METHOD)) {
return ensureResolved();
}
if (invocation.getMethod().equals(toDBRefMethod)) {
if (invocation.getMethod().equals(TO_DBREF_METHOD)) {
return this.dbref;
}
@ -227,17 +230,22 @@ public class DefaultDbRefResolver implements DbRefResolver { @@ -227,17 +230,22 @@ public class DefaultDbRefResolver implements DbRefResolver {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
if (method.equals(initializeMethod)) {
if (INITIALIZE_METHOD.equals(method)) {
return ensureResolved();
}
if (method.equals(toDBRefMethod)) {
if (TO_DBREF_METHOD.equals(method)) {
return this.dbref;
}
return ReflectionUtils.isObjectMethod(method) ? method.invoke(obj, args) : method.invoke(ensureResolved(), args);
}
/**
* Will trigger the resolution if the proxy is not resolved already or return a previously resolved result.
*
* @return
*/
private Object ensureResolved() {
if (!resolved) {
@ -248,16 +256,28 @@ public class DefaultDbRefResolver implements DbRefResolver { @@ -248,16 +256,28 @@ public class DefaultDbRefResolver implements DbRefResolver {
return this.result;
}
/**
* Callback method for serialization.
*
* @param out
* @throws IOException
*/
private void writeObject(ObjectOutputStream out) throws IOException {
ensureResolved();
out.writeObject(this.result);
}
/**
* Callback method for deserialization.
*
* @param in
* @throws IOException
*/
private void readObject(ObjectInputStream in) throws IOException {
try {
this.resolved = true; // Object is guaranteed to be resolved after serializations
this.resolved = true;
this.result = in.readObject();
} catch (ClassNotFoundException e) {
throw new LazyLoadingException("Could not deserialize result", e);
@ -265,6 +285,8 @@ public class DefaultDbRefResolver implements DbRefResolver { @@ -265,6 +285,8 @@ public class DefaultDbRefResolver implements DbRefResolver {
}
/**
* Resolves the proxy into its backing object.
*
* @return
*/
private synchronized Object resolve() {
@ -284,14 +306,6 @@ public class DefaultDbRefResolver implements DbRefResolver { @@ -284,14 +306,6 @@ public class DefaultDbRefResolver implements DbRefResolver {
return result;
}
public boolean isResolved() {
return resolved;
}
public Object getResult() {
return result;
}
}
/**

9
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java

@ -262,11 +262,11 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -262,11 +262,11 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
entity.doWithAssociations(new AssociationHandler<MongoPersistentProperty>() {
public void doWithAssociation(Association<MongoPersistentProperty> association) {
MongoPersistentProperty inverseProp = association.getInverse();
MongoPersistentProperty property = association.getInverse();
Object value = dbo.get(inverseProp.getName());
Object value = dbo.get(property.getName());
DBRef dbref = value instanceof DBRef ? (DBRef) value : null;
Object obj = dbRefResolver.resolveDbRef(inverseProp, dbref, new DbRefResolverCallback() {
Object obj = dbRefResolver.resolveDbRef(property, dbref, new DbRefResolverCallback() {
@Override
public Object resolve(MongoPersistentProperty property) {
@ -274,7 +274,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -274,7 +274,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
});
wrapper.setProperty(inverseProp, obj);
wrapper.setProperty(property, obj);
}
});
@ -446,6 +446,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App @@ -446,6 +446,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
dbRefObj = dbRefObj != null ? dbRefObj : createDBRef(obj, prop);
if (null != dbRefObj) {
accessor.put(prop, dbRefObj);
return;

6
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2014 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.
@ -50,6 +50,8 @@ import com.mongodb.DBObject; @@ -50,6 +50,8 @@ import com.mongodb.DBObject;
import com.mongodb.DBRef;
/**
* Unit tests dor {@link DbRefMappingMongoConverterUnitTests}.
*
* @author Oliver Gierke
*/
@RunWith(MockitoJUnitRunner.class)
@ -345,6 +347,7 @@ public class DbRefMappingMongoConverterUnitTests { @@ -345,6 +347,7 @@ public class DbRefMappingMongoConverterUnitTests {
}
}
@SuppressWarnings("serial")
static class LazyDbRefTargetWithPeristenceConstructor extends LazyDbRefTarget {
boolean persistenceConstructorCalled;
@ -362,6 +365,7 @@ public class DbRefMappingMongoConverterUnitTests { @@ -362,6 +365,7 @@ public class DbRefMappingMongoConverterUnitTests {
}
}
@SuppressWarnings("serial")
static class LazyDbRefTargetWithPeristenceConstructorWithoutDefaultConstructor extends LazyDbRefTarget {
boolean persistenceConstructorCalled;

7
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingTestUtils.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2014 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.
@ -21,6 +21,7 @@ import static org.junit.Assert.*; @@ -21,6 +21,7 @@ import static org.junit.Assert.*;
import org.springframework.aop.framework.Advised;
import org.springframework.cglib.proxy.Factory;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver.LazyLoadingInterceptor;
import org.springframework.test.util.ReflectionTestUtils;
/**
* Utility class to test proxy handling for lazy loading.
@ -39,8 +40,8 @@ public class LazyLoadingTestUtils { @@ -39,8 +40,8 @@ public class LazyLoadingTestUtils {
public static void assertProxyIsResolved(Object target, boolean expected) {
LazyLoadingInterceptor interceptor = extractInterceptor(target);
assertThat(interceptor.isResolved(), is(expected));
assertThat(interceptor.getResult(), is(expected ? notNullValue() : nullValue()));
assertThat(ReflectionTestUtils.getField(interceptor, "resolved"), is((Object) expected));
assertThat(ReflectionTestUtils.getField(interceptor, "result"), is(expected ? notNullValue() : nullValue()));
}
private static LazyLoadingInterceptor extractInterceptor(Object proxy) {

Loading…
Cancel
Save