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:
@@ -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())) {
|
||||||
|
|||||||
@@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user