diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapper.java index 8b36d9684..cb90b25e8 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapper.java @@ -17,10 +17,8 @@ package org.springframework.batch.item.file.mapping; import java.beans.PropertyEditor; -import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; @@ -38,8 +36,8 @@ import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; +import org.springframework.validation.BindException; import org.springframework.validation.DataBinder; -import org.springframework.validation.ObjectError; /** * {@link FieldSetMapper} implementation based on bean property paths. The @@ -159,27 +157,20 @@ public class BeanWrapperFieldSetMapper extends DefaultPropertyEditorRegistrar * Map the {@link FieldSet} to an object retrieved from the enclosing Spring * context, or to a new instance of the required type if no prototype is * available. - * - * @throws NotWritablePropertyException if the {@link FieldSet} contains a - * field that cannot be mapped to a bean property. - * @throws BindingException if there is a type conversion or other error (if + * @throws BindException if there is a type conversion or other error (if * the {@link DataBinder} from {@link #createBinder(Object)} has errors * after binding). * + * @throws NotWritablePropertyException if the {@link FieldSet} contains a + * field that cannot be mapped to a bean property. * @see org.springframework.batch.item.file.mapping.FieldSetMapper#mapFieldSet(FieldSet) */ - @SuppressWarnings("unchecked") - public T mapFieldSet(FieldSet fs) { + public T mapFieldSet(FieldSet fs) throws BindException { T copy = getBean(); DataBinder binder = createBinder(copy); binder.bind(new MutablePropertyValues(getBeanProperties(copy, fs.getProperties()))); if (binder.getBindingResult().hasErrors()) { - List errors = binder.getBindingResult().getAllErrors(); - List messages = new ArrayList(errors.size()); - for (ObjectError error : errors) { - messages.add(error.getDefaultMessage()); - } - throw new BindingException("" + messages); + throw new BindException(binder.getBindingResult()); } return copy; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/BindingException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/BindingException.java deleted file mode 100644 index 956ebf2ff..000000000 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/BindingException.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2006-2007 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file.mapping; - -/** - * @author Dave Syer - * - */ -public class BindingException extends RuntimeException { - - /** - * @param msg - */ - public BindingException(String msg) { - super(msg); - } - -} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/FieldSetMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/FieldSetMapper.java index 07374defc..c8a570053 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/FieldSetMapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/FieldSetMapper.java @@ -17,6 +17,7 @@ package org.springframework.batch.item.file.mapping; import org.springframework.batch.item.file.transform.FieldSet; +import org.springframework.validation.BindException; @@ -34,6 +35,7 @@ public interface FieldSetMapper { * Method used to map data obtained from a {@link FieldSet} into an object. * * @param fieldSet the {@link FieldSet} to map + * @throws BindException if there is a problem with the binding */ - T mapFieldSet(FieldSet fieldSet); + T mapFieldSet(FieldSet fieldSet) throws BindException; } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapperTests.java index 35c561abb..29bcf614c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapperTests.java @@ -21,9 +21,11 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.beans.PropertyEditor; +import java.math.BigDecimal; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -41,6 +43,7 @@ import org.springframework.beans.propertyeditors.PropertiesEditor; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.StaticApplicationContext; +import org.springframework.validation.BindException; import org.springframework.validation.DataBinder; public class BeanWrapperFieldSetMapperTests { @@ -279,7 +282,7 @@ public class BeanWrapperFieldSetMapperTests { // BeanWrapperFieldSetMapper doesn't currently support nesting with // collections. @Test - public void testNestedList() { + public void testNestedList() throws Exception { TestNestedList nestedList = new TestNestedList(); List nestedC = new ArrayList(); @@ -368,6 +371,23 @@ public class BeanWrapperFieldSetMapperTests { assertEquals(7890.1, bean.getVarFloat(), 0.01); } + @Test + public void testBinderWithErrors() throws Exception { + + BeanWrapperFieldSetMapper mapper = new BeanWrapperFieldSetMapper(); + mapper.setTargetType(TestObject.class); + + FieldSet fieldSet = new DefaultFieldSet(new String[] { "foo", "7890.1" }, new String[] { "varDouble", "varFloat" }); + try { + mapper.mapFieldSet(fieldSet); + fail("Expected BindException"); + } catch (BindException e) { + assertEquals(1, e.getErrorCount()); + assertEquals("typeMismatch", e.getFieldError("varDouble").getCode()); + } + + } + @Test public void testFieldSpecificCustomEditor() throws Exception { @@ -544,4 +564,119 @@ public class BeanWrapperFieldSetMapperTests { } } + + public static class TestObject { + String varString; + + boolean varBoolean; + + char varChar; + + byte varByte; + + short varShort; + + int varInt; + + long varLong; + + float varFloat; + + double varDouble; + + BigDecimal varBigDecimal; + + Date varDate; + + public Date getVarDate() { + return (Date)varDate.clone(); + } + + public void setVarDate(Date varDate) { + this.varDate = varDate == null ? null : (Date)varDate.clone(); + } + + public TestObject() { + } + + public BigDecimal getVarBigDecimal() { + return varBigDecimal; + } + + public void setVarBigDecimal(BigDecimal varBigDecimal) { + this.varBigDecimal = varBigDecimal; + } + + public boolean isVarBoolean() { + return varBoolean; + } + + public void setVarBoolean(boolean varBoolean) { + this.varBoolean = varBoolean; + } + + public byte getVarByte() { + return varByte; + } + + public void setVarByte(byte varByte) { + this.varByte = varByte; + } + + public char getVarChar() { + return varChar; + } + + public void setVarChar(char varChar) { + this.varChar = varChar; + } + + public double getVarDouble() { + return varDouble; + } + + public void setVarDouble(double varDouble) { + this.varDouble = varDouble; + } + + public float getVarFloat() { + return varFloat; + } + + public void setVarFloat(float varFloat) { + this.varFloat = varFloat; + } + + public long getVarLong() { + return varLong; + } + + public void setVarLong(long varLong) { + this.varLong = varLong; + } + + public short getVarShort() { + return varShort; + } + + public void setVarShort(short varShort) { + this.varShort = varShort; + } + + public String getVarString() { + return varString; + } + + public void setVarString(String varString) { + this.varString = varString; + } + + public int getVarInt() { + return varInt; + } + + public void setVarInt(int varInt) { + this.varInt = varInt; + } + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/TestObject.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/TestObject.java deleted file mode 100644 index 149021631..000000000 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/TestObject.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2006-2007 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.file.mapping; - -import java.math.BigDecimal; -import java.util.Date; - -public class TestObject { - String varString; - - boolean varBoolean; - - char varChar; - - byte varByte; - - short varShort; - - int varInt; - - long varLong; - - float varFloat; - - double varDouble; - - BigDecimal varBigDecimal; - - Date varDate; - - public Date getVarDate() { - return (Date)varDate.clone(); - } - - public void setVarDate(Date varDate) { - this.varDate = varDate == null ? null : (Date)varDate.clone(); - } - - public TestObject() { - } - - public BigDecimal getVarBigDecimal() { - return varBigDecimal; - } - - public void setVarBigDecimal(BigDecimal varBigDecimal) { - this.varBigDecimal = varBigDecimal; - } - - public boolean isVarBoolean() { - return varBoolean; - } - - public void setVarBoolean(boolean varBoolean) { - this.varBoolean = varBoolean; - } - - public byte getVarByte() { - return varByte; - } - - public void setVarByte(byte varByte) { - this.varByte = varByte; - } - - public char getVarChar() { - return varChar; - } - - public void setVarChar(char varChar) { - this.varChar = varChar; - } - - public double getVarDouble() { - return varDouble; - } - - public void setVarDouble(double varDouble) { - this.varDouble = varDouble; - } - - public float getVarFloat() { - return varFloat; - } - - public void setVarFloat(float varFloat) { - this.varFloat = varFloat; - } - - public long getVarLong() { - return varLong; - } - - public void setVarLong(long varLong) { - this.varLong = varLong; - } - - public short getVarShort() { - return varShort; - } - - public void setVarShort(short varShort) { - this.varShort = varShort; - } - - public String getVarString() { - return varString; - } - - public void setVarString(String varString) { - this.varString = varString; - } - - public int getVarInt() { - return varInt; - } - - public void setVarInt(int varInt) { - this.varInt = varInt; - } -} diff --git a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/file/mapping/bean-wrapper.xml b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/file/mapping/bean-wrapper.xml index 0994fe27d..0a5fa6071 100644 --- a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/file/mapping/bean-wrapper.xml +++ b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/file/mapping/bean-wrapper.xml @@ -9,6 +9,6 @@ - + \ No newline at end of file diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/multiline/AggregateItemFieldSetMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/multiline/AggregateItemFieldSetMapper.java index bb4292d9f..24997b8ef 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/multiline/AggregateItemFieldSetMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/multiline/AggregateItemFieldSetMapper.java @@ -19,6 +19,7 @@ import org.springframework.batch.item.file.mapping.FieldSetMapper; import org.springframework.batch.item.file.transform.FieldSet; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; +import org.springframework.validation.BindException; /** * Delegating mapper to convert form a vanilla {@link FieldSetMapper} to one @@ -82,8 +83,9 @@ public class AggregateItemFieldSetMapper implements FieldSetMapper mapFieldSet(FieldSet fieldSet) { + public AggregateItem mapFieldSet(FieldSet fieldSet) throws BindException { if (fieldSet.readString(0).equals(begin)) { return AggregateItem.getHeader();