OPEN - issue BATCH-295: JobLauncher should have only one run method.

http://jira.springframework.org/browse/BATCH-295

Add a property editor for JobIdentifier so the JMX demo can work.
This commit is contained in:
dsyer
2008-01-21 11:37:12 +00:00
parent c4e47ffab0
commit badcf74c7b
11 changed files with 410 additions and 145 deletions

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;

View File

@@ -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;
}
}
}