Skip to content

Commit 3597194

Browse files
Thomas Darimontodrotbohm
authored andcommitted
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.
1 parent 6f06cce commit 3597194

File tree

2 files changed

+51
-6
lines changed

2 files changed

+51
-6
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,14 @@ public Object populateId(MongoPersistentProperty property, DBRef source, Object
6262

6363
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(property);
6464
MongoPersistentProperty idProperty = persistentEntity.getIdProperty();
65-
66-
if (idProperty.usePropertyAccess()) {
65+
66+
if(idProperty.usePropertyAccess()) {
6767
return proxy;
6868
}
69-
69+
7070
SpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(proxy, spELContext);
7171
BeanWrapper<Object> proxyWrapper = BeanWrapper.create(proxy, null);
72-
72+
7373
DBObject object = new BasicDBObject(idProperty.getFieldName(), source.getId());
7474
ObjectPath objectPath = ObjectPath.ROOT.push(proxy, persistentEntity, null);
7575
proxyWrapper.setProperty(idProperty, resolver.getValueInternal(idProperty, object, evaluator, objectPath));

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

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
import org.junit.runner.RunWith;
3737
import org.mockito.Mock;
3838
import org.mockito.runners.MockitoJUnitRunner;
39+
import org.springframework.data.annotation.AccessType;
40+
import org.springframework.data.annotation.AccessType.Type;
3941
import org.springframework.data.annotation.Id;
4042
import org.springframework.data.annotation.PersistenceConstructor;
4143
import org.springframework.data.mapping.PropertyPath;
@@ -46,6 +48,7 @@
4648
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
4749
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
4850
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
51+
import org.springframework.test.util.ReflectionTestUtils;
4952
import org.springframework.util.SerializationUtils;
5053

5154
import com.mongodb.BasicDBObject;
@@ -494,13 +497,17 @@ public void shouldBeAbleToStoreNestedReferencesToSelf() {
494497
assertThat(found.nested.reference, is(found));
495498
}
496499

500+
/**
501+
* @see DATAMONGO-1012
502+
*/
497503
@Test
498-
public void testname() {
504+
public void shouldEagerlyResolveIdPropertyWithFieldAccess() {
499505

500506
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(ClassWithLazyDbRefs.class);
501507
MongoPersistentProperty property = entity.getPersistentProperty("dbRefToConcreteType");
502508

503-
Object dbRef = converter.toDBRef(new LazyDbRefTarget(new ObjectId().toString()), property);
509+
String idValue = new ObjectId().toString();
510+
DBRef dbRef = converter.toDBRef(new LazyDbRefTarget(idValue), property);
504511

505512
DBObject object = new BasicDBObject("dbRefToConcreteType", dbRef);
506513

@@ -510,6 +517,28 @@ public void testname() {
510517
MongoPersistentProperty idProperty = mappingContext.getPersistentEntity(LazyDbRefTarget.class).getIdProperty();
511518

512519
assertThat(wrapper.getProperty(idProperty), is(notNullValue()));
520+
assertProxyIsResolved(result.dbRefToConcreteType, false);
521+
}
522+
523+
/**
524+
* @see DATAMONGO-1012
525+
*/
526+
@Test
527+
public void shouldNotEagerlyResolveIdPropertyWithPropertyAccess() {
528+
529+
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(ClassWithLazyDbRefs.class);
530+
MongoPersistentProperty property = entity.getPersistentProperty("dbRefToConcreteTypeWithPropertyAccess");
531+
532+
String idValue = new ObjectId().toString();
533+
DBRef dbRef = converter.toDBRef(new LazyDbRefTargetPropertyAccess(idValue), property);
534+
535+
DBObject object = new BasicDBObject("dbRefToConcreteTypeWithPropertyAccess", dbRef);
536+
537+
ClassWithLazyDbRefs result = converter.read(ClassWithLazyDbRefs.class, object);
538+
539+
LazyDbRefTargetPropertyAccess proxy = result.dbRefToConcreteTypeWithPropertyAccess;
540+
assertThat(ReflectionTestUtils.getField(proxy, "id"), is(nullValue()));
541+
assertProxyIsResolved(proxy, false);
513542
}
514543

515544
private Object transport(Object result) {
@@ -534,6 +563,7 @@ static class ClassWithLazyDbRefs {
534563
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) List<LazyDbRefTarget> dbRefToInterface;
535564
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) ArrayList<LazyDbRefTarget> dbRefToConcreteCollection;
536565
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) LazyDbRefTarget dbRefToConcreteType;
566+
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) LazyDbRefTargetPropertyAccess dbRefToConcreteTypeWithPropertyAccess;
537567
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) LazyDbRefTargetWithPeristenceConstructor dbRefToConcreteTypeWithPersistenceConstructor;
538568
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) LazyDbRefTargetWithPeristenceConstructorWithoutDefaultConstructor dbRefToConcreteTypeWithPersistenceConstructorWithoutDefaultConstructor;
539569
}
@@ -574,6 +604,21 @@ public String getValue() {
574604
}
575605
}
576606

607+
static class LazyDbRefTargetPropertyAccess implements Serializable {
608+
609+
private static final long serialVersionUID = 1L;
610+
611+
@Id @AccessType(Type.PROPERTY) String id;
612+
613+
public LazyDbRefTargetPropertyAccess(String id) {
614+
this.id = id;
615+
}
616+
617+
public String getId() {
618+
return id;
619+
}
620+
}
621+
577622
@SuppressWarnings("serial")
578623
static class LazyDbRefTargetWithPeristenceConstructor extends LazyDbRefTarget {
579624

0 commit comments

Comments
 (0)