fixed DataBinder's conversion error handling for direct field access with ConversionService (SPR-6953)
This commit is contained in:
parent
65b0a8fcb2
commit
53b6e1c1b0
|
|
@ -781,7 +781,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||||
"Getter for property '" + actualName + "' threw exception", ex);
|
"Getter for property '" + actualName + "' threw exception", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
catch(IllegalAccessException ex) {
|
catch (IllegalAccessException ex) {
|
||||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||||
"Illegal attempt to get property '" + actualName + "' threw exception", ex);
|
"Illegal attempt to get property '" + actualName + "' threw exception", ex);
|
||||||
}
|
}
|
||||||
|
|
@ -813,7 +813,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||||
}
|
}
|
||||||
setPropertyValue(name, newArray);
|
setPropertyValue(name, newArray);
|
||||||
return newArray;
|
return newArray;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2009 the original author or authors.
|
* Copyright 2002-2010 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -22,6 +22,8 @@ import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.core.MethodParameter;
|
import org.springframework.core.MethodParameter;
|
||||||
|
import org.springframework.core.convert.ConversionException;
|
||||||
|
import org.springframework.core.convert.ConverterNotFoundException;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
@ -125,10 +127,11 @@ public class DirectFieldAccessor extends AbstractPropertyAccessor {
|
||||||
Object convertedValue = this.typeConverterDelegate.convertIfNecessary(oldValue, newValue, field);
|
Object convertedValue = this.typeConverterDelegate.convertIfNecessary(oldValue, newValue, field);
|
||||||
field.set(this.target, convertedValue);
|
field.set(this.target, convertedValue);
|
||||||
}
|
}
|
||||||
catch (IllegalAccessException ex) {
|
catch (ConverterNotFoundException ex) {
|
||||||
throw new InvalidPropertyException(this.target.getClass(), propertyName, "Field is not accessible", ex);
|
PropertyChangeEvent pce = new PropertyChangeEvent(this.target, propertyName, oldValue, newValue);
|
||||||
|
throw new ConversionNotSupportedException(pce, field.getType(), ex);
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException ex) {
|
catch (ConversionException ex) {
|
||||||
PropertyChangeEvent pce = new PropertyChangeEvent(this.target, propertyName, oldValue, newValue);
|
PropertyChangeEvent pce = new PropertyChangeEvent(this.target, propertyName, oldValue, newValue);
|
||||||
throw new TypeMismatchException(pce, field.getType(), ex);
|
throw new TypeMismatchException(pce, field.getType(), ex);
|
||||||
}
|
}
|
||||||
|
|
@ -136,6 +139,13 @@ public class DirectFieldAccessor extends AbstractPropertyAccessor {
|
||||||
PropertyChangeEvent pce = new PropertyChangeEvent(this.target, propertyName, oldValue, newValue);
|
PropertyChangeEvent pce = new PropertyChangeEvent(this.target, propertyName, oldValue, newValue);
|
||||||
throw new ConversionNotSupportedException(pce, field.getType(), ex);
|
throw new ConversionNotSupportedException(pce, field.getType(), ex);
|
||||||
}
|
}
|
||||||
|
catch (IllegalArgumentException ex) {
|
||||||
|
PropertyChangeEvent pce = new PropertyChangeEvent(this.target, propertyName, oldValue, newValue);
|
||||||
|
throw new TypeMismatchException(pce, field.getType(), ex);
|
||||||
|
}
|
||||||
|
catch (IllegalAccessException ex) {
|
||||||
|
throw new InvalidPropertyException(this.target.getClass(), propertyName, "Field is not accessible", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T convertIfNecessary(
|
public <T> T convertIfNecessary(
|
||||||
|
|
|
||||||
|
|
@ -495,7 +495,11 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||||
* property values, as an alternative to JavaBeans PropertyEditors.
|
* property values, as an alternative to JavaBeans PropertyEditors.
|
||||||
*/
|
*/
|
||||||
public void setConversionService(ConversionService conversionService) {
|
public void setConversionService(ConversionService conversionService) {
|
||||||
|
Assert.state(this.conversionService == null, "DataBinder is already initialized with ConversionService");
|
||||||
this.conversionService = conversionService;
|
this.conversionService = conversionService;
|
||||||
|
if (this.bindingResult != null && conversionService != null) {
|
||||||
|
this.bindingResult.initConversion(conversionService);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2009 the original author or authors.
|
* Copyright 2002-2010 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -327,6 +327,83 @@ public class DataBinderTests extends TestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testBindingErrorWithFormatter() {
|
||||||
|
TestBean tb = new TestBean();
|
||||||
|
DataBinder binder = new DataBinder(tb);
|
||||||
|
FormattingConversionService conversionService = new FormattingConversionService();
|
||||||
|
ConversionServiceFactory.addDefaultConverters(conversionService);
|
||||||
|
conversionService.addFormatterForFieldType(Float.class, new NumberFormatter());
|
||||||
|
binder.setConversionService(conversionService);
|
||||||
|
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||||
|
pvs.add("myFloat", "1x2");
|
||||||
|
|
||||||
|
LocaleContextHolder.setLocale(Locale.GERMAN);
|
||||||
|
try {
|
||||||
|
binder.bind(pvs);
|
||||||
|
assertEquals(new Float(0.0), tb.getMyFloat());
|
||||||
|
assertEquals("1x2", binder.getBindingResult().getFieldValue("myFloat"));
|
||||||
|
assertTrue(binder.getBindingResult().hasFieldErrors("myFloat"));
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
LocaleContextHolder.resetLocaleContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBindingWithFormatterAgainstFields() {
|
||||||
|
TestBean tb = new TestBean();
|
||||||
|
DataBinder binder = new DataBinder(tb);
|
||||||
|
FormattingConversionService conversionService = new FormattingConversionService();
|
||||||
|
ConversionServiceFactory.addDefaultConverters(conversionService);
|
||||||
|
conversionService.addFormatterForFieldType(Float.class, new NumberFormatter());
|
||||||
|
binder.setConversionService(conversionService);
|
||||||
|
binder.initDirectFieldAccess();
|
||||||
|
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||||
|
pvs.add("myFloat", "1,2");
|
||||||
|
|
||||||
|
LocaleContextHolder.setLocale(Locale.GERMAN);
|
||||||
|
try {
|
||||||
|
binder.bind(pvs);
|
||||||
|
assertEquals(new Float(1.2), tb.getMyFloat());
|
||||||
|
assertEquals("1,2", binder.getBindingResult().getFieldValue("myFloat"));
|
||||||
|
|
||||||
|
PropertyEditor editor = binder.getBindingResult().findEditor("myFloat", Float.class);
|
||||||
|
assertNotNull(editor);
|
||||||
|
editor.setValue(new Float(1.4));
|
||||||
|
assertEquals("1,4", editor.getAsText());
|
||||||
|
|
||||||
|
editor = binder.getBindingResult().findEditor("myFloat", null);
|
||||||
|
assertNotNull(editor);
|
||||||
|
editor.setAsText("1,6");
|
||||||
|
assertEquals(new Float(1.6), editor.getValue());
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
LocaleContextHolder.resetLocaleContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBindingErrorWithFormatterAgainstFields() {
|
||||||
|
TestBean tb = new TestBean();
|
||||||
|
DataBinder binder = new DataBinder(tb);
|
||||||
|
binder.initDirectFieldAccess();
|
||||||
|
FormattingConversionService conversionService = new FormattingConversionService();
|
||||||
|
ConversionServiceFactory.addDefaultConverters(conversionService);
|
||||||
|
conversionService.addFormatterForFieldType(Float.class, new NumberFormatter());
|
||||||
|
binder.setConversionService(conversionService);
|
||||||
|
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||||
|
pvs.add("myFloat", "1x2");
|
||||||
|
|
||||||
|
LocaleContextHolder.setLocale(Locale.GERMAN);
|
||||||
|
try {
|
||||||
|
binder.bind(pvs);
|
||||||
|
assertEquals(new Float(0.0), tb.getMyFloat());
|
||||||
|
assertEquals("1x2", binder.getBindingResult().getFieldValue("myFloat"));
|
||||||
|
assertTrue(binder.getBindingResult().hasFieldErrors("myFloat"));
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
LocaleContextHolder.resetLocaleContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void testBindingWithAllowedFields() throws Exception {
|
public void testBindingWithAllowedFields() throws Exception {
|
||||||
TestBean rod = new TestBean();
|
TestBean rod = new TestBean();
|
||||||
DataBinder binder = new DataBinder(rod);
|
DataBinder binder = new DataBinder(rod);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue