diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java b/org.springframework.beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java index 56753956ff4..255ebb435c7 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java @@ -781,7 +781,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra "Getter for property '" + actualName + "' threw exception", ex); } - catch(IllegalAccessException ex) { + catch (IllegalAccessException ex) { throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName, "Illegal attempt to get property '" + actualName + "' threw exception", ex); } @@ -813,7 +813,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra } setPropertyValue(name, newArray); return newArray; - } else { + } + else { return array; } } diff --git a/org.springframework.beans/src/main/java/org/springframework/beans/DirectFieldAccessor.java b/org.springframework.beans/src/main/java/org/springframework/beans/DirectFieldAccessor.java index c2d6629023d..04425df2115 100644 --- a/org.springframework.beans/src/main/java/org/springframework/beans/DirectFieldAccessor.java +++ b/org.springframework.beans/src/main/java/org/springframework/beans/DirectFieldAccessor.java @@ -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"); * 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 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.util.Assert; import org.springframework.util.ReflectionUtils; @@ -125,10 +127,11 @@ public class DirectFieldAccessor extends AbstractPropertyAccessor { Object convertedValue = this.typeConverterDelegate.convertIfNecessary(oldValue, newValue, field); field.set(this.target, convertedValue); } - catch (IllegalAccessException ex) { - throw new InvalidPropertyException(this.target.getClass(), propertyName, "Field is not accessible", ex); + catch (ConverterNotFoundException 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); 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); 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 convertIfNecessary( diff --git a/org.springframework.context/src/main/java/org/springframework/validation/DataBinder.java b/org.springframework.context/src/main/java/org/springframework/validation/DataBinder.java index fa90fba98c0..6653905900a 100644 --- a/org.springframework.context/src/main/java/org/springframework/validation/DataBinder.java +++ b/org.springframework.context/src/main/java/org/springframework/validation/DataBinder.java @@ -495,7 +495,11 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter { * property values, as an alternative to JavaBeans PropertyEditors. */ public void setConversionService(ConversionService conversionService) { + Assert.state(this.conversionService == null, "DataBinder is already initialized with ConversionService"); this.conversionService = conversionService; + if (this.bindingResult != null && conversionService != null) { + this.bindingResult.initConversion(conversionService); + } } /** diff --git a/org.springframework.context/src/test/java/org/springframework/validation/DataBinderTests.java b/org.springframework.context/src/test/java/org/springframework/validation/DataBinderTests.java index 097f42e7a1c..baba01a67e7 100644 --- a/org.springframework.context/src/test/java/org/springframework/validation/DataBinderTests.java +++ b/org.springframework.context/src/test/java/org/springframework/validation/DataBinderTests.java @@ -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"); * 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 { TestBean rod = new TestBean(); DataBinder binder = new DataBinder(rod);