RESOLVED - issue BATCH-1372: Namespace support for partitioning
Also tidied up (changed) construction pattern for SimpleStepExecutionSplitter, so it doesn't need a step instance.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beansProjectDescription>
|
||||
<version>1</version>
|
||||
<pluginVersion><![CDATA[2.2.7.200910202224-RELEASE]]></pluginVersion>
|
||||
<pluginVersion><![CDATA[2.2.8.200911091054-RELEASE]]></pluginVersion>
|
||||
<configSuffixes>
|
||||
<configSuffix><![CDATA[xml]]></configSuffix>
|
||||
</configSuffixes>
|
||||
@@ -94,6 +94,13 @@
|
||||
<config>src/test/resources/org/springframework/batch/core/scope/StepScopeProxyTargetClassIntegrationTests-context.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/core/configuration/xml/StopAndRestartFailedJobParserTests-context.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/core/launch/support/test-environment-with-registry-and-auto-register.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementIllegalAttributeParserTests-context.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementIllegalTransactionalAttributeParserTests-context.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementSimpleAttributeParserTests-context.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementTransactionalAttributeParserTests-context.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/core/configuration/xml/FlowStepParserTests-context.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/core/configuration/xml/JobParserWrongSchemaInRootTests-context.xml</config>
|
||||
<config>src/test/resources/org/springframework/batch/core/configuration/xml/PartitionStepParserTests-context.xml</config>
|
||||
</configs>
|
||||
<configSets>
|
||||
<configSet>
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.config.TypedStringValue;
|
||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
@@ -58,6 +59,20 @@ public abstract class AbstractStepParser {
|
||||
|
||||
private static final String TASKLET_ELE = "tasklet";
|
||||
|
||||
private static final String PARTITION_ELE = "partition";
|
||||
|
||||
private static final String STEP_ATTR = "step";
|
||||
|
||||
private static final String PARTITIONER_ATTR = "partitioner";
|
||||
|
||||
private static final String HANDLER_ATTR = "handler";
|
||||
|
||||
private static final String HANDLER_ELE = "handler";
|
||||
|
||||
private static final String TASK_EXECUTOR_ATTR = "task-executor";
|
||||
|
||||
private static final String GRID_SIZE_ATTR = "grid-size";
|
||||
|
||||
private static final String FLOW_ELE = "flow";
|
||||
|
||||
private static final String CHUNK_ELE = "chunk";
|
||||
@@ -86,17 +101,23 @@ public abstract class AbstractStepParser {
|
||||
AbstractBeanDefinition bd = builder.getRawBeanDefinition();
|
||||
|
||||
Element taskletElement = DomUtils.getChildElementByTagName(stepElement, TASKLET_ELE);
|
||||
if (taskletElement!=null) {
|
||||
if (taskletElement != null) {
|
||||
boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement);
|
||||
parseTasklet(stepElement, taskletElement, bd, parserContext, stepUnderspecified);
|
||||
}
|
||||
|
||||
Element flowElement = DomUtils.getChildElementByTagName(stepElement, FLOW_ELE);
|
||||
if (flowElement!=null) {
|
||||
if (flowElement != null) {
|
||||
boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement);
|
||||
parseFlow(stepElement, flowElement, bd, parserContext, stepUnderspecified);
|
||||
}
|
||||
|
||||
Element partitionElement = DomUtils.getChildElementByTagName(stepElement, PARTITION_ELE);
|
||||
if (partitionElement != null) {
|
||||
boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement);
|
||||
parsePartition(stepElement, partitionElement, bd, parserContext, stepUnderspecified);
|
||||
}
|
||||
|
||||
String parentRef = stepElement.getAttribute(PARENT_ATTR);
|
||||
if (StringUtils.hasText(parentRef)) {
|
||||
bd.setParentName(parentRef);
|
||||
@@ -125,6 +146,47 @@ public abstract class AbstractStepParser {
|
||||
|
||||
}
|
||||
|
||||
private void parsePartition(Element stepElement, Element partitionElement, AbstractBeanDefinition bd,
|
||||
ParserContext parserContext, boolean stepUnderspecified) {
|
||||
|
||||
bd.setBeanClass(StepParserStepFactoryBean.class);
|
||||
bd.setAttribute("isNamespaceStep", true);
|
||||
String stepRef = partitionElement.getAttribute(STEP_ATTR);
|
||||
String partitionerRef = partitionElement.getAttribute(PARTITIONER_ATTR);
|
||||
String handlerRef = partitionElement.getAttribute(HANDLER_ATTR);
|
||||
|
||||
if (!StringUtils.hasText(stepRef)) {
|
||||
parserContext.getReaderContext().error("You must specify a step", partitionElement);
|
||||
return;
|
||||
}
|
||||
if (!StringUtils.hasText(partitionerRef)) {
|
||||
parserContext.getReaderContext().error("You must specify a partitioner", partitionElement);
|
||||
return;
|
||||
}
|
||||
|
||||
MutablePropertyValues propertyValues = bd.getPropertyValues();
|
||||
propertyValues.addPropertyValue("step", new RuntimeBeanReference(stepRef));
|
||||
propertyValues.addPropertyValue("partitioner", new RuntimeBeanReference(partitionerRef));
|
||||
|
||||
if (!StringUtils.hasText(handlerRef)) {
|
||||
Element handlerElement = DomUtils.getChildElementByTagName(partitionElement, HANDLER_ELE);
|
||||
if (handlerElement != null) {
|
||||
String taskExecutorRef = partitionElement.getAttribute(TASK_EXECUTOR_ATTR);
|
||||
if (StringUtils.hasText(taskExecutorRef)) {
|
||||
propertyValues.addPropertyValue("taskExecutor", new RuntimeBeanReference(taskExecutorRef));
|
||||
}
|
||||
String gridSize = partitionElement.getAttribute(GRID_SIZE_ATTR);
|
||||
if (StringUtils.hasText(gridSize)) {
|
||||
propertyValues.addPropertyValue("gridSize", new TypedStringValue(gridSize));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
propertyValues.addPropertyValue("partitionHandler", new RuntimeBeanReference(handlerRef));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void parseTasklet(Element stepElement, Element taskletElement, AbstractBeanDefinition bd,
|
||||
ParserContext parserContext, boolean stepUnderspecified) {
|
||||
|
||||
@@ -182,7 +244,7 @@ public abstract class AbstractStepParser {
|
||||
}
|
||||
|
||||
bd.getPropertyValues().addPropertyValue("flow", flowDefinition);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void validateTaskletAttributesAndSubelements(Element taskletElement, ParserContext parserContext,
|
||||
@@ -328,7 +390,7 @@ public abstract class AbstractStepParser {
|
||||
if (StringUtils.hasText(allowStartIfComplete)) {
|
||||
propertyValues.addPropertyValue("allowStartIfComplete", allowStartIfComplete);
|
||||
}
|
||||
String taskExecutorBeanId = taskletElement.getAttribute("task-executor");
|
||||
String taskExecutorBeanId = taskletElement.getAttribute(TASK_EXECUTOR_ATTR);
|
||||
if (StringUtils.hasText(taskExecutorBeanId)) {
|
||||
RuntimeBeanReference taskExecutorRef = new RuntimeBeanReference(taskExecutorBeanId);
|
||||
propertyValues.addPropertyValue("taskExecutor", taskExecutorRef);
|
||||
|
||||
@@ -26,7 +26,14 @@ import org.springframework.batch.core.StepExecutionListener;
|
||||
import org.springframework.batch.core.StepListener;
|
||||
import org.springframework.batch.core.job.flow.Flow;
|
||||
import org.springframework.batch.core.job.flow.FlowStep;
|
||||
import org.springframework.batch.core.partition.PartitionHandler;
|
||||
import org.springframework.batch.core.partition.support.PartitionStep;
|
||||
import org.springframework.batch.core.partition.support.Partitioner;
|
||||
import org.springframework.batch.core.partition.support.SimplePartitioner;
|
||||
import org.springframework.batch.core.partition.support.SimpleStepExecutionSplitter;
|
||||
import org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.core.step.AbstractStep;
|
||||
import org.springframework.batch.core.step.item.FaultTolerantStepFactoryBean;
|
||||
import org.springframework.batch.core.step.item.SimpleStepFactoryBean;
|
||||
import org.springframework.batch.core.step.tasklet.Tasklet;
|
||||
@@ -42,6 +49,7 @@ import org.springframework.batch.retry.RetryListener;
|
||||
import org.springframework.batch.retry.policy.MapRetryContextCache;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.core.task.SyncTaskExecutor;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
@@ -81,12 +89,25 @@ class StepParserStepFactoryBean<I, O> implements FactoryBean, BeanNameAware {
|
||||
private Tasklet tasklet;
|
||||
|
||||
private PlatformTransactionManager transactionManager;
|
||||
|
||||
|
||||
//
|
||||
// Floe Elements
|
||||
// Flow Elements
|
||||
//
|
||||
private Flow flow;
|
||||
|
||||
//
|
||||
// Partition Elements
|
||||
//
|
||||
private Partitioner partitioner;
|
||||
|
||||
private static final int DEFAULT_GRID_SIZE = 6;
|
||||
|
||||
private Step step;
|
||||
|
||||
private PartitionHandler partitionHandler;
|
||||
|
||||
private int gridSize = DEFAULT_GRID_SIZE;
|
||||
|
||||
//
|
||||
// Tasklet Elements
|
||||
//
|
||||
@@ -176,12 +197,62 @@ class StepParserStepFactoryBean<I, O> implements FactoryBean, BeanNameAware {
|
||||
configureFlowStep(ts);
|
||||
return ts;
|
||||
}
|
||||
else if (step != null) {
|
||||
PartitionStep ts = new PartitionStep();
|
||||
configurePartitionStep(ts);
|
||||
return ts;
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Step [" + name
|
||||
+ "] has neither a <chunk/> element nor a 'ref' attribute referencing a Tasklet.");
|
||||
}
|
||||
}
|
||||
|
||||
private void configureAbstractStep(AbstractStep ts) {
|
||||
if (name != null) {
|
||||
ts.setName(name);
|
||||
}
|
||||
if (allowStartIfComplete != null) {
|
||||
ts.setAllowStartIfComplete(allowStartIfComplete);
|
||||
}
|
||||
if (jobRepository != null) {
|
||||
ts.setJobRepository(jobRepository);
|
||||
}
|
||||
if (startLimit != null) {
|
||||
ts.setStartLimit(startLimit);
|
||||
}
|
||||
if (listeners != null) {
|
||||
int i = 0;
|
||||
StepExecutionListener[] newListeners = new StepExecutionListener[listeners.length];
|
||||
for (StepListener listener : listeners) {
|
||||
newListeners[i++] = (StepExecutionListener) listener;
|
||||
}
|
||||
ts.setStepExecutionListeners(newListeners);
|
||||
}
|
||||
}
|
||||
|
||||
private void configurePartitionStep(PartitionStep ts) {
|
||||
Assert.state(partitioner != null, "A Partitioner must be provided for a partition step");
|
||||
Assert.state(step != null, "A Step must be provided for a partition step");
|
||||
configureAbstractStep(ts);
|
||||
if (partitionHandler != null) {
|
||||
ts.setPartitionHandler(partitionHandler);
|
||||
}
|
||||
else {
|
||||
TaskExecutorPartitionHandler partitionHandler = new TaskExecutorPartitionHandler();
|
||||
partitionHandler.setStep(step);
|
||||
if (taskExecutor == null) {
|
||||
taskExecutor = new SyncTaskExecutor();
|
||||
}
|
||||
partitionHandler.setGridSize(gridSize);
|
||||
partitionHandler.setTaskExecutor(taskExecutor);
|
||||
ts.setPartitionHandler(partitionHandler);
|
||||
}
|
||||
SimpleStepExecutionSplitter splitter = new SimpleStepExecutionSplitter(jobRepository, step,
|
||||
new SimplePartitioner());
|
||||
ts.setStepExecutionSplitter(splitter);
|
||||
}
|
||||
|
||||
private void configureSimple(SimpleStepFactoryBean<I, O> fb) {
|
||||
if (name != null) {
|
||||
fb.setBeanName(name);
|
||||
@@ -271,32 +342,13 @@ class StepParserStepFactoryBean<I, O> implements FactoryBean, BeanNameAware {
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private void configureTaskletStep(TaskletStep ts) {
|
||||
if (name != null) {
|
||||
ts.setName(name);
|
||||
}
|
||||
if (allowStartIfComplete != null) {
|
||||
ts.setAllowStartIfComplete(allowStartIfComplete);
|
||||
}
|
||||
if (jobRepository != null) {
|
||||
ts.setJobRepository(jobRepository);
|
||||
}
|
||||
if (startLimit != null) {
|
||||
ts.setStartLimit(startLimit);
|
||||
}
|
||||
configureAbstractStep(ts);
|
||||
if (tasklet != null) {
|
||||
ts.setTasklet(tasklet);
|
||||
}
|
||||
if (transactionManager != null) {
|
||||
ts.setTransactionManager(transactionManager);
|
||||
}
|
||||
if (listeners != null) {
|
||||
int i = 0;
|
||||
StepExecutionListener[] newListeners = new StepExecutionListener[listeners.length];
|
||||
for (StepListener listener : listeners) {
|
||||
newListeners[i++] = (StepExecutionListener) listener;
|
||||
}
|
||||
ts.setStepExecutionListeners(newListeners);
|
||||
}
|
||||
if (transactionTimeout != null || propagation != null || isolation != null
|
||||
|| noRollbackExceptionClasses != null) {
|
||||
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
|
||||
@@ -323,42 +375,27 @@ class StepParserStepFactoryBean<I, O> implements FactoryBean, BeanNameAware {
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private void configureFlowStep(FlowStep ts) {
|
||||
if (name != null) {
|
||||
ts.setName(name);
|
||||
}
|
||||
if (allowStartIfComplete != null) {
|
||||
ts.setAllowStartIfComplete(allowStartIfComplete);
|
||||
}
|
||||
if (jobRepository != null) {
|
||||
ts.setJobRepository(jobRepository);
|
||||
}
|
||||
if (startLimit != null) {
|
||||
ts.setStartLimit(startLimit);
|
||||
}
|
||||
configureAbstractStep(ts);
|
||||
if (flow != null) {
|
||||
ts.setFlow(flow);
|
||||
}
|
||||
if (listeners != null) {
|
||||
int i = 0;
|
||||
StepExecutionListener[] newListeners = new StepExecutionListener[listeners.length];
|
||||
for (StepListener listener : listeners) {
|
||||
newListeners[i++] = (StepExecutionListener) listener;
|
||||
}
|
||||
ts.setStepExecutionListeners(newListeners);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateFaultTolerantSettings() {
|
||||
validateDependency("skippable-exception-classes", skippableExceptionClasses, "skip-limit", skipLimit, true);
|
||||
validateDependency("retryable-exception-classes", retryableExceptionClasses, "retry-limit", retryLimit, true);
|
||||
validateAtLeastOneDependency("processor-transactional", processorTransactional, "'retry-limit' or 'skip-limit'", retryLimit, skipLimit);
|
||||
validateAtLeastOneDependency("processor-transactional", processorTransactional,
|
||||
"'retry-limit' or 'skip-limit'", retryLimit, skipLimit);
|
||||
validateDependency("retry-listeners", retryListeners, "retry-limit", retryLimit, false);
|
||||
if (isPresent(processorTransactional) && !processorTransactional && isPresent(readerTransactionalQueue) && readerTransactionalQueue) {
|
||||
throw new IllegalArgumentException("The field 'processor-transactional' cannot be false if 'reader-transactional-queue' is true");
|
||||
if (isPresent(processorTransactional) && !processorTransactional && isPresent(readerTransactionalQueue)
|
||||
&& readerTransactionalQueue) {
|
||||
throw new IllegalArgumentException(
|
||||
"The field 'processor-transactional' cannot be false if 'reader-transactional-queue' is true");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateAtLeastOneDependency(String dependantName, Boolean dependantValue, String name, Object... values) {
|
||||
private void validateAtLeastOneDependency(String dependantName, Boolean dependantValue, String name,
|
||||
Object... values) {
|
||||
boolean oneIsPresent = false;
|
||||
for (Object value : values) {
|
||||
if (isPresent(value)) {
|
||||
@@ -427,7 +464,7 @@ class StepParserStepFactoryBean<I, O> implements FactoryBean, BeanNameAware {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// =========================================================
|
||||
// Flow Attributes
|
||||
// =========================================================
|
||||
@@ -439,6 +476,38 @@ class StepParserStepFactoryBean<I, O> implements FactoryBean, BeanNameAware {
|
||||
this.flow = flow;
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
// Partition Attributes
|
||||
// =========================================================
|
||||
|
||||
/**
|
||||
* @param partitioner the partitioner to set
|
||||
*/
|
||||
public void setPartitioner(Partitioner partitioner) {
|
||||
this.partitioner = partitioner;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param partitionHandler the partitionHandler to set
|
||||
*/
|
||||
public void setPartitionHandler(PartitionHandler partitionHandler) {
|
||||
this.partitionHandler = partitionHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param gridSize the gridSize to set
|
||||
*/
|
||||
public void setGridSize(int gridSize) {
|
||||
this.gridSize = gridSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param step the step to set
|
||||
*/
|
||||
public void setStep(Step step) {
|
||||
this.step = step;
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
// Tasklet Attributes
|
||||
// =========================================================
|
||||
|
||||
@@ -30,6 +30,8 @@ import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.core.partition.StepExecutionSplitter;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Generic implementation of {@link StepExecutionSplitter} that delegates to a
|
||||
@@ -44,20 +46,22 @@ import org.springframework.batch.item.ExecutionContext;
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
public class SimpleStepExecutionSplitter implements StepExecutionSplitter {
|
||||
public class SimpleStepExecutionSplitter implements StepExecutionSplitter, InitializingBean {
|
||||
|
||||
private static final String STEP_NAME_SEPARATOR = ":";
|
||||
|
||||
private final String stepName;
|
||||
private String stepName;
|
||||
|
||||
private final Partitioner partitioner;
|
||||
private Partitioner partitioner;
|
||||
|
||||
private final Step step;
|
||||
private boolean allowStartIfComplete = false;
|
||||
|
||||
private final JobRepository jobRepository;
|
||||
private JobRepository jobRepository;
|
||||
|
||||
public SimpleStepExecutionSplitter(JobRepository jobRepository, Step step) {
|
||||
this(jobRepository, step, new SimplePartitioner());
|
||||
/**
|
||||
* Default constructor for convenience in configuration.
|
||||
*/
|
||||
public SimpleStepExecutionSplitter() {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,17 +69,73 @@ public class SimpleStepExecutionSplitter implements StepExecutionSplitter {
|
||||
* properties.
|
||||
*
|
||||
* @param jobRepository the {@link JobRepository}
|
||||
* @param step the target step (a local version of it)
|
||||
* @param step the target step (a local version of it), used to extract the
|
||||
* name and allowStartIfComplete flags
|
||||
* @param partitioner a {@link Partitioner} to use for generating input
|
||||
* parameters
|
||||
*/
|
||||
public SimpleStepExecutionSplitter(JobRepository jobRepository, Step step, Partitioner partitioner) {
|
||||
this.jobRepository = jobRepository;
|
||||
this.step = step;
|
||||
this.allowStartIfComplete = step.isAllowStartIfComplete();
|
||||
this.partitioner = partitioner;
|
||||
this.stepName = step.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check mandatory properties (step name, job repository and partitioner).
|
||||
*
|
||||
* @see InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.state(jobRepository != null, "A JobRepository is required");
|
||||
Assert.state(stepName != null, "A step name is required");
|
||||
Assert.state(partitioner != null, "A Partitioner is required");
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag to indicate that the partition target step is allowed to start if an
|
||||
* execution is complete. Should be the same as the value that would be
|
||||
* returned by the {@link Step} itself from its own properties. Defaults to
|
||||
* false.
|
||||
*
|
||||
* @see Step#isAllowStartIfComplete()
|
||||
*
|
||||
* @param allowStartIfComplete the value to set
|
||||
*/
|
||||
public void setAllowStartIfComplete(boolean allowStartIfComplete) {
|
||||
this.allowStartIfComplete = allowStartIfComplete;
|
||||
}
|
||||
|
||||
/**
|
||||
* The job repository that will be used to manage the persistence of the
|
||||
* delegate step executions.
|
||||
*
|
||||
* @param jobRepository the JobRepository to set
|
||||
*/
|
||||
public void setJobRepository(JobRepository jobRepository) {
|
||||
this.jobRepository = jobRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link Partitioner} that will be used to generate step execution meta
|
||||
* data for the target step.
|
||||
*
|
||||
* @param partitioner the partitioner to set
|
||||
*/
|
||||
public void setPartitioner(Partitioner partitioner) {
|
||||
this.partitioner = partitioner;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the target step that will be executed across the partitions.
|
||||
* Mandatory with no default.
|
||||
*
|
||||
* @param stepName the step name to set
|
||||
*/
|
||||
public void setStepName(String stepName) {
|
||||
this.stepName = stepName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see StepExecutionSplitter#getStepName()
|
||||
*/
|
||||
@@ -144,11 +204,12 @@ public class SimpleStepExecutionSplitter implements StepExecutionSplitter {
|
||||
stepExecution.setExecutionContext(context);
|
||||
}
|
||||
|
||||
return shouldStart(step, lastStepExecution) || isRestart;
|
||||
return shouldStart(allowStartIfComplete, lastStepExecution) || isRestart;
|
||||
|
||||
}
|
||||
|
||||
private boolean shouldStart(Step step, StepExecution lastStepExecution) throws JobExecutionException {
|
||||
private boolean shouldStart(boolean allowStartIfComplete, StepExecution lastStepExecution)
|
||||
throws JobExecutionException {
|
||||
|
||||
if (lastStepExecution == null) {
|
||||
return true;
|
||||
@@ -162,7 +223,7 @@ public class SimpleStepExecutionSplitter implements StepExecutionSplitter {
|
||||
+ "so it may be dangerous to proceed. " + "Manual intervention is probably necessary.");
|
||||
}
|
||||
|
||||
if (stepStatus == BatchStatus.COMPLETED && step.isAllowStartIfComplete() == false) {
|
||||
if (stepStatus == BatchStatus.COMPLETED && !allowStartIfComplete) {
|
||||
// step is complete, false should be returned, indicating that the
|
||||
// step should not be started
|
||||
return false;
|
||||
|
||||
@@ -107,34 +107,13 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="description" minOccurs="0" />
|
||||
<xsd:choice minOccurs="0" maxOccurs="1">
|
||||
<xsd:element name="tasklet" type="taskletType" />
|
||||
<xsd:element name="flow">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="parent" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation
|
||||
source="java:org.springframework.batch.core.job.flow.Flow"><![CDATA[
|
||||
The flow that will execute in this step.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="parent">
|
||||
<tool:expected-type
|
||||
type="org.springframework.batch.core.job.flow.Flow" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id" type="xsd:ID" use="required" />
|
||||
<xsd:attributeGroup ref="parentAttribute" />
|
||||
<xsd:attributeGroup ref="abstractAttribute" />
|
||||
<xsd:attributeGroup ref="jobRepositoryAttribute" />
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="stepType">
|
||||
<xsd:attribute name="id" type="xsd:ID" use="required" />
|
||||
<xsd:attributeGroup ref="abstractAttribute" />
|
||||
<xsd:attributeGroup ref="jobRepositoryAttribute" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
@@ -295,34 +274,12 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="description" minOccurs="0" />
|
||||
<xsd:choice minOccurs="0" maxOccurs="1">
|
||||
<xsd:element name="tasklet" type="taskletType" />
|
||||
<xsd:element name="flow">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="parent" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation
|
||||
source="java:org.springframework.batch.core.job.flow.Flow"><![CDATA[
|
||||
The flow that will execute in this step.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="parent">
|
||||
<tool:expected-type
|
||||
type="org.springframework.batch.core.job.flow.Flow" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
<xsd:group ref="transitions" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id" type="xsd:ID" use="required" />
|
||||
<xsd:attributeGroup ref="parentAttribute" />
|
||||
<xsd:attributeGroup ref="nextAttribute" />
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="stepType">
|
||||
<xsd:attribute name="id" type="xsd:ID" use="required" />
|
||||
<xsd:attributeGroup ref="nextAttribute" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="split">
|
||||
@@ -343,7 +300,8 @@
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:group ref="flowGroup" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:attribute name="parent" type="xsd:string" use="optional">
|
||||
<xsd:attribute name="parent" type="xsd:string"
|
||||
use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation
|
||||
source="java:org.springframework.batch.core.job.flow.Flow"><![CDATA[
|
||||
@@ -439,6 +397,109 @@
|
||||
</xsd:choice>
|
||||
</xsd:group>
|
||||
|
||||
<xsd:complexType name="stepType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="description" minOccurs="0" />
|
||||
<xsd:choice minOccurs="0" maxOccurs="1">
|
||||
<xsd:element name="tasklet" type="taskletType" />
|
||||
<xsd:element name="partition" type="partitionType" />
|
||||
<xsd:element name="flow">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="parent" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation
|
||||
source="java:org.springframework.batch.core.job.flow.Flow"><![CDATA[
|
||||
The flow that will execute in this step.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="parent">
|
||||
<tool:expected-type
|
||||
type="org.springframework.batch.core.job.flow.Flow" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
<xsd:group ref="transitions" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
<xsd:attributeGroup ref="parentAttribute" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="partitionType">
|
||||
<xsd:all>
|
||||
<xsd:element name="handler" minOccurs="0" maxOccurs="1">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Inline specification of a simple TaskExecutorPartitionHandler]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="task-executor">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Reference to a TaskExecutor]]>
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type
|
||||
type="org.springframework.core.task.TaskExecutor" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="grid-size">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Grid size for the handler. Defaults to 6.]]>
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="direct"/>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:all>
|
||||
<xsd:attribute name="handler">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Reference to a PartitionHandler]]>
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.core.partition.PartitionHandler" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="partitioner">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Reference to a Partitioner]]>
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.core.partition.support.Partitioner" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="step">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Reference to a Step]]>
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.core.Step" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="taskletType">
|
||||
<xsd:all>
|
||||
<xsd:element name="chunk" type="chunkTaskletType"
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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.core.configuration.xml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
|
||||
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;
|
||||
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class PartitionStepParserTests {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("job1")
|
||||
private Job job1;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("job2")
|
||||
private Job job2;
|
||||
|
||||
@Autowired
|
||||
private JobRepository jobRepository;
|
||||
|
||||
@Autowired
|
||||
private MapJobRepositoryFactoryBean mapJobRepositoryFactoryBean;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mapJobRepositoryFactoryBean.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultHandlerStep() throws Exception {
|
||||
assertNotNull(job1);
|
||||
JobExecution jobExecution = jobRepository.createJobExecution(job1.getName(), new JobParameters());
|
||||
job1.execute(jobExecution);
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
List<String> stepNames = getStepNames(jobExecution);
|
||||
assertEquals(7, stepNames.size());
|
||||
assertEquals("[s1, step1:partition0, step1:partition1, step1:partition2, step1:partition3, step1:partition4, step1:partition5]", stepNames.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandlerRefStep() throws Exception {
|
||||
assertNotNull(job2);
|
||||
JobExecution jobExecution = jobRepository.createJobExecution(job2.getName(), new JobParameters());
|
||||
job2.execute(jobExecution);
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
List<String> stepNames = getStepNames(jobExecution);
|
||||
assertEquals(3, stepNames.size());
|
||||
assertEquals("[s2, s3, step1:partition0]", stepNames.toString());
|
||||
}
|
||||
|
||||
private List<String> getStepNames(JobExecution jobExecution) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
for (StepExecution stepExecution : jobExecution.getStepExecutions()) {
|
||||
list.add(stepExecution.getStepName());
|
||||
}
|
||||
Collections.sort(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -56,7 +56,7 @@ public class PartitionStepTests {
|
||||
|
||||
@Test
|
||||
public void testVanillaStepExecution() throws Exception {
|
||||
step.setStepExecutionSplitter(new SimpleStepExecutionSplitter(jobRepository, remote));
|
||||
step.setStepExecutionSplitter(new SimpleStepExecutionSplitter(jobRepository, remote, new SimplePartitioner()));
|
||||
step.setPartitionHandler(new PartitionHandler() {
|
||||
public Collection<StepExecution> handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution)
|
||||
throws Exception {
|
||||
@@ -80,7 +80,7 @@ public class PartitionStepTests {
|
||||
|
||||
@Test
|
||||
public void testFailedStepExecution() throws Exception {
|
||||
step.setStepExecutionSplitter(new SimpleStepExecutionSplitter(jobRepository, remote));
|
||||
step.setStepExecutionSplitter(new SimpleStepExecutionSplitter(jobRepository, remote, new SimplePartitioner()));
|
||||
step.setPartitionHandler(new PartitionHandler() {
|
||||
public Collection<StepExecution> handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution)
|
||||
throws Exception {
|
||||
@@ -104,7 +104,7 @@ public class PartitionStepTests {
|
||||
|
||||
@Test
|
||||
public void testStoppedStepExecution() throws Exception {
|
||||
step.setStepExecutionSplitter(new SimpleStepExecutionSplitter(jobRepository, remote));
|
||||
step.setStepExecutionSplitter(new SimpleStepExecutionSplitter(jobRepository, remote, new SimplePartitioner()));
|
||||
step.setPartitionHandler(new PartitionHandler() {
|
||||
public Collection<StepExecution> handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution)
|
||||
throws Exception {
|
||||
@@ -135,7 +135,7 @@ public class PartitionStepTests {
|
||||
result.getExecutionContext().put("aggregated", true);
|
||||
}
|
||||
});
|
||||
step.setStepExecutionSplitter(new SimpleStepExecutionSplitter(jobRepository, remote));
|
||||
step.setStepExecutionSplitter(new SimpleStepExecutionSplitter(jobRepository, remote, new SimplePartitioner()));
|
||||
step.setPartitionHandler(new PartitionHandler() {
|
||||
public Collection<StepExecution> handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution)
|
||||
throws Exception {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.springframework.batch.core.partition.support;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
@@ -11,8 +12,6 @@ import org.junit.Test;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.core.partition.support.Partitioner;
|
||||
import org.springframework.batch.core.partition.support.SimpleStepExecutionSplitter;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
|
||||
import org.springframework.batch.core.step.tasklet.TaskletStep;
|
||||
@@ -35,10 +34,11 @@ public class SimpleStepExecutionSplitterTests {
|
||||
|
||||
@Test
|
||||
public void testSimpleStepExecutionProviderJobRepositoryStep() throws Exception {
|
||||
SimpleStepExecutionSplitter splitter = new SimpleStepExecutionSplitter(jobRepository, step);
|
||||
SimpleStepExecutionSplitter splitter = new SimpleStepExecutionSplitter(jobRepository, step,
|
||||
new SimplePartitioner());
|
||||
Set<StepExecution> execs = splitter.split(stepExecution, 2);
|
||||
assertEquals(2, execs.size());
|
||||
|
||||
|
||||
for (StepExecution execution : execs) {
|
||||
assertNotNull("step execution partition is saved", execution.getId());
|
||||
}
|
||||
@@ -57,14 +57,16 @@ public class SimpleStepExecutionSplitterTests {
|
||||
|
||||
@Test
|
||||
public void testRememberGridSize() throws Exception {
|
||||
SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, step);
|
||||
SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, step,
|
||||
new SimplePartitioner());
|
||||
assertEquals(2, provider.split(stepExecution, 2).size());
|
||||
assertEquals(2, provider.split(stepExecution, 3).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetStepName() {
|
||||
SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, step);
|
||||
SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, step,
|
||||
new SimplePartitioner());
|
||||
assertEquals("step", provider.getStepName());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/batch"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.1.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
|
||||
|
||||
<beans:import resource="common-context.xml" />
|
||||
|
||||
<job id="job1">
|
||||
<step id="s1">
|
||||
<partition step="step1" partitioner="partitioner">
|
||||
<handler task-executor="taskExecutor" grid-size="2" />
|
||||
</partition>
|
||||
</step>
|
||||
</job>
|
||||
|
||||
<job id="job2">
|
||||
<step id="s2" next="s3">
|
||||
<partition step="step1" handler="handler" partitioner="partitioner"/>
|
||||
</step>
|
||||
<step id="s3" parent="step2"/>
|
||||
</job>
|
||||
|
||||
<bean id="handler"
|
||||
class="org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler"
|
||||
xmlns="http://www.springframework.org/schema/beans">
|
||||
<property name="step" ref="step1"/>
|
||||
</bean>
|
||||
|
||||
<beans:bean id="taskExecutor"
|
||||
class="org.springframework.core.task.SimpleAsyncTaskExecutor" />
|
||||
|
||||
<beans:bean id="partitioner"
|
||||
class="org.springframework.batch.core.partition.support.SimplePartitioner" />
|
||||
|
||||
</beans:beans>
|
||||
@@ -1,18 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:p="http://www.springframework.org/schema/p" 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.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
|
||||
|
||||
<import resource="classpath:/org/springframework/batch/core/repository/dao/data-source-context.xml" />
|
||||
<import
|
||||
resource="classpath:/org/springframework/batch/core/repository/dao/data-source-context.xml" />
|
||||
|
||||
<bean id="job1" parent="simpleJob">
|
||||
<property name="steps">
|
||||
<bean name="step1:master" class="org.springframework.batch.core.partition.support.PartitionStep">
|
||||
<bean name="step1:master"
|
||||
class="org.springframework.batch.core.partition.support.PartitionStep">
|
||||
<property name="partitionHandler">
|
||||
<bean class="org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler">
|
||||
<bean
|
||||
class="org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler">
|
||||
<property name="taskExecutor">
|
||||
<bean class="org.springframework.core.task.SimpleAsyncTaskExecutor" />
|
||||
</property>
|
||||
@@ -21,9 +24,14 @@
|
||||
</bean>
|
||||
</property>
|
||||
<property name="stepExecutionSplitter">
|
||||
<bean class="org.springframework.batch.core.partition.support.SimpleStepExecutionSplitter">
|
||||
<constructor-arg ref="jobRepository" />
|
||||
<constructor-arg ref="step1" />
|
||||
<bean
|
||||
class="org.springframework.batch.core.partition.support.SimpleStepExecutionSplitter">
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
<property name="stepName" value="step1" />
|
||||
<property name="partitioner">
|
||||
<bean
|
||||
class="org.springframework.batch.core.partition.support.SimplePartitioner" />
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
@@ -32,7 +40,8 @@
|
||||
</bean>
|
||||
<bean id="step1" parent="simpleStep">
|
||||
<property name="itemReader">
|
||||
<bean class="org.springframework.batch.core.partition.ExampleItemReader" scope="step">
|
||||
<bean class="org.springframework.batch.core.partition.ExampleItemReader"
|
||||
scope="step">
|
||||
<!--
|
||||
<property name="resource"
|
||||
value="#{stepAttributes[jobParameters['resource']]}"/>
|
||||
@@ -44,23 +53,29 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="simpleJob" class="org.springframework.batch.core.job.SimpleJob" abstract="true">
|
||||
<bean id="simpleJob" class="org.springframework.batch.core.job.SimpleJob"
|
||||
abstract="true">
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
<property name="restartable" value="true" />
|
||||
</bean>
|
||||
|
||||
<bean id="simpleStep" class="org.springframework.batch.core.step.item.SimpleStepFactoryBean" abstract="true">
|
||||
<bean id="simpleStep"
|
||||
class="org.springframework.batch.core.step.item.SimpleStepFactoryBean"
|
||||
abstract="true">
|
||||
<property name="transactionManager" ref="transactionManager" />
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
<property name="startLimit" value="100" />
|
||||
<property name="commitInterval" value="1" />
|
||||
</bean>
|
||||
|
||||
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
|
||||
<bean id="jobLauncher"
|
||||
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
</bean>
|
||||
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"
|
||||
p:databaseType="hsql" p:dataSource-ref="dataSource" p:transactionManager-ref="transactionManager" />
|
||||
<bean id="jobRepository"
|
||||
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"
|
||||
p:databaseType="hsql" p:dataSource-ref="dataSource"
|
||||
p:transactionManager-ref="transactionManager" />
|
||||
|
||||
<bean class="org.springframework.batch.core.scope.StepScope" />
|
||||
|
||||
|
||||
@@ -68,8 +68,11 @@
|
||||
<property name="stepExecutionSplitter">
|
||||
<bean
|
||||
class="org.springframework.batch.core.partition.support.SimpleStepExecutionSplitter">
|
||||
<constructor-arg ref="jobRepository" />
|
||||
<constructor-arg ref="step1" />
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
<property name="stepName" ref="step1" />
|
||||
<property name="partitioner">
|
||||
<bean class="org.springframework.batch.core.partition.support.SimplePartitioner"/>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?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"
|
||||
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.1.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
|
||||
@@ -9,88 +8,108 @@
|
||||
<job id="partitionJob" 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">
|
||||
|
||||
<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.core.partition.support.MultiResourcePartitioner">
|
||||
<property name="resources" value="classpath:data/iosample/input/delimited*.csv" />
|
||||
<bean
|
||||
class="org.springframework.batch.core.partition.support.SimpleStepExecutionSplitter">
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
<property name="stepName" value="step1" />
|
||||
<property name="partitioner">
|
||||
<bean
|
||||
class="org.springframework.batch.core.partition.support.MultiResourcePartitioner">
|
||||
<property name="resources"
|
||||
value="classpath:data/iosample/input/delimited*.csv" />
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="partitionHandler">
|
||||
<bean class="org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler">
|
||||
<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"/>
|
||||
<property name="gridSize" value="2" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<step id="step1" xmlns="http://www.springframework.org/schema/batch" job-repository="jobRepository">
|
||||
<step id="step1" xmlns="http://www.springframework.org/schema/batch">
|
||||
<tasklet transaction-manager="transactionManager">
|
||||
<chunk writer="itemWriter" reader="itemReader" processor="itemProcessor" commit-interval="5" />
|
||||
<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/file/"/>
|
||||
<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">
|
||||
|
||||
<bean id="itemReader" scope="step" autowire-candidate="false"
|
||||
parent="itemReaderParent">
|
||||
<property name="resource" value="#{stepExecutionContext[fileName]}" />
|
||||
</bean>
|
||||
|
||||
<bean id="inputTestReader" class="org.springframework.batch.item.file.MultiResourceItemReader">
|
||||
<bean id="inputTestReader"
|
||||
class="org.springframework.batch.item.file.MultiResourceItemReader">
|
||||
<property name="resources" value="classpath:data/iosample/input/delimited*.csv" />
|
||||
<property name="delegate" ref="testItemReader" />
|
||||
</bean>
|
||||
|
||||
<bean id="outputTestReader" class="org.springframework.batch.item.file.MultiResourceItemReader" scope="prototype">
|
||||
<bean id="outputTestReader"
|
||||
class="org.springframework.batch.item.file.MultiResourceItemReader"
|
||||
scope="prototype">
|
||||
<property name="resources" value="file:target/output/file/delimited*.csv" />
|
||||
<property name="delegate" ref="testItemReader" />
|
||||
</bean>
|
||||
|
||||
<bean id="testItemReader" parent="itemReaderParent"/>
|
||||
<bean id="testItemReader" parent="itemReaderParent" />
|
||||
|
||||
<bean id="itemReaderParent" class="org.springframework.batch.item.file.FlatFileItemReader" abstract="true">
|
||||
<bean id="itemReaderParent" class="org.springframework.batch.item.file.FlatFileItemReader"
|
||||
abstract="true">
|
||||
<property name="lineMapper">
|
||||
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
|
||||
<property name="lineTokenizer">
|
||||
<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
|
||||
<bean
|
||||
class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
|
||||
<property name="delimiter" value="," />
|
||||
<property name="names" value="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
|
||||
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="itemProcessor" class="org.springframework.batch.sample.domain.trade.internal.CustomerCreditIncreaseProcessor" />
|
||||
<bean id="itemProcessor"
|
||||
class="org.springframework.batch.sample.domain.trade.internal.CustomerCreditIncreaseProcessor" />
|
||||
|
||||
<bean id="itemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter" scope="step">
|
||||
<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">
|
||||
<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">
|
||||
<bean
|
||||
class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
|
||||
<property name="names" value="name,credit" />
|
||||
</bean>
|
||||
</property>
|
||||
|
||||
@@ -15,16 +15,16 @@
|
||||
<property name="stepExecutionSplitter">
|
||||
<bean
|
||||
class="org.springframework.batch.core.partition.support.SimpleStepExecutionSplitter">
|
||||
<constructor-arg ref="jobRepository" />
|
||||
<constructor-arg ref="step1" />
|
||||
<constructor-arg>
|
||||
<property name="jobRepository" ref="jobRepository" />
|
||||
<property name="stepName" value="step1" />
|
||||
<property name="partitioner">
|
||||
<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>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="partitionHandler">
|
||||
@@ -34,13 +34,13 @@
|
||||
<bean class="org.springframework.core.task.SyncTaskExecutor" />
|
||||
</property>
|
||||
<property name="step" ref="step1" />
|
||||
<property name="gridSize" value="2"/>
|
||||
<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">
|
||||
<tasklet transaction-manager="transactionManager">
|
||||
<chunk writer="itemWriter" reader="itemReader" processor="itemProcessor"
|
||||
commit-interval="5" />
|
||||
<listeners>
|
||||
@@ -52,7 +52,7 @@
|
||||
<bean id="fileNameListener"
|
||||
class="org.springframework.batch.sample.common.OutputFileListener"
|
||||
scope="step">
|
||||
<property name="path" value="file:./target/output/jdbc/"/>
|
||||
<property name="path" value="file:./target/output/jdbc/" />
|
||||
</bean>
|
||||
|
||||
<bean id="itemReader" scope="step" autowire-candidate="false"
|
||||
@@ -89,14 +89,17 @@
|
||||
<property name="lineMapper">
|
||||
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
|
||||
<property name="lineTokenizer">
|
||||
<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
|
||||
<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
|
||||
class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
|
||||
<property name="targetType"
|
||||
value="org.springframework.batch.sample.domain.trade.CustomerCredit" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
Reference in New Issue
Block a user