DATAMONGO-1012 - Improved identifier initialization on DBRef proxies.

Identifier initalization is now only triggered if field access is used. Before that the id initialization would've resolved the proxy eagerly as the getter access performed by the BeanWrapper would've been intercepted by the proxy and is indistinguishable from a normal method call. This would've rendered the entire use case to create proxies ad absurdum.

Added test case to check for non-initialization in the property access scenario.
This commit is contained in:
Thomas Darimont
2014-08-13 13:46:05 +02:00
committed by Oliver Gierke
parent 6f06ccec8e
commit 3597194742
2 changed files with 51 additions and 6 deletions

View File

@@ -62,14 +62,14 @@ class DefaultDbRefProxyHandler implements DbRefProxyHandler {
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(property);
MongoPersistentProperty idProperty = persistentEntity.getIdProperty();
if (idProperty.usePropertyAccess()) {
if(idProperty.usePropertyAccess()) {
return proxy;
}
SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(proxy, spELContext);
BeanWrapper<Object> proxyWrapper = BeanWrapper.create(proxy, null);
DBObject object = new BasicDBObject(idProperty.getFieldName(), source.getId());
ObjectPath objectPath = ObjectPath.ROOT.push(proxy, persistentEntity, null);
proxyWrapper.setProperty(idProperty, resolver.getValueInternal(idProperty, object, evaluator, objectPath));

View File

@@ -36,6 +36,8 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.annotation.AccessType;
import org.springframework.data.annotation.AccessType.Type;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.mapping.PropertyPath;
@@ -46,6 +48,7 @@ import org.springframework.data.mongodb.core.convert.MappingMongoConverterUnitTe
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.util.SerializationUtils;
import com.mongodb.BasicDBObject;
@@ -494,13 +497,17 @@ public class DbRefMappingMongoConverterUnitTests {
assertThat(found.nested.reference, is(found));
}
/**
* @see DATAMONGO-1012
*/
@Test
public void testname() {
public void shouldEagerlyResolveIdPropertyWithFieldAccess() {
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(ClassWithLazyDbRefs.class);
MongoPersistentProperty property = entity.getPersistentProperty("dbRefToConcreteType");
Object dbRef = converter.toDBRef(new LazyDbRefTarget(new ObjectId().toString()), property);
String idValue = new ObjectId().toString();
DBRef dbRef = converter.toDBRef(new LazyDbRefTarget(idValue), property);
DBObject object = new BasicDBObject("dbRefToConcreteType", dbRef);
@@ -510,6 +517,28 @@ public class DbRefMappingMongoConverterUnitTests {
MongoPersistentProperty idProperty = mappingContext.getPersistentEntity(LazyDbRefTarget.class).getIdProperty();
assertThat(wrapper.getProperty(idProperty), is(notNullValue()));
assertProxyIsResolved(result.dbRefToConcreteType, false);
}
/**
* @see DATAMONGO-1012
*/
@Test
public void shouldNotEagerlyResolveIdPropertyWithPropertyAccess() {
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(ClassWithLazyDbRefs.class);
MongoPersistentProperty property = entity.getPersistentProperty("dbRefToConcreteTypeWithPropertyAccess");
String idValue = new ObjectId().toString();
DBRef dbRef = converter.toDBRef(new LazyDbRefTargetPropertyAccess(idValue), property);
DBObject object = new BasicDBObject("dbRefToConcreteTypeWithPropertyAccess", dbRef);
ClassWithLazyDbRefs result = converter.read(ClassWithLazyDbRefs.class, object);
LazyDbRefTargetPropertyAccess proxy = result.dbRefToConcreteTypeWithPropertyAccess;
assertThat(ReflectionTestUtils.getField(proxy, "id"), is(nullValue()));
assertProxyIsResolved(proxy, false);
}
private Object transport(Object result) {
@@ -534,6 +563,7 @@ public class DbRefMappingMongoConverterUnitTests {
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) List<LazyDbRefTarget> dbRefToInterface;
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) ArrayList<LazyDbRefTarget> dbRefToConcreteCollection;
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) LazyDbRefTarget dbRefToConcreteType;
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) LazyDbRefTargetPropertyAccess dbRefToConcreteTypeWithPropertyAccess;
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) LazyDbRefTargetWithPeristenceConstructor dbRefToConcreteTypeWithPersistenceConstructor;
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) LazyDbRefTargetWithPeristenceConstructorWithoutDefaultConstructor dbRefToConcreteTypeWithPersistenceConstructorWithoutDefaultConstructor;
}
@@ -574,6 +604,21 @@ public class DbRefMappingMongoConverterUnitTests {
}
}
static class LazyDbRefTargetPropertyAccess implements Serializable {
private static final long serialVersionUID = 1L;
@Id @AccessType(Type.PROPERTY) String id;
public LazyDbRefTargetPropertyAccess(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
@SuppressWarnings("serial")
static class LazyDbRefTargetWithPeristenceConstructor extends LazyDbRefTarget {