added configurable "autoGrowNestedPaths" property to DataBinder (SPR-6430)

This commit is contained in:
Juergen Hoeller 2009-11-25 00:17:29 +00:00
parent 9a2f9ccde4
commit bb97ca32c4
3 changed files with 40 additions and 6 deletions

View File

@ -79,11 +79,11 @@ public interface BeanWrapper extends ConfigurablePropertyAccessor {
PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException; PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException;
/** /**
* Set if this BeanWrapper should attempt to "auto-grow" a nested path that contains a null value. * Set whether this BeanWrapper should attempt to "auto-grow" a nested path that contains a null value.
* <p>If true, a null path location will be populated with a default object value and traversed * <p>If "true", a null path location will be populated with a default object value and traversed
* instead of resulting in a {@link NullValueInNestedPathException}. Turning this flag on also * instead of resulting in a {@link NullValueInNestedPathException}. Turning this flag on also
* enables auto-growth of collection elements when an index that is out of bounds is accessed. * enables auto-growth of collection elements when accessing an out-of-bounds index.
* <p>Default is false. * <p>Default is "false" on a plain BeanWrapper.
*/ */
void setAutoGrowNestedPaths(boolean autoGrowNestedPaths); void setAutoGrowNestedPaths(boolean autoGrowNestedPaths);

View File

@ -44,6 +44,8 @@ public class BeanPropertyBindingResult extends AbstractPropertyBindingResult imp
private final Object target; private final Object target;
private final boolean autoGrowNestedPaths;
private transient BeanWrapper beanWrapper; private transient BeanWrapper beanWrapper;
@ -53,8 +55,19 @@ public class BeanPropertyBindingResult extends AbstractPropertyBindingResult imp
* @param objectName the name of the target object * @param objectName the name of the target object
*/ */
public BeanPropertyBindingResult(Object target, String objectName) { public BeanPropertyBindingResult(Object target, String objectName) {
this(target, objectName, true);
}
/**
* Creates a new instance of the {@link BeanPropertyBindingResult} class.
* @param target the target bean to bind onto
* @param objectName the name of the target object
* @param autoGrowNestedPaths whether to "auto-grow" a nested path that contains a null value
*/
public BeanPropertyBindingResult(Object target, String objectName, boolean autoGrowNestedPaths) {
super(objectName); super(objectName);
this.target = target; this.target = target;
this.autoGrowNestedPaths = autoGrowNestedPaths;
} }
@ -73,7 +86,7 @@ public class BeanPropertyBindingResult extends AbstractPropertyBindingResult imp
if (this.beanWrapper == null) { if (this.beanWrapper == null) {
this.beanWrapper = createBeanWrapper(); this.beanWrapper = createBeanWrapper();
this.beanWrapper.setExtractOldValueForEditor(true); this.beanWrapper.setExtractOldValueForEditor(true);
this.beanWrapper.setAutoGrowNestedPaths(true); this.beanWrapper.setAutoGrowNestedPaths(this.autoGrowNestedPaths);
} }
return this.beanWrapper; return this.beanWrapper;
} }

View File

@ -125,6 +125,8 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
private boolean ignoreInvalidFields = false; private boolean ignoreInvalidFields = false;
private boolean autoGrowNestedPaths = true;
private String[] allowedFields; private String[] allowedFields;
private String[] disallowedFields; private String[] disallowedFields;
@ -182,7 +184,7 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
public void initBeanPropertyAccess() { public void initBeanPropertyAccess() {
Assert.isNull(this.bindingResult, Assert.isNull(this.bindingResult,
"DataBinder is already initialized - call initBeanPropertyAccess before any other configuration methods"); "DataBinder is already initialized - call initBeanPropertyAccess before any other configuration methods");
this.bindingResult = new BeanPropertyBindingResult(getTarget(), getObjectName()); this.bindingResult = new BeanPropertyBindingResult(getTarget(), getObjectName(), isAutoGrowNestedPaths());
if (this.conversionService != null) { if (this.conversionService != null) {
this.bindingResult.initConversion(this.conversionService); this.bindingResult.initConversion(this.conversionService);
} }
@ -330,6 +332,25 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
return this.ignoreInvalidFields; return this.ignoreInvalidFields;
} }
/**
* Set whether this binder should attempt to "auto-grow" a nested path that contains a null value.
* <p>If "true", a null path location will be populated with a default object value and traversed
* instead of resulting in an exception. This flag also enables auto-growth of collection elements
* when accessing an out-of-bounds index.
* <p>Default is "true" on a standard DataBinder.
* @see org.springframework.beans.BeanWrapper#setAutoGrowNestedPaths
*/
public void setAutoGrowNestedPaths(boolean autoGrowNestedPaths) {
this.autoGrowNestedPaths = autoGrowNestedPaths;
}
/**
* Return whether "auto-growing" of nested paths has been activated.
*/
public boolean isAutoGrowNestedPaths() {
return this.autoGrowNestedPaths;
}
/** /**
* Register fields that should be allowed for binding. Default is all * Register fields that should be allowed for binding. Default is all
* fields. Restrict this for example to avoid unwanted modifications * fields. Restrict this for example to avoid unwanted modifications