RESOLVED - issue BATCH-1420: Late Binding only happens first time when using inner bean definition with collection property
This commit is contained in:
@@ -30,6 +30,8 @@ import org.springframework.beans.PropertyEditorRegistrySupport;
|
||||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.beans.TypeMismatchException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionVisitor;
|
||||
import org.springframework.beans.factory.config.TypedStringValue;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
@@ -266,7 +268,7 @@ public class PlaceholderTargetSource extends SimpleBeanTargetSource implements I
|
||||
|
||||
private Object getPropertyFromContext(String key) {
|
||||
Object context = contextFactory.getContext();
|
||||
if (context==null) {
|
||||
if (context == null) {
|
||||
throw new IllegalStateException("No context available while replacing placeholders.");
|
||||
}
|
||||
BeanWrapper wrapper = new BeanWrapperImpl(context);
|
||||
@@ -334,30 +336,47 @@ public class PlaceholderTargetSource extends SimpleBeanTargetSource implements I
|
||||
}
|
||||
}
|
||||
|
||||
} else if (value instanceof Map) {
|
||||
|
||||
}
|
||||
else if (value instanceof Map) {
|
||||
|
||||
Map map = (Map) value;
|
||||
Map newValue = new ManagedMap(map.size());
|
||||
newValue.putAll(map);
|
||||
super.visitMap(newValue);
|
||||
value = newValue;
|
||||
|
||||
} else if (value instanceof List) {
|
||||
|
||||
|
||||
}
|
||||
else if (value instanceof List) {
|
||||
|
||||
List list = (List) value;
|
||||
List newValue = new ManagedList(list.size());
|
||||
newValue.addAll(list);
|
||||
super.visitList(newValue);
|
||||
value = newValue;
|
||||
|
||||
} else if (value instanceof Set) {
|
||||
|
||||
|
||||
}
|
||||
else if (value instanceof Set) {
|
||||
|
||||
Set list = (Set) value;
|
||||
Set newValue = new ManagedSet(list.size());
|
||||
newValue.addAll(list);
|
||||
super.visitSet(newValue);
|
||||
value = newValue;
|
||||
|
||||
|
||||
}
|
||||
else if (value instanceof BeanDefinition) {
|
||||
|
||||
BeanDefinition newValue = new GenericBeanDefinition((BeanDefinition) value);
|
||||
visitBeanDefinition((BeanDefinition) newValue);
|
||||
value = newValue;
|
||||
|
||||
}
|
||||
else if (value instanceof BeanDefinitionHolder) {
|
||||
|
||||
BeanDefinition newValue = new GenericBeanDefinition(((BeanDefinitionHolder) value).getBeanDefinition());
|
||||
visitBeanDefinition((BeanDefinition) newValue);
|
||||
value = newValue;
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import static org.junit.Assert.fail;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -26,6 +27,8 @@ public class TaskExecutorPartitionHandlerTests {
|
||||
private TaskExecutorPartitionHandler handler = new TaskExecutorPartitionHandler();
|
||||
|
||||
private int count = 0;
|
||||
|
||||
private Collection<String> stepExecutions = new TreeSet<String>();
|
||||
|
||||
private StepExecution stepExecution = new StepExecution("step", new JobExecution(1L));
|
||||
|
||||
@@ -50,6 +53,7 @@ public class TaskExecutorPartitionHandlerTests {
|
||||
@Override
|
||||
public void execute(StepExecution stepExecution) throws JobInterruptedException {
|
||||
count++;
|
||||
stepExecutions.add(stepExecution.getStepName());
|
||||
}
|
||||
});
|
||||
handler.afterPropertiesSet();
|
||||
@@ -74,6 +78,7 @@ public class TaskExecutorPartitionHandlerTests {
|
||||
handler.setGridSize(2);
|
||||
handler.handle(stepExecutionSplitter, stepExecution);
|
||||
assertEquals(2, count);
|
||||
assertEquals("[foo0, foo1]", stepExecutions.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -61,6 +61,10 @@ public class MultipleContextPlaceholderTargetSourceTests {
|
||||
@Qualifier("list")
|
||||
private TestBean list;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("nestedList")
|
||||
private TestBean nestedList;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("map")
|
||||
private TestBean map;
|
||||
@@ -120,6 +124,23 @@ public class MultipleContextPlaceholderTargetSourceTests {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleValueInNestedList() throws Exception {
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
final String value = "foo" + i;
|
||||
contextFactory.setContext(this);
|
||||
attributes = Collections.singletonMap("foo", value);
|
||||
try {
|
||||
assertEquals("foo" + i, nestedList.getParent().getNames().get(0));
|
||||
}
|
||||
finally {
|
||||
contextFactory.clearContext();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleValueInMap() throws Exception {
|
||||
|
||||
@@ -144,10 +165,20 @@ public class MultipleContextPlaceholderTargetSourceTests {
|
||||
|
||||
public static class TestBean {
|
||||
private String name;
|
||||
|
||||
private TestBean parent;
|
||||
|
||||
private List<String> names = new ArrayList<String>();
|
||||
|
||||
private Map<String, String> map = new HashMap<String, String>();
|
||||
|
||||
public TestBean getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void setParent(TestBean parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
|
||||
@@ -36,6 +36,16 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="nestedList" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="targetSource">
|
||||
<bean
|
||||
class="org.springframework.batch.core.scope.util.PlaceholderTargetSource">
|
||||
<property name="contextFactory" ref="context" />
|
||||
<property name="targetBeanName" value="nestedListTarget" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="map" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="targetSource">
|
||||
<bean
|
||||
@@ -60,7 +70,22 @@
|
||||
class="org.springframework.batch.core.scope.util.MultipleContextPlaceholderTargetSourceTests$TestBean">
|
||||
<property name="names">
|
||||
<list>
|
||||
<value>%{attributes[foo]}</value></list>
|
||||
<value>%{attributes[foo]}</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="nestedListTarget"
|
||||
class="org.springframework.batch.core.scope.util.MultipleContextPlaceholderTargetSourceTests$TestBean">
|
||||
<property name="parent">
|
||||
<bean
|
||||
class="org.springframework.batch.core.scope.util.MultipleContextPlaceholderTargetSourceTests$TestBean">
|
||||
<property name="names">
|
||||
<list>
|
||||
<value>%{attributes[foo]}</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beansProjectDescription>
|
||||
<version>1</version>
|
||||
<pluginVersion><![CDATA[2.2.7.200909172100-CI-R3407-B467]]></pluginVersion>
|
||||
<pluginVersion><![CDATA[2.2.7.200909182116-CI-R3408-B468]]></pluginVersion>
|
||||
<configSuffixes>
|
||||
<configSuffix><![CDATA[xml]]></configSuffix>
|
||||
</configSuffixes>
|
||||
@@ -60,13 +60,11 @@
|
||||
<config>src/test/resources/org/springframework/batch/sample/MultilineJobFunctionalTests-context.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/sample/MultilineOrderJobFunctionalTests-context.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/sample/ParallelJobFunctionalTests-context.xml</config>
|
||||
<config>src/main/resources/jobs/partitionJob.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/sample/RestartFunctionalTests-context.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/sample/RetrySampleFunctionalTests-context.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/sample/common/StagingItemReaderTests-context.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/sample/common/StagingItemWriterTests-context.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/sample/TradeJobFunctionalTests-context.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/sample/PartitionJobFunctionalTests-context.xml</config>
|
||||
<config>src/main/resources/jobs/multilineOrderValidator.xml</config>
|
||||
<config>src/main/resources/jobs/restartFileSampleJob.xml</config>
|
||||
<config>src/main/resources/jobs/taskletJob.xml</config>
|
||||
@@ -75,6 +73,7 @@
|
||||
<config>src/main/resources/jobs/iosample/jdbcPaging.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/sample/GroovyJobFunctionalTests-context.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/sample/TaskletJobFunctionalTests-context.xml</config>
|
||||
<config>src/main/resources/jobs/partitionJdbcJob.xml</config>
|
||||
</configs>
|
||||
<configSets>
|
||||
<configSet>
|
||||
@@ -395,7 +394,6 @@
|
||||
<incomplete>false</incomplete>
|
||||
<configs>
|
||||
<config>src/main/resources/data-source-context.xml</config>
|
||||
<config>src/main/resources/jobs/partitionJob.xml</config>
|
||||
<config>src/main/resources/simple-job-launcher-context.xml</config>
|
||||
</configs>
|
||||
</configSet>
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
package org.springframework.batch.sample.common;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.batch.core.partition.support.Partitioner;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
|
||||
|
||||
/**
|
||||
* Simple minded partitioner for a range of values of a column in a database
|
||||
* table. Works best if the values are uniformly distributed (e.g.
|
||||
* auto-generated primary key values).
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class ColumnRangePartitioner implements Partitioner {
|
||||
|
||||
private SimpleJdbcTemplate jdbcTemplate;
|
||||
|
||||
private String table;
|
||||
|
||||
private String column;
|
||||
|
||||
/**
|
||||
* The name of the SQL table the data are in.
|
||||
*
|
||||
* @param table the name of the table
|
||||
*/
|
||||
public void setTable(String table) {
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the column to partition.
|
||||
*
|
||||
* @param column the column name.
|
||||
*/
|
||||
public void setColumn(String column) {
|
||||
this.column = column;
|
||||
}
|
||||
|
||||
/**
|
||||
* The data source for connecting to the database.
|
||||
*
|
||||
* @param dataSource a {@link DataSource}
|
||||
*/
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
jdbcTemplate = new SimpleJdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Partition a database table assuming that the data in the column specified
|
||||
* are uniformly distributed. The execution context values will have keys
|
||||
* <code>minValue</code> and <code>maxValue</code> specifying the range of
|
||||
* values to consider in each partition.
|
||||
*
|
||||
* @see Partitioner#partition(int)
|
||||
*/
|
||||
public Map<String, ExecutionContext> partition(int gridSize) {
|
||||
|
||||
int min = jdbcTemplate.queryForInt("SELECT MIN(" + column + ") from " + table);
|
||||
int max = jdbcTemplate.queryForInt("SELECT MAX(" + column + ") from " + table);
|
||||
int targetSize = (max - min) / gridSize + 1;
|
||||
|
||||
Map<String, ExecutionContext> result = new HashMap<String, ExecutionContext>();
|
||||
int number = 0;
|
||||
int start = min;
|
||||
int end = start + targetSize - 1;
|
||||
|
||||
while (start <= max) {
|
||||
|
||||
ExecutionContext value = new ExecutionContext();
|
||||
result.put("partition" + number, value);
|
||||
|
||||
if (end >= max) {
|
||||
end = max;
|
||||
}
|
||||
value.putInt("minValue", start);
|
||||
value.putInt("maxValue", end);
|
||||
start += targetSize;
|
||||
end += targetSize;
|
||||
number++;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,6 +30,12 @@ public class OutputFileListener {
|
||||
|
||||
private String inputKeyName = "fileName";
|
||||
|
||||
private String path = "file:./target/output/";
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public void setOutputKeyName(String outputKeyName) {
|
||||
this.outputKeyName = outputKeyName;
|
||||
}
|
||||
@@ -39,11 +45,15 @@ public class OutputFileListener {
|
||||
}
|
||||
|
||||
@BeforeStep
|
||||
public void CreateOutputNameFromInput(StepExecution stepExecution) {
|
||||
public void createOutputNameFromInput(StepExecution stepExecution) {
|
||||
ExecutionContext executionContext = stepExecution.getExecutionContext();
|
||||
if (executionContext.containsKey(inputKeyName) && !executionContext.containsKey(outputKeyName)) {
|
||||
String inputName = executionContext.getString(inputKeyName);
|
||||
executionContext.putString(outputKeyName, "file:./target/output/" + FilenameUtils.getBaseName(inputName) + ".csv");
|
||||
String inputName = stepExecution.getStepName().replace(":", "-");
|
||||
if (executionContext.containsKey(inputKeyName)) {
|
||||
inputName = executionContext.getString(inputKeyName);
|
||||
}
|
||||
if (!executionContext.containsKey(outputKeyName)) {
|
||||
executionContext.putString(outputKeyName, path + FilenameUtils.getBaseName(inputName)
|
||||
+ ".csv");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
<bean class="org.springframework.core.task.SyncTaskExecutor" />
|
||||
</property>
|
||||
<property name="step" ref="step1" />
|
||||
<property name="gridSize" value="2"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
@@ -42,7 +43,10 @@
|
||||
</tasklet>
|
||||
</step>
|
||||
|
||||
<bean id="fileNameListener" class="org.springframework.batch.sample.common.OutputFileListener" scope="step"/>
|
||||
<bean id="fileNameListener" class="org.springframework.batch.sample.common.OutputFileListener" scope="step">
|
||||
<property name="path" value="file:./target/output/file/"/>
|
||||
</bean>
|
||||
|
||||
|
||||
<bean id="itemReader" scope="step" autowire-candidate="false" parent="itemReaderParent">
|
||||
<property name="resource" value="#{stepExecutionContext[fileName]}" />
|
||||
@@ -54,7 +58,7 @@
|
||||
</bean>
|
||||
|
||||
<bean id="outputTestReader" class="org.springframework.batch.item.file.MultiResourceItemReader" scope="prototype">
|
||||
<property name="resources" value="file:target/output/delimited*.csv" />
|
||||
<property name="resources" value="file:target/output/file/delimited*.csv" />
|
||||
<property name="delegate" ref="testItemReader" />
|
||||
</bean>
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
|
||||
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.0.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
|
||||
|
||||
<job id="partitionJdbcJob" xmlns="http://www.springframework.org/schema/batch">
|
||||
<step id="step" parent="step1:master" />
|
||||
</job>
|
||||
|
||||
<bean name="step1:master"
|
||||
class="org.springframework.batch.core.partition.support.PartitionStep">
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
<property name="stepExecutionSplitter">
|
||||
<bean
|
||||
class="org.springframework.batch.core.partition.support.SimpleStepExecutionSplitter">
|
||||
<constructor-arg ref="jobRepository" />
|
||||
<constructor-arg ref="step1" />
|
||||
<constructor-arg>
|
||||
<bean
|
||||
class="org.springframework.batch.sample.common.ColumnRangePartitioner">
|
||||
<property name="dataSource" ref="dataSource" />
|
||||
<property name="table" value="CUSTOMER" />
|
||||
<property name="column" value="ID" />
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="partitionHandler">
|
||||
<bean
|
||||
class="org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler">
|
||||
<property name="taskExecutor">
|
||||
<bean class="org.springframework.core.task.SyncTaskExecutor" />
|
||||
</property>
|
||||
<property name="step" ref="step1" />
|
||||
<property name="gridSize" value="2"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<step id="step1" xmlns="http://www.springframework.org/schema/batch">
|
||||
<tasklet job-repository="jobRepository" transaction-manager="transactionManager">
|
||||
<chunk writer="itemWriter" reader="itemReader" processor="itemProcessor"
|
||||
commit-interval="5" />
|
||||
<listeners>
|
||||
<listener ref="fileNameListener" />
|
||||
</listeners>
|
||||
</tasklet>
|
||||
</step>
|
||||
|
||||
<bean id="fileNameListener"
|
||||
class="org.springframework.batch.sample.common.OutputFileListener"
|
||||
scope="step">
|
||||
<property name="path" value="file:./target/output/jdbc/"/>
|
||||
</bean>
|
||||
|
||||
<bean id="itemReader" scope="step" autowire-candidate="false"
|
||||
parent="itemReaderParent">
|
||||
<property name="sql">
|
||||
<value>
|
||||
<![CDATA[
|
||||
select ID,NAME,CREDIT from CUSTOMER where ID >= ? and ID <= ?
|
||||
]]>
|
||||
</value>
|
||||
</property>
|
||||
<property name="preparedStatementSetter">
|
||||
<bean
|
||||
class="org.springframework.batch.core.resource.ListPreparedStatementSetter">
|
||||
<property name="parameters">
|
||||
<list>
|
||||
<value>#{stepExecutionContext[minValue]}</value>
|
||||
<value>#{stepExecutionContext[maxValue]}</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="outputTestReader"
|
||||
class="org.springframework.batch.item.file.MultiResourceItemReader"
|
||||
scope="prototype">
|
||||
<property name="resources" value="file:target/output/jdbc/*.csv" />
|
||||
<property name="delegate" ref="testItemReader" />
|
||||
</bean>
|
||||
|
||||
<bean id="testItemReader" class="org.springframework.batch.item.file.FlatFileItemReader">
|
||||
<property name="lineMapper">
|
||||
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
|
||||
<property name="lineTokenizer">
|
||||
<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
|
||||
<property name="delimiter" value="," />
|
||||
<property name="names" value="id,name,credit" />
|
||||
</bean>
|
||||
</property>
|
||||
<property name="fieldSetMapper">
|
||||
<bean class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
|
||||
<property name="targetType" value="org.springframework.batch.sample.domain.trade.CustomerCredit" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="inputTestReader" parent="itemReaderParent">
|
||||
<property name="sql">
|
||||
<value>
|
||||
<![CDATA[
|
||||
select ID,NAME,CREDIT from CUSTOMER
|
||||
]]>
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="itemReaderParent"
|
||||
class="org.springframework.batch.item.database.JdbcCursorItemReader"
|
||||
abstract="true">
|
||||
<property name="dataSource" ref="dataSource" />
|
||||
<property name="rowMapper">
|
||||
<bean
|
||||
class="org.springframework.batch.sample.domain.trade.internal.CustomerCreditRowMapper" />
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="itemProcessor"
|
||||
class="org.springframework.batch.sample.domain.trade.internal.CustomerCreditIncreaseProcessor" />
|
||||
|
||||
<bean id="itemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter"
|
||||
scope="step">
|
||||
<property name="resource" value="#{stepExecutionContext[outputFile]}" />
|
||||
<property name="lineAggregator">
|
||||
<bean
|
||||
class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
|
||||
<property name="delimiter" value="," />
|
||||
<property name="fieldExtractor">
|
||||
<bean
|
||||
class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
|
||||
<property name="names" value="id,name,credit" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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.sample;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemStream;
|
||||
import org.springframework.batch.sample.domain.trade.CustomerCredit;
|
||||
import org.springframework.batch.sample.domain.trade.internal.CustomerCreditIncreaseProcessor;
|
||||
import org.springframework.batch.test.AbstractJobTests;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration()
|
||||
public class PartitionFileJobFunctionalTests extends AbstractJobTests {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("inputTestReader")
|
||||
private ItemReader<CustomerCredit> inputReader;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("outputTestReader")
|
||||
private ItemReader<CustomerCredit> outputReader;
|
||||
|
||||
/**
|
||||
* Check the resulting credits correspond to inputs increased by fixed
|
||||
* amount.
|
||||
*/
|
||||
@Test
|
||||
public void testUpdateCredit() throws Exception {
|
||||
|
||||
assertTrue("Define a prototype bean called 'outputTestReader' to check the output", getApplicationContext()
|
||||
.containsBeanDefinition("outputTestReader"));
|
||||
|
||||
open(inputReader);
|
||||
List<CustomerCredit> inputs = new ArrayList<CustomerCredit>(getCredits(inputReader));
|
||||
close(inputReader);
|
||||
|
||||
JobExecution jobExecution = this.launchJob();
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
|
||||
open(outputReader);
|
||||
List<CustomerCredit> outputs = new ArrayList<CustomerCredit>(getCredits(outputReader));
|
||||
close(outputReader);
|
||||
|
||||
assertEquals(inputs.size(), outputs.size());
|
||||
int itemCount = inputs.size();
|
||||
assertTrue(itemCount > 0);
|
||||
|
||||
inputs.iterator();
|
||||
for (int i = 0; i < itemCount; i++) {
|
||||
assertEquals(inputs.get(i).getCredit().add(CustomerCreditIncreaseProcessor.FIXED_AMOUNT).intValue(),
|
||||
outputs.get(i).getCredit().intValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all credits using the provided reader.
|
||||
*/
|
||||
private Set<CustomerCredit> getCredits(ItemReader<CustomerCredit> reader) throws Exception {
|
||||
CustomerCredit credit;
|
||||
Set<CustomerCredit> result = new LinkedHashSet<CustomerCredit>();
|
||||
while ((credit = reader.read()) != null) {
|
||||
result.add(credit);
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the reader if applicable.
|
||||
*/
|
||||
private void open(ItemReader<?> reader) {
|
||||
if (reader instanceof ItemStream) {
|
||||
((ItemStream) reader).open(new ExecutionContext());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the reader if applicable.
|
||||
*/
|
||||
private void close(ItemReader<?> reader) {
|
||||
if (reader instanceof ItemStream) {
|
||||
((ItemStream) reader).close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,7 +20,9 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -39,12 +41,16 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration()
|
||||
public class PartitionJobFunctionalTests extends AbstractJobTests {
|
||||
public class PartitionJdbcJobFunctionalTests extends AbstractJobTests {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("inputTestReader")
|
||||
private ItemReader<CustomerCredit> inputReader;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("outputTestReader")
|
||||
private ItemReader<CustomerCredit> outputReader;
|
||||
|
||||
/**
|
||||
* Check the resulting credits correspond to inputs increased by fixed
|
||||
* amount.
|
||||
@@ -56,23 +62,21 @@ public class PartitionJobFunctionalTests extends AbstractJobTests {
|
||||
.containsBeanDefinition("outputTestReader"));
|
||||
|
||||
open(inputReader);
|
||||
List<CustomerCredit> inputs = getCredits(inputReader);
|
||||
List<CustomerCredit> inputs = new ArrayList<CustomerCredit>(getCredits(inputReader));
|
||||
close(inputReader);
|
||||
|
||||
JobExecution jobExecution = this.launchJob();
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ItemReader<CustomerCredit> outputReader = (ItemReader<CustomerCredit>) getApplicationContext().getBean(
|
||||
"outputTestReader");
|
||||
open(outputReader);
|
||||
List<CustomerCredit> outputs = getCredits(outputReader);
|
||||
List<CustomerCredit> outputs = new ArrayList<CustomerCredit>(getCredits(outputReader));
|
||||
close(outputReader);
|
||||
|
||||
assertEquals(inputs.size(), outputs.size());
|
||||
int itemCount = inputs.size();
|
||||
assertTrue(itemCount > 0);
|
||||
|
||||
inputs.iterator();
|
||||
for (int i = 0; i < itemCount; i++) {
|
||||
assertEquals(inputs.get(i).getCredit().add(CustomerCreditIncreaseProcessor.FIXED_AMOUNT).intValue(),
|
||||
outputs.get(i).getCredit().intValue());
|
||||
@@ -83,9 +87,9 @@ public class PartitionJobFunctionalTests extends AbstractJobTests {
|
||||
/**
|
||||
* Read all credits using the provided reader.
|
||||
*/
|
||||
private List<CustomerCredit> getCredits(ItemReader<CustomerCredit> reader) throws Exception {
|
||||
private Set<CustomerCredit> getCredits(ItemReader<CustomerCredit> reader) throws Exception {
|
||||
CustomerCredit credit;
|
||||
List<CustomerCredit> result = new ArrayList<CustomerCredit>();
|
||||
Set<CustomerCredit> result = new LinkedHashSet<CustomerCredit>();
|
||||
while ((credit = reader.read()) != null) {
|
||||
result.add(credit);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.springframework.batch.sample.common;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class ColumnRangePartitionerTests {
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
@Autowired
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
private ColumnRangePartitioner partitioner = new ColumnRangePartitioner();
|
||||
|
||||
@Test
|
||||
public void testPartition() {
|
||||
partitioner.setDataSource(dataSource);
|
||||
partitioner.setTable("CUSTOMER");
|
||||
partitioner.setColumn("ID");
|
||||
Map<String, ExecutionContext> partition = partitioner.partition(2);
|
||||
assertEquals(2, partition.size());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.springframework.batch.sample.common;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
|
||||
public class OutputFileListenerTests {
|
||||
|
||||
private OutputFileListener listener = new OutputFileListener();
|
||||
private StepExecution stepExecution = new StepExecution("foo", new JobExecution(0L), 1L);
|
||||
|
||||
@Test
|
||||
public void testCreateOutputNameFromInput() {
|
||||
listener.createOutputNameFromInput(stepExecution);
|
||||
assertEquals("{outputFile=file:./target/output/foo.csv}", stepExecution.getExecutionContext().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetPath() {
|
||||
listener.setPath("spam/");
|
||||
listener.createOutputNameFromInput(stepExecution);
|
||||
assertEquals("{outputFile=spam/foo.csv}", stepExecution.getExecutionContext().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetOutputKeyName() {
|
||||
listener.setPath("");
|
||||
listener.setOutputKeyName("spam");
|
||||
listener.createOutputNameFromInput(stepExecution);
|
||||
assertEquals("{spam=foo.csv}", stepExecution.getExecutionContext().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetInputKeyName() {
|
||||
listener.setPath("");
|
||||
listener.setInputKeyName("spam");
|
||||
stepExecution.getExecutionContext().putString("spam", "bar");
|
||||
listener.createOutputNameFromInput(stepExecution);
|
||||
assertEquals("{outputFile=bar.csv, spam=bar}", stepExecution.getExecutionContext().toString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,6 @@
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
|
||||
|
||||
<import resource="classpath:/simple-job-launcher-context.xml" />
|
||||
<import resource="classpath:/jobs/partitionJob.xml" />
|
||||
<import resource="classpath:/jobs/partitionFileJob.xml" />
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
|
||||
|
||||
<import resource="classpath:/simple-job-launcher-context.xml" />
|
||||
<import resource="classpath:/jobs/partitionJdbcJob.xml" />
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd">
|
||||
|
||||
<import resource="classpath:data-source-context.xml"/>
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user