Skip to content

DATAMONGO-1271 Provide read lifecycle events when loading DBRefs #322

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>
Expand All @@ -15,7 +15,7 @@
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>1.8.0.BUILD-SNAPSHOT</version>
<version>1.7.0.RELEASE</version>
</parent>

<modules>
Expand All @@ -28,7 +28,7 @@
<properties>
<project.type>multi</project.type>
<dist.id>spring-data-mongodb</dist.id>
<springdata.commons>1.12.0.BUILD-SNAPSHOT</springdata.commons>
<springdata.commons>1.11.0.RELEASE</springdata.commons>
<mongo>2.13.0</mongo>
<mongo.osgi>2.13.0</mongo.osgi>
</properties>
Expand Down Expand Up @@ -156,8 +156,8 @@

<repositories>
<repository>
<id>spring-libs-snapshot</id>
<url>https://repo.spring.io/libs-snapshot</url>
<id>spring-libs-release</id>
<url>https://repo.spring.io/libs-release</url>
</repository>
</repositories>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
*/
package org.springframework.data.mongodb.core.convert;

import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.DBRef;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand All @@ -23,12 +27,12 @@
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.ConversionService;
Expand All @@ -53,18 +57,15 @@
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.data.mongodb.core.mapping.event.AfterConvertEvent;
import org.springframework.data.mongodb.core.mapping.event.AfterLoadEvent;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;

import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.DBRef;

/**
* {@link MongoConverter} that uses a {@link MappingContext} to do sophisticated mapping of domain objects to
* {@link DBObject}.
Expand All @@ -74,6 +75,7 @@
* @author Patrik Wasik
* @author Thomas Darimont
* @author Christoph Strobl
* @author Jordi Llach
*/
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware, ValueResolver {

Expand Down Expand Up @@ -288,8 +290,11 @@ public void doWithPersistentProperty(MongoPersistentProperty prop) {
public void doWithAssociation(Association<MongoPersistentProperty> association) {

final MongoPersistentProperty property = association.getInverse();
Object value = dbo.get(property.getFieldName());

// constructor properties that contain a DBRef(lazy=false) are already fetched, skip them
if (entity.isConstructorArgument(property) && property.isDbReference() && !property.getDBRef().lazy()) {
return;
}
Object value = dbo.get(property.getFieldName());
if (value == null) {
return;
}
Expand Down Expand Up @@ -866,7 +871,7 @@ protected DBRef createDBRef(Object target, MongoPersistentProperty property) {
@Override
public Object getValueInternal(MongoPersistentProperty prop, DBObject dbo, SpELExpressionEvaluator evaluator,
ObjectPath path) {
return new MongoDbPropertyValueProvider(dbo, evaluator, path).getPropertyValue(prop);
return new MongoDbPropertyValueProvider(dbo, evaluator, path, false).getPropertyValue(prop);
}

/**
Expand Down Expand Up @@ -900,8 +905,7 @@ private Object readCollectionOrArray(TypeInformation<?> targetType, BasicDBList
Object dbObjItem = sourceValue.get(i);

if (dbObjItem instanceof DBRef) {
items.add(
DBRef.class.equals(rawComponentType) ? dbObjItem : read(componentType, readRef((DBRef) dbObjItem), path));
items.add(DBRef.class.equals(rawComponentType) ? dbObjItem : readAndConvertDBRef((DBRef)dbObjItem, componentType, path, rawComponentType));
} else if (dbObjItem instanceof DBObject) {
items.add(read(componentType, (DBObject) dbObjItem, path));
} else {
Expand Down Expand Up @@ -953,7 +957,7 @@ protected Map<Object, Object> readMap(TypeInformation<?> type, DBObject dbObject
if (value instanceof DBObject) {
map.put(key, read(valueType, (DBObject) value, path));
} else if (value instanceof DBRef) {
map.put(key, DBRef.class.equals(rawValueType) ? value : read(valueType, readRef((DBRef) value)));
map.put(key, DBRef.class.equals(rawValueType) ? value : readAndConvertDBRef((DBRef) value, valueType, ObjectPath.ROOT, rawValueType));
} else {
Class<?> valueClass = valueType == null ? null : valueType.getType();
map.put(key, getPotentiallyConvertedSimpleRead(value, valueClass));
Expand Down Expand Up @@ -1098,7 +1102,8 @@ private class MongoDbPropertyValueProvider implements PropertyValueProvider<Mong
private final DBObjectAccessor source;
private final SpELExpressionEvaluator evaluator;
private final ObjectPath path;

private final boolean ignoreLazyDBRefProperties;

/**
* Creates a new {@link MongoDbPropertyValueProvider} for the given source, {@link SpELExpressionEvaluator} and
* {@link ObjectPath}.
Expand All @@ -1108,14 +1113,18 @@ private class MongoDbPropertyValueProvider implements PropertyValueProvider<Mong
* @param path can be {@literal null}.
*/
public MongoDbPropertyValueProvider(DBObject source, SpELExpressionEvaluator evaluator, ObjectPath path) {

Assert.notNull(source);
this(source, evaluator, path, true); // ignoring by default
}

MongoDbPropertyValueProvider(DBObject source, SpELExpressionEvaluator evaluator, ObjectPath path, boolean ignoreLazyDBRefProperties) {
Assert.notNull(source);
Assert.notNull(evaluator);

this.source = new DBObjectAccessor(source);
this.evaluator = evaluator;
this.path = path;
}
this.ignoreLazyDBRefProperties = ignoreLazyDBRefProperties;
}

/*
* (non-Javadoc)
Expand All @@ -1129,6 +1138,9 @@ public <T> T getPropertyValue(MongoPersistentProperty property) {
if (value == null) {
return null;
}
if (this.ignoreLazyDBRefProperties && property.isDbReference() && property.getDBRef().lazy()) { // lazy DBRef, BasicDBList are resolved later by default
return null;
}

return readValue(value, property.getTypeInformation(), path);
}
Expand Down Expand Up @@ -1190,20 +1202,26 @@ private <T> T readValue(Object value, TypeInformation<?> type, ObjectPath path)

@SuppressWarnings("unchecked")
private <T> T potentiallyReadOrResolveDbRef(DBRef dbref, TypeInformation<?> type, ObjectPath path, Class<?> rawType) {

if (rawType.equals(DBRef.class)) {
return (T) dbref;
}

Object object = dbref == null ? null : path.getPathItem(dbref.getId(), dbref.getCollectionName());

if (object != null) {
return (T) object;
}

return (T) (object != null ? object : read(type, readRef(dbref), path));
return (T) (object != null ? object : readAndConvertDBRef(dbref, type, path, rawType));
}

private <T> T readAndConvertDBRef(DBRef dbref, TypeInformation<?> type, ObjectPath path, Class<?> rawType) {
DBObject readRef = readRef(dbref);
final String collectionName = dbref.getCollectionName();
if (canPublishEvent()) ((ApplicationEventPublisher)this.applicationContext).publishEvent(new AfterLoadEvent<T>(readRef, (Class<T>)rawType, collectionName));
T t = (T) read(type, readRef, path);
if (canPublishEvent()) ((ApplicationEventPublisher)this.applicationContext).publishEvent(new AfterConvertEvent<T>(readRef, t, collectionName));
return t;
}

private boolean canPublishEvent() {
return this.applicationContext != null;
}

/**
* Performs the fetch operation for the given {@link DBRef}.
*
Expand All @@ -1224,4 +1242,4 @@ DBObject readRef(DBRef ref) {
static class NestedDocument {

}
}
}
Loading