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:
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -102,7 +102,14 @@
|
||||
|
||||
<bean id="convertingMethodInterceptor"
|
||||
class="org.springframework.batch.execution.bootstrap.support.TypeConverterMethodInterceptor">
|
||||
<property name="convertException" value="true" />
|
||||
<property name="convertException" value="true" />
|
||||
<property name="customEditors">
|
||||
<map>
|
||||
<entry key="org.springframework.batch.core.domain.JobIdentifier">
|
||||
<bean class="org.springframework.batch.execution.bootstrap.support.JobIdentifierPropertyEditor"/>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="logAdvice"
|
||||
|
||||
Reference in New Issue
Block a user