diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/ExportedJobLauncher.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/ExportedJobLauncher.java
index 1afbc2859..df6ecc3b2 100644
--- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/ExportedJobLauncher.java
+++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/ExportedJobLauncher.java
@@ -18,38 +18,29 @@ package org.springframework.batch.execution.bootstrap.support;
import java.util.Properties;
+import org.springframework.batch.core.domain.JobExecution;
+import org.springframework.batch.core.domain.JobIdentifier;
import org.springframework.batch.execution.launch.JobLauncher;
-import org.springframework.batch.repeat.ExitStatus;
/**
* Interface to expose for remote management of jobs. Similar to
- * {@link JobLauncher}, but replaces {@link ExitStatus} with String in return
- * types, so it can be inspected by remote clients like the jconsole from the
- * JRE without any links to Spring Batch.
+ * {@link JobLauncher}, but replaces {@link JobExecution} and
+ * {@link JobIdentifier} with Strings in return types and method parameters, so
+ * it can be inspected by remote clients like the jconsole from the JRE without
+ * any links to Spring Batch.
*
* @author Dave Syer
*
*/
public interface ExportedJobLauncher {
- /**
- * Launch a job and get back a representation of the {@link ExitStatus}
- * returned by a {@link JobLauncher}. Normally the launch will be
- * asynchronous, so the possible values of the return type are constrained
- * (it will never be {@link ExitStatus#CONTINUABLE}).
- *
- * @return a representation of the {@link ExitStatus} returned by a
- * {@link JobLauncher}.
- */
- String run();
-
/**
* Launch a job with the given name.
*
* @param name the name of the job to launch
- * @return a representation of the {@link ExitStatus} returned by a
- * {@link JobLauncher}.
- *
+ * @return a representation of the {@link JobExecution} returned by a
+ * {@link JobLauncher}.
+ *
* @see #run()
*/
String run(String name);
@@ -69,11 +60,12 @@ public interface ExportedJobLauncher {
* @see JobLauncher#isRunning()
*/
boolean isRunning();
-
+
/**
* Query statistics of currently executing jobs.
*
- * @return properties representing last known state of currently executing jobs
+ * @return properties representing last known state of currently executing
+ * jobs
*/
public Properties getStatistics();
diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/JobIdentifierPropertyEditor.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/JobIdentifierPropertyEditor.java
new file mode 100644
index 000000000..510f5f145
--- /dev/null
+++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/JobIdentifierPropertyEditor.java
@@ -0,0 +1,65 @@
+/*
+ * 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.execution.bootstrap.support;
+
+import java.beans.PropertyEditorSupport;
+
+import org.springframework.batch.core.domain.Job;
+import org.springframework.batch.core.domain.JobIdentifier;
+import org.springframework.batch.core.runtime.JobIdentifierFactory;
+import org.springframework.batch.core.runtime.SimpleJobIdentifierFactory;
+
+/**
+ * Simple adapter for a {@link JobIdentifierFactory} that can be used to convert
+ * from a {@link Job} name to a {@link JobIdentifier}.
+ *
+ * @author Dave Syer
+ *
+ */
+public class JobIdentifierPropertyEditor extends PropertyEditorSupport {
+
+ private JobIdentifierFactory jobIdentifierFactory = new SimpleJobIdentifierFactory();
+
+ /**
+ * Public setter for the {@link JobIdentifierFactory}.
+ * @param jobIdentifierFactory the jobIdentifierFactory to set
+ */
+ public void setJobIdentifierFactory(JobIdentifierFactory jobIdentifierFactory) {
+ this.jobIdentifierFactory = jobIdentifierFactory;
+ }
+
+ /**
+ * Accept name of {@link Job} and create a {@link JobIdentifier}.
+ *
+ * @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
+ */
+ public void setAsText(String text) throws IllegalArgumentException {
+ setValue(jobIdentifierFactory.getJobIdentifier(text));
+ }
+
+ /**
+ * Extract the name from the {@link JobIdentifier}.
+ *
+ * @see java.beans.PropertyEditorSupport#getAsText()
+ */
+ public String getAsText() {
+ JobIdentifier identifier = (JobIdentifier) getValue();
+ if (identifier == null) {
+ return null;
+ }
+ return identifier.getName();
+ }
+}
\ No newline at end of file
diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/TypeConverterMethodInterceptor.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/TypeConverterMethodInterceptor.java
index dc9723eef..1f9b9fd5a 100644
--- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/TypeConverterMethodInterceptor.java
+++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/bootstrap/support/TypeConverterMethodInterceptor.java
@@ -24,9 +24,12 @@ import java.util.List;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
+import org.springframework.batch.support.DefaultPropertyEditorRegistrar;
+import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.TypeMismatchException;
+import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
@@ -37,13 +40,32 @@ import org.springframework.util.ReflectionUtils;
* @author Dave Syer
*
*/
-public class TypeConverterMethodInterceptor implements MethodInterceptor {
+public class TypeConverterMethodInterceptor extends DefaultPropertyEditorRegistrar implements MethodInterceptor,
+ InitializingBean {
// Get the default PropertyEditorRegistry free.
- private TypeConverter typeConverter = new SimpleTypeConverter();
+ private TypeConverter typeConverter;
private boolean convertException = false;
+ /**
+ * Ensure that the {@link TypeConverter} is set up, creating one if
+ * necessary, and if it is a {@link PropertyEditorRegistry}, register the
+ * custom editors. (If it is not a {@link PropertyEditorRegistry} then the
+ * custom editors are ignored).
+ *
+ * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
+ */
+ public void afterPropertiesSet() throws Exception {
+ if (typeConverter == null) {
+ SimpleTypeConverter converter = new SimpleTypeConverter();
+ typeConverter = converter;
+ }
+ if (typeConverter instanceof PropertyEditorRegistry) {
+ registerCustomEditors((PropertyEditorRegistry) typeConverter);
+ }
+ }
+
/**
* Set a flag that will cause exceptions during method invocation to be
* caught and treated as a result. This can be useful if used over JConsole,
@@ -107,7 +129,7 @@ public class TypeConverterMethodInterceptor implements MethodInterceptor {
}
});
- if (methods.size()==1) {
+ if (methods.size() == 1) {
method = (Method) methods.get(0);
for (int i = 0; i < arguments.length; i++) {
Object arg = arguments[i];
diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JobDao.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JobDao.java
index 4597b5ce0..5781cfd41 100644
--- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JobDao.java
+++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JobDao.java
@@ -18,7 +18,6 @@ package org.springframework.batch.execution.repository.dao;
import java.util.List;
-import org.springframework.batch.core.domain.Job;
import org.springframework.batch.core.domain.JobExecution;
import org.springframework.batch.core.domain.JobIdentifier;
import org.springframework.batch.core.domain.JobInstance;
diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/bootstrap/support/JobIdentifierPropertyEditorTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/bootstrap/support/JobIdentifierPropertyEditorTests.java
new file mode 100644
index 000000000..71e118170
--- /dev/null
+++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/bootstrap/support/JobIdentifierPropertyEditorTests.java
@@ -0,0 +1,62 @@
+/*
+ * 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.execution.bootstrap.support;
+
+import org.springframework.batch.core.domain.JobIdentifier;
+import org.springframework.batch.core.runtime.SimpleJobIdentifierFactory;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Dave Syer
+ *
+ */
+public class JobIdentifierPropertyEditorTests extends TestCase {
+
+ private JobIdentifierPropertyEditor editor = new JobIdentifierPropertyEditor();
+
+ /**
+ * Test method for {@link org.springframework.batch.execution.bootstrap.support.JobIdentifierPropertyEditor#setJobIdentifierFactory(org.springframework.batch.core.runtime.JobIdentifierFactory)}.
+ */
+ public void testSetJobIdentifierFactory() {
+ editor.setJobIdentifierFactory(new SimpleJobIdentifierFactory() {
+ public JobIdentifier getJobIdentifier(String name) {
+ return super.getJobIdentifier("test:"+name);
+ }
+ });
+ editor.setAsText("foo");
+ JobIdentifier identifier = (JobIdentifier) editor.getValue();
+ assertEquals("test:foo", identifier.getName());
+ }
+
+ /**
+ * Test method for {@link org.springframework.batch.execution.bootstrap.support.JobIdentifierPropertyEditor#setAsText(java.lang.String)}.
+ */
+ public void testSetAsTextString() {
+ editor.setAsText("foo");
+ JobIdentifier identifier = (JobIdentifier) editor.getValue();
+ assertEquals("foo", identifier.getName());
+ }
+
+ /**
+ * Test method for {@link org.springframework.batch.execution.bootstrap.support.JobIdentifierPropertyEditor#getAsText()}.
+ */
+ public void testGetAsText() {
+ editor.setAsText("foo");
+ assertEquals("foo", editor.getAsText());
+ }
+
+}
diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/bootstrap/support/TypeConverterMethodInterceptorTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/bootstrap/support/TypeConverterMethodInterceptorTests.java
index 7f0ac1d36..eab003316 100644
--- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/bootstrap/support/TypeConverterMethodInterceptorTests.java
+++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/bootstrap/support/TypeConverterMethodInterceptorTests.java
@@ -17,6 +17,15 @@ public class TypeConverterMethodInterceptorTests extends TestCase {
private List list = new ArrayList();
+ /*
+ * (non-Javadoc)
+ * @see junit.framework.TestCase#setUp()
+ */
+ protected void setUp() throws Exception {
+ super.setUp();
+ interceptor.afterPropertiesSet();
+ }
+
/**
* Even though TestBean does not implement Test, the proxy will invoke a
* method is called with the same signature.
@@ -72,6 +81,36 @@ public class TypeConverterMethodInterceptorTests extends TestCase {
assertEquals("FOO:true", proxy.getBean());
}
+ public void testInvokeWithNoMethodMatch() throws Exception {
+ ProxyFactory factory = new ProxyFactory(Test.class, interceptor);
+ factory.setTarget(this);
+ Test proxy = (Test) factory.getProxy();
+ assertNull(proxy.getBean());
+ }
+
+ public void testInvokeWithError() throws Exception {
+ ProxyFactory factory = new ProxyFactory(Test.class, interceptor);
+ factory.setTarget(new TestBean(true));
+ Test proxy = (Test) factory.getProxy();
+ try {
+ assertNull(proxy.error());
+ fail("Expected RuntimeException");
+ }
+ catch (RuntimeException e) {
+ // expected
+ assertEquals("Foo", e.getMessage());
+ }
+ }
+
+ public void testInvokeWithErrorAndConvert() throws Exception {
+ ProxyFactory factory = new ProxyFactory(Test.class, interceptor);
+ factory.setTarget(new TestBean(true));
+ Test proxy = (Test) factory.getProxy();
+ interceptor.setConvertException(true);
+ String msg = proxy.error();
+ assertTrue("Message is not a stacktrace: "+msg, msg.indexOf("RuntimeException: Foo")>=0);
+ }
+
public void testInvokeWithMethodParameterConversionToBoolean() throws Exception {
ProxyFactory factory = new ProxyFactory(Test.class, interceptor);
factory.setTarget(new TestBean(true));
@@ -94,11 +133,12 @@ public class TypeConverterMethodInterceptorTests extends TestCase {
try {
proxy.getInvalid();
fail("Expected TypeMismatchException");
- } catch (TypeMismatchException e) {
+ }
+ catch (TypeMismatchException e) {
// expected
}
}
-
+
public void testTypeConverter() throws Exception {
final TestCase testCase = this;
interceptor.setTypeConverter(new SimpleTypeConverter() {
@@ -112,6 +152,12 @@ public class TypeConverterMethodInterceptorTests extends TestCase {
assertEquals(testCase, proxy.getInvalid());
}
+ public void testTypeConverterAfterPropertiesSet() throws Exception {
+ testTypeConverter();
+ interceptor.afterPropertiesSet();
+ testTypeConverter();
+ }
+
public void testInvokeWithMethodParameterConversionWithPropertyEditor() throws Exception {
final TestBean bean = new TestBean(false);
SimpleTypeConverter converter = new SimpleTypeConverter();
@@ -135,17 +181,19 @@ public class TypeConverterMethodInterceptorTests extends TestCase {
String relayPattern(String pattern);
TestCase getInvalid();
-
+
int getValue();
void operate();
-
+
String grab(String value);
-
+
String relayBean(String value);
+
+ String error();
}
- // N.B. TestBean intentionally does not implement Test!
+ // N.B. TestBean intentionally does not implement Test!
public class TestBean {
private boolean test;
@@ -173,7 +221,7 @@ public class TypeConverterMethodInterceptorTests extends TestCase {
public TestBean getInvalid() {
return this;
}
-
+
public String getValue() {
return "123";
}
@@ -181,14 +229,18 @@ public class TypeConverterMethodInterceptorTests extends TestCase {
public void operate() {
list.add("FOO");
}
-
+
public String grab(boolean flag) {
- return "flag:"+flag;
+ return "flag:" + flag;
}
public String toString() {
return "FOO:" + test;
}
+
+ public String error() {
+ throw new RuntimeException("Foo");
+ }
}
}
diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/mapping/BeanWrapperFieldSetMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/mapping/BeanWrapperFieldSetMapper.java
index 7791fb3ee..d67557fc7 100644
--- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/mapping/BeanWrapperFieldSetMapper.java
+++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/mapping/BeanWrapperFieldSetMapper.java
@@ -16,7 +16,6 @@
package org.springframework.batch.io.file.mapping;
-import java.beans.PropertyEditor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -26,6 +25,7 @@ import java.util.Map;
import java.util.Properties;
import java.util.Set;
+import org.springframework.batch.support.DefaultPropertyEditorRegistrar;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.NotWritablePropertyException;
@@ -35,9 +35,7 @@ import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
-import org.springframework.beans.factory.config.CustomEditorConfigurer;
import org.springframework.util.Assert;
-import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.validation.DataBinder;
import org.springframework.validation.ObjectError;
@@ -78,7 +76,7 @@ import org.springframework.validation.ObjectError;
* @author Dave Syer
*
*/
-public class BeanWrapperFieldSetMapper implements FieldSetMapper, BeanFactoryAware, InitializingBean {
+public class BeanWrapperFieldSetMapper extends DefaultPropertyEditorRegistrar implements FieldSetMapper, BeanFactoryAware, InitializingBean {
private String name;
@@ -86,8 +84,6 @@ public class BeanWrapperFieldSetMapper implements FieldSetMapper, BeanFactoryAwa
private BeanFactory beanFactory;
- private Map customEditors;
-
private static Map propertiesMatched = new HashMap();
private static int distanceLimit = 5;
@@ -187,27 +183,10 @@ public class BeanWrapperFieldSetMapper implements FieldSetMapper, BeanFactoryAwa
DataBinder binder = new DataBinder(target);
binder.setIgnoreUnknownFields(false);
initBinder(binder);
- registerPropertyEditors(binder);
+ registerCustomEditors(binder);
return binder;
}
- /**
- * Register property editors with the DataBinder. If any property editors
- * have been supplied they are registered for use when binding a field set.
- *
- * @param binder new binder instance
- */
- protected void registerPropertyEditors(DataBinder binder) {
- if (this.customEditors != null) {
- for (Iterator it = customEditors.entrySet().iterator(); it.hasNext();) {
- Map.Entry entry = (Map.Entry) it.next();
- Class key = (Class) entry.getKey();
- PropertyEditor value = (PropertyEditor) entry.getValue();
- binder.registerCustomEditor(key, value);
- }
- }
- }
-
/**
* Initialize a new binder instance. This hook allows customization of
* binder settings such as the
@@ -336,38 +315,4 @@ public class BeanWrapperFieldSetMapper implements FieldSetMapper, BeanFactoryAwa
properties.setProperty(newName, value);
}
- /**
- * Specify the {@link PropertyEditor custom editors} to apply to target
- * beans mapped with this {@link FieldSetMapper}.
- *
- *
- * @param customEditors a map of Class to PropertyEditor (or class name to
- * PropertyEditor).
- * @see CustomEditorConfigurer#setCustomEditors(Map)
- */
- public void setCustomEditors(Map customEditors) {
- this.customEditors = new HashMap();
- for (Iterator it = customEditors.entrySet().iterator(); it.hasNext();) {
- Map.Entry entry = (Map.Entry) it.next();
- Object key = entry.getKey();
- Class requiredType = null;
- if (key instanceof Class) {
- requiredType = (Class) key;
- }
- else if (key instanceof String) {
- String className = (String) key;
- requiredType = ClassUtils.resolveClassName(className, getClass().getClassLoader());
- }
- else {
- throw new IllegalArgumentException("Invalid key [" + key
- + "] for custom editor: needs to be Class or String.");
- }
- Object value = entry.getValue();
- if (!(value instanceof PropertyEditor)) {
- throw new IllegalArgumentException("Mapped value [" + value + "] for custom editor key [" + key
- + "] is not of required type [" + PropertyEditor.class.getName() + "]");
- }
- this.customEditors.put(requiredType, value);
- }
- }
}
diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/DefaultPropertyEditorRegistrar.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/DefaultPropertyEditorRegistrar.java
new file mode 100644
index 000000000..d3b478183
--- /dev/null
+++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/DefaultPropertyEditorRegistrar.java
@@ -0,0 +1,90 @@
+/*
+ * 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.support;
+
+import java.beans.PropertyEditor;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.springframework.beans.PropertyEditorRegistrar;
+import org.springframework.beans.PropertyEditorRegistry;
+import org.springframework.beans.factory.config.CustomEditorConfigurer;
+import org.springframework.util.ClassUtils;
+
+/**
+ * A re-usable {@link PropertyEditorRegistrar} that can be used wherever one
+ * needs to register custom {@link PropertyEditor} instances with a
+ * {@link PropertyEditorRegistry} (like a bean wrapper, or a type converter).
+ *
+ * @author Dave Syer
+ *
+ */
+public class DefaultPropertyEditorRegistrar implements PropertyEditorRegistrar {
+
+ private Map customEditors;
+
+ /**
+ * Register the custom editors with the given registry.
+ *
+ * @see org.springframework.beans.PropertyEditorRegistrar#registerCustomEditors(org.springframework.beans.PropertyEditorRegistry)
+ */
+ public void registerCustomEditors(PropertyEditorRegistry registry) {
+ if (this.customEditors != null) {
+ for (Iterator it = customEditors.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry) it.next();
+ Class key = (Class) entry.getKey();
+ PropertyEditor value = (PropertyEditor) entry.getValue();
+ registry.registerCustomEditor(key, value);
+ }
+ }
+ }
+
+ /**
+ * Specify the {@link PropertyEditor custom editors} to register.
+ *
+ *
+ * @param customEditors a map of Class to PropertyEditor (or class name to
+ * PropertyEditor).
+ * @see CustomEditorConfigurer#setCustomEditors(Map)
+ */
+ public void setCustomEditors(Map customEditors) {
+ this.customEditors = new HashMap();
+ for (Iterator it = customEditors.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry) it.next();
+ Object key = entry.getKey();
+ Class requiredType = null;
+ if (key instanceof Class) {
+ requiredType = (Class) key;
+ }
+ else if (key instanceof String) {
+ String className = (String) key;
+ requiredType = ClassUtils.resolveClassName(className, getClass().getClassLoader());
+ }
+ else {
+ throw new IllegalArgumentException("Invalid key [" + key
+ + "] for custom editor: needs to be Class or String.");
+ }
+ Object value = entry.getValue();
+ if (!(value instanceof PropertyEditor)) {
+ throw new IllegalArgumentException("Mapped value [" + value + "] for custom editor key [" + key
+ + "] is not of required type [" + PropertyEditor.class.getName() + "]");
+ }
+ this.customEditors.put(requiredType, value);
+ }
+ }
+
+}
diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/mapping/BeanWrapperFieldSetMapperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/mapping/BeanWrapperFieldSetMapperTests.java
index e84d5971c..55fc1b246 100644
--- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/mapping/BeanWrapperFieldSetMapperTests.java
+++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/mapping/BeanWrapperFieldSetMapperTests.java
@@ -24,9 +24,6 @@ import java.util.Properties;
import junit.framework.TestCase;
-import org.springframework.batch.io.file.mapping.BeanWrapperFieldSetMapper;
-import org.springframework.batch.io.file.mapping.BindingException;
-import org.springframework.batch.support.IntArrayPropertyEditor;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.NotWritablePropertyException;
import org.springframework.beans.propertyeditors.CustomNumberEditor;
@@ -252,17 +249,6 @@ public class BeanWrapperFieldSetMapperTests extends TestCase {
assertEquals('C', result.getVarChar());
}
- public void testIntArray() throws Exception {
- BeanWithIntArray result = new BeanWithIntArray();
- BeanWrapperImpl wrapper = new BeanWrapperImpl(result);
- wrapper.registerCustomEditor(int[].class, new IntArrayPropertyEditor());
- PropertiesEditor editor = new PropertiesEditor();
- editor.setAsText("numbers=1,2,3, 4");
- Properties props = (Properties) editor.getValue();
- wrapper.setPropertyValues(props);
- assertEquals(4, result.numbers[3]);
- }
-
// BeanWrapperFieldSetMapper doesn't currently support nesting with
// collections.
public void testNestedList() {
@@ -307,37 +293,6 @@ public class BeanWrapperFieldSetMapperTests extends TestCase {
}
}
- public void testSetCustomEditorsWithInvalidTypeName() throws Exception {
-
- BeanWrapperFieldSetMapper mapper = new BeanWrapperFieldSetMapper();
- try {
- mapper.setCustomEditors(Collections.singletonMap("FOO", new CustomNumberEditor(Long.class, true)));
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- public void testSetCustomEditorsWithInvalidType() throws Exception {
-
- BeanWrapperFieldSetMapper mapper = new BeanWrapperFieldSetMapper();
- try {
- mapper.setCustomEditors(Collections.singletonMap(new Object(), new CustomNumberEditor(Long.class, true)));
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
-
- public void testSetCustomEditorsWithInvalidEditor() throws Exception {
-
- BeanWrapperFieldSetMapper mapper = new BeanWrapperFieldSetMapper();
- try {
- mapper.setCustomEditors(Collections.singletonMap(Long.class, "FOO"));
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
public void testPaddedLongWithEditor() throws Exception {
BeanWrapperFieldSetMapper mapper = new BeanWrapperFieldSetMapper();
@@ -367,14 +322,6 @@ public class BeanWrapperFieldSetMapperTests extends TestCase {
assertEquals(78, bean.getVarInt());
}
- private static class BeanWithIntArray {
- private int[] numbers;
-
- public void setNumbers(int[] numbers) {
- this.numbers = numbers;
- }
- }
-
private static class TestNestedList {
List nestedC;
diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/DefaultPropertEditorRegistrarTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/DefaultPropertEditorRegistrarTests.java
new file mode 100644
index 000000000..73c4e3d95
--- /dev/null
+++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/DefaultPropertEditorRegistrarTests.java
@@ -0,0 +1,84 @@
+/*
+ * 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.io.support;
+
+import java.util.Collections;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+import org.springframework.batch.support.DefaultPropertyEditorRegistrar;
+import org.springframework.batch.support.IntArrayPropertyEditor;
+import org.springframework.beans.BeanWrapperImpl;
+import org.springframework.beans.propertyeditors.CustomNumberEditor;
+import org.springframework.beans.propertyeditors.PropertiesEditor;
+
+public class DefaultPropertEditorRegistrarTests extends TestCase {
+
+ public void testIntArray() throws Exception {
+ DefaultPropertyEditorRegistrar mapper = new DefaultPropertyEditorRegistrar();
+ BeanWithIntArray result = new BeanWithIntArray();
+ BeanWrapperImpl wrapper = new BeanWrapperImpl(result);
+ mapper.setCustomEditors(Collections.singletonMap(int[].class, new IntArrayPropertyEditor()));
+ mapper.registerCustomEditors(wrapper);
+ PropertiesEditor editor = new PropertiesEditor();
+ editor.setAsText("numbers=1,2,3, 4");
+ Properties props = (Properties) editor.getValue();
+ wrapper.setPropertyValues(props);
+ assertEquals(4, result.numbers[3]);
+ }
+
+ public void testSetCustomEditorsWithInvalidTypeName() throws Exception {
+
+ DefaultPropertyEditorRegistrar mapper = new DefaultPropertyEditorRegistrar();
+ try {
+ mapper.setCustomEditors(Collections.singletonMap("FOO", new CustomNumberEditor(Long.class, true)));
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testSetCustomEditorsWithInvalidType() throws Exception {
+
+ DefaultPropertyEditorRegistrar mapper = new DefaultPropertyEditorRegistrar();
+ try {
+ mapper.setCustomEditors(Collections.singletonMap(new Object(), new CustomNumberEditor(Long.class, true)));
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+
+ public void testSetCustomEditorsWithInvalidEditor() throws Exception {
+
+ DefaultPropertyEditorRegistrar mapper = new DefaultPropertyEditorRegistrar();
+ try {
+ mapper.setCustomEditors(Collections.singletonMap(Long.class, "FOO"));
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ private static class BeanWithIntArray {
+ private int[] numbers;
+
+ public void setNumbers(int[] numbers) {
+ this.numbers = numbers;
+ }
+ }
+
+}
diff --git a/spring-batch-samples/src/main/resources/jobs/adhocLoopJob.xml b/spring-batch-samples/src/main/resources/jobs/adhocLoopJob.xml
index 9522b1da3..7ab538998 100644
--- a/spring-batch-samples/src/main/resources/jobs/adhocLoopJob.xml
+++ b/spring-batch-samples/src/main/resources/jobs/adhocLoopJob.xml
@@ -102,7 +102,14 @@
-
+
+
+
+