DATAREST-1163 - ValidationErrors now properly looks up null values.
The field value lookup in ValidationErrors previously threw a NotReadablePropertyException in case a property value was null as we incorrectly piped the null value into an Optional in turn. We now eagerly reject the property if we can't find a PersistentProperty in the metamodel to avoid this.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,6 @@ package org.springframework.data.rest.core;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.ConfigurablePropertyAccessor;
|
||||
@@ -83,17 +82,30 @@ public class ValidationErrors extends AbstractPropertyBindingResult {
|
||||
|
||||
do {
|
||||
|
||||
String segment = iterator.next();
|
||||
|
||||
Optional<? extends PersistentProperty<?>> property = entities.getPersistentEntity(value.getClass())//
|
||||
.map(it -> it.getPersistentProperty(PropertyAccessorUtils.getPropertyName(segment)));
|
||||
|
||||
value = getValue(value, property, segment, propertyName);
|
||||
value = lookupValueOn(value, iterator.next());
|
||||
|
||||
} while (iterator.hasNext());
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value the original value, must not be {@literal null}..
|
||||
* @param segment the property segment to look up, must not be {@literal null} or empty.
|
||||
* @return
|
||||
*/
|
||||
private Object lookupValueOn(Object value, String segment) {
|
||||
|
||||
PersistentProperty<?> property = entities.getPersistentEntity(value.getClass()) //
|
||||
.map(it -> it.getPersistentProperty(PropertyAccessorUtils.getPropertyName(segment))) //
|
||||
.orElseThrow(() -> new NotReadablePropertyException(value.getClass(), segment));
|
||||
|
||||
ConfigurablePropertyAccessor accessor = property.usePropertyAccess() //
|
||||
? PropertyAccessorFactory.forBeanPropertyAccess(value) //
|
||||
: PropertyAccessorFactory.forDirectFieldAccess(value);
|
||||
|
||||
return accessor.getPropertyValue(segment);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -105,18 +117,4 @@ public class ValidationErrors extends AbstractPropertyBindingResult {
|
||||
public Object getTarget() {
|
||||
return source;
|
||||
}
|
||||
|
||||
private static Object getValue(Object source, Optional<? extends PersistentProperty<?>> property, String segment,
|
||||
String name) {
|
||||
|
||||
return property.map(it -> {
|
||||
|
||||
ConfigurablePropertyAccessor accessor = it.usePropertyAccess()
|
||||
? PropertyAccessorFactory.forBeanPropertyAccess(source)
|
||||
: PropertyAccessorFactory.forDirectFieldAccess(source);
|
||||
|
||||
return accessor.getPropertyValue(segment);
|
||||
|
||||
}).orElseThrow(() -> new NotReadablePropertyException(source.getClass(), name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,14 @@ public class ValidationErrorsUnitTests {
|
||||
expectedErrorBehavior(new ValidationErrors(new Foo(), entities));
|
||||
}
|
||||
|
||||
@Test // DATAREST-1163
|
||||
public void returnsNullForPropertyValue() {
|
||||
|
||||
ValidationErrors errors = new ValidationErrors(new Foo(), entities);
|
||||
|
||||
assertThat(errors.getFieldValue("bar")).isNull();
|
||||
}
|
||||
|
||||
private static void expectedErrorBehavior(Errors errors) {
|
||||
|
||||
assertThat(errors.getFieldValue("bars")).isNotNull();
|
||||
@@ -79,6 +87,7 @@ public class ValidationErrorsUnitTests {
|
||||
|
||||
static class Foo {
|
||||
List<Bar> bars = Collections.singletonList(new Bar());
|
||||
Bar bar = null;
|
||||
}
|
||||
|
||||
static class Bar {
|
||||
|
||||
Reference in New Issue
Block a user