DATAMONGO-553 - MappingMongoConverter now uses MongoPersistentProperty.usePropertyAccess() to decide whether to use property access.

Introduced usePropertyAccess() method on MongoPersistentProperty and added an implementation that forces that into being true for Throwable.cause as using the field would cause a cycle as it points to this in the first place but rather massages the value in the getter.
This commit is contained in:
Oliver Gierke
2012-10-17 17:27:15 -04:00
parent 342f9ae837
commit 4aeba6f92d
6 changed files with 64 additions and 5 deletions

View File

@@ -346,13 +346,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
} }
final BeanWrapper<MongoPersistentEntity<Object>, Object> wrapper = BeanWrapper.create(obj, conversionService); final BeanWrapper<MongoPersistentEntity<Object>, Object> wrapper = BeanWrapper.create(obj, conversionService);
// Write the ID
final MongoPersistentProperty idProperty = entity.getIdProperty(); final MongoPersistentProperty idProperty = entity.getIdProperty();
if (!dbo.containsField("_id") && null != idProperty) { if (!dbo.containsField("_id") && null != idProperty) {
boolean fieldAccessOnly = idProperty.usePropertyAccess() ? false : useFieldAccessOnly;
try { try {
Object id = wrapper.getProperty(idProperty, Object.class, useFieldAccessOnly); Object id = wrapper.getProperty(idProperty, Object.class, fieldAccessOnly);
dbo.put("_id", idMapper.convertId(id)); dbo.put("_id", idMapper.convertId(id));
} catch (ConversionException ignored) { } catch (ConversionException ignored) {
} }
@@ -366,7 +367,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return; return;
} }
Object propertyObj = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly); boolean fieldAccessOnly = prop.usePropertyAccess() ? false : useFieldAccessOnly;
Object propertyObj = wrapper.getProperty(prop, prop.getType(), fieldAccessOnly);
if (null != propertyObj) { if (null != propertyObj) {
if (!conversions.isSimpleType(propertyObj.getClass())) { if (!conversions.isSimpleType(propertyObj.getClass())) {

View File

@@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.data.mapping.Association; import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty; import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
import org.springframework.data.mapping.model.SimpleTypeHolder; import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import com.mongodb.DBObject; import com.mongodb.DBObject;
@@ -46,6 +47,8 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<Class<?>>(); private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<Class<?>>();
private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<String>(); private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<String>();
private static final Field CAUSE_FIELD;
static { static {
SUPPORTED_ID_TYPES.add(ObjectId.class); SUPPORTED_ID_TYPES.add(ObjectId.class);
SUPPORTED_ID_TYPES.add(String.class); SUPPORTED_ID_TYPES.add(String.class);
@@ -53,6 +56,8 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
SUPPORTED_ID_PROPERTY_NAMES.add("id"); SUPPORTED_ID_PROPERTY_NAMES.add("id");
SUPPORTED_ID_PROPERTY_NAMES.add("_id"); SUPPORTED_ID_PROPERTY_NAMES.add("_id");
CAUSE_FIELD = ReflectionUtils.findField(Throwable.class, "cause");
} }
/** /**
@@ -155,4 +160,12 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
public boolean isVersionProperty() { public boolean isVersionProperty() {
return getField().isAnnotationPresent(Version.class); return getField().isAnnotationPresent(Version.class);
} }
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#usePropertyAccess()
*/
public boolean usePropertyAccess() {
return CAUSE_FIELD.equals(getField());
}
} }

View File

@@ -80,4 +80,12 @@ public interface MongoPersistentProperty extends PersistentProperty<MongoPersist
return source.getFieldName(); return source.getFieldName();
} }
} }
/**
* Returns whether property access shall be used for reading the property value. This means it will use the getter
* instead of field access.
*
* @return
*/
boolean usePropertyAccess();
} }

View File

@@ -123,6 +123,13 @@ public class SimpleMongoMappingContext extends
return false; return false;
} }
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#usePropertyAccess()
*/
public boolean usePropertyAccess() {
return false;
}
} }
static class SimpleMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty> implements static class SimpleMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty> implements

View File

@@ -918,7 +918,7 @@ public class MappingMongoConverterUnitTests {
Object contacts = result.get("contacts"); Object contacts = result.get("contacts");
assertThat(contacts, is(instanceOf(Collection.class))); assertThat(contacts, is(instanceOf(Collection.class)));
assertThat(((Collection<?>) contacts).size(), is(2)); assertThat(((Collection<?>) contacts).size(), is(2));
assertThat(((Collection<Object>) contacts), hasItem(nullValue())); assertThat((Collection<Object>) contacts, hasItem(nullValue()));
} }
/** /**
@@ -1310,6 +1310,19 @@ public class MappingMongoConverterUnitTests {
assertThat(type.toString(), is("_")); assertThat(type.toString(), is("_"));
} }
/**
* @see DATAMONGO-533
*/
@Test
public void marshalsThrowableCorrectly() {
ThrowableWrapper wrapper = new ThrowableWrapper();
wrapper.throwable = new Exception();
DBObject dbObject = new BasicDBObject();
converter.write(wrapper, dbObject);
}
static class GenericType<T> { static class GenericType<T> {
T content; T content;
} }
@@ -1498,6 +1511,11 @@ public class MappingMongoConverterUnitTests {
String name; String name;
} }
static class ThrowableWrapper {
Throwable throwable;
}
private class LocalDateToDateConverter implements Converter<LocalDate, Date> { private class LocalDateToDateConverter implements Converter<LocalDate, Date> {
public Date convert(LocalDate source) { public Date convert(LocalDate source) {

View File

@@ -68,6 +68,16 @@ public class BasicMongoPersistentPropertyUnitTests {
getPropertyFor(ReflectionUtils.findField(Person.class, "ssn")); getPropertyFor(ReflectionUtils.findField(Person.class, "ssn"));
} }
/**
* @see DATAMONGO-553
*/
@Test
public void usesPropertyAccessForThrowableCause() {
MongoPersistentProperty property = getPropertyFor(ReflectionUtils.findField(Throwable.class, "cause"));
assertThat(property.usePropertyAccess(), is(true));
}
private MongoPersistentProperty getPropertyFor(Field field) { private MongoPersistentProperty getPropertyFor(Field field) {
return new BasicMongoPersistentProperty(field, null, entity, new SimpleTypeHolder()); return new BasicMongoPersistentProperty(field, null, entity, new SimpleTypeHolder());
} }