From 4aeba6f92d32decc55fc3a1c7c07da48a5186c8f Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Wed, 17 Oct 2012 17:27:15 -0400 Subject: [PATCH] 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. --- .../core/convert/MappingMongoConverter.java | 11 ++++++---- .../mapping/BasicMongoPersistentProperty.java | 13 ++++++++++++ .../core/mapping/MongoPersistentProperty.java | 8 ++++++++ .../mapping/SimpleMongoMappingContext.java | 7 +++++++ .../MappingMongoConverterUnitTests.java | 20 ++++++++++++++++++- ...BasicMongoPersistentPropertyUnitTests.java | 10 ++++++++++ 6 files changed, 64 insertions(+), 5 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java index 359c4cd5d..a7e1e3605 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java @@ -346,13 +346,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App } final BeanWrapper, Object> wrapper = BeanWrapper.create(obj, conversionService); - - // Write the ID final MongoPersistentProperty idProperty = entity.getIdProperty(); + if (!dbo.containsField("_id") && null != idProperty) { + boolean fieldAccessOnly = idProperty.usePropertyAccess() ? false : useFieldAccessOnly; + try { - Object id = wrapper.getProperty(idProperty, Object.class, useFieldAccessOnly); + Object id = wrapper.getProperty(idProperty, Object.class, fieldAccessOnly); dbo.put("_id", idMapper.convertId(id)); } catch (ConversionException ignored) { } @@ -366,7 +367,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App 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 (!conversions.isSimpleType(propertyObj.getClass())) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java index 03e91abac..d823cb171 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentProperty.java @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty; import org.springframework.data.mapping.model.SimpleTypeHolder; +import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import com.mongodb.DBObject; @@ -46,6 +47,8 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope private static final Set> SUPPORTED_ID_TYPES = new HashSet>(); private static final Set SUPPORTED_ID_PROPERTY_NAMES = new HashSet(); + private static final Field CAUSE_FIELD; + static { SUPPORTED_ID_TYPES.add(ObjectId.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"); + + CAUSE_FIELD = ReflectionUtils.findField(Throwable.class, "cause"); } /** @@ -155,4 +160,12 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope public boolean isVersionProperty() { return getField().isAnnotationPresent(Version.class); } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#usePropertyAccess() + */ + public boolean usePropertyAccess() { + return CAUSE_FIELD.equals(getField()); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java index d5e1d6533..6f523c347 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoPersistentProperty.java @@ -80,4 +80,12 @@ public interface MongoPersistentProperty extends PersistentProperty extends BasicPersistentEntity implements diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index ef8eb2077..71026e308 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -918,7 +918,7 @@ public class MappingMongoConverterUnitTests { Object contacts = result.get("contacts"); assertThat(contacts, is(instanceOf(Collection.class))); assertThat(((Collection) contacts).size(), is(2)); - assertThat(((Collection) contacts), hasItem(nullValue())); + assertThat((Collection) contacts, hasItem(nullValue())); } /** @@ -1310,6 +1310,19 @@ public class MappingMongoConverterUnitTests { 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 content; } @@ -1498,6 +1511,11 @@ public class MappingMongoConverterUnitTests { String name; } + static class ThrowableWrapper { + + Throwable throwable; + } + private class LocalDateToDateConverter implements Converter { public Date convert(LocalDate source) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java index 92a1f2577..b1c26388f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/BasicMongoPersistentPropertyUnitTests.java @@ -68,6 +68,16 @@ public class BasicMongoPersistentPropertyUnitTests { 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) { return new BasicMongoPersistentProperty(field, null, entity, new SimpleTypeHolder()); }