diff --git a/spring-batch-core/.springBeans b/spring-batch-core/.springBeans index 406e7e463..ae68998df 100644 --- a/spring-batch-core/.springBeans +++ b/spring-batch-core/.springBeans @@ -1,7 +1,7 @@ 1 - + @@ -94,6 +94,13 @@ src/test/resources/org/springframework/batch/core/scope/StepScopeProxyTargetClassIntegrationTests-context.xml src/test/resources/org/springframework/batch/core/configuration/xml/StopAndRestartFailedJobParserTests-context.xml src/test/resources/org/springframework/batch/core/launch/support/test-environment-with-registry-and-auto-register.xml + src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementIllegalAttributeParserTests-context.xml + src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementIllegalTransactionalAttributeParserTests-context.xml + src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementSimpleAttributeParserTests-context.xml + src/test/resources/org/springframework/batch/core/configuration/xml/ChunkElementTransactionalAttributeParserTests-context.xml + src/test/resources/org/springframework/batch/core/configuration/xml/FlowStepParserTests-context.xml + src/test/resources/org/springframework/batch/core/configuration/xml/JobParserWrongSchemaInRootTests-context.xml + src/test/resources/org/springframework/batch/core/configuration/xml/PartitionStepParserTests-context.xml diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java index 90776b247..41f8d8334 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java @@ -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); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java index 84e5d7dd2..b0529abc9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java @@ -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 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 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 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 fb) { if (name != null) { fb.setBeanName(name); @@ -271,32 +342,13 @@ class StepParserStepFactoryBean 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 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 implements FactoryBean, BeanNameAware { this.name = name; } } - + // ========================================================= // Flow Attributes // ========================================================= @@ -439,6 +476,38 @@ class StepParserStepFactoryBean 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 // ========================================================= diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/SimpleStepExecutionSplitter.java b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/SimpleStepExecutionSplitter.java index dcdffc7f9..269fcdf46 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/SimpleStepExecutionSplitter.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/SimpleStepExecutionSplitter.java @@ -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; diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.1.xsd b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.1.xsd index 0fe5cfa03..5de23ebae 100644 --- a/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.1.xsd +++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.1.xsd @@ -107,34 +107,13 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + @@ -295,34 +274,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + @@ -343,7 +300,8 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 stepNames = getStepNames(jobExecution); + assertEquals(3, stepNames.size()); + assertEquals("[s2, s3, step1:partition0]", stepNames.toString()); + } + + private List getStepNames(JobExecution jobExecution) { + List list = new ArrayList(); + for (StepExecution stepExecution : jobExecution.getStepExecutions()) { + list.add(stepExecution.getStepName()); + } + Collections.sort(list); + return list; + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/PartitionStepTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/PartitionStepTests.java index f888eb0ba..e9e8477c3 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/PartitionStepTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/PartitionStepTests.java @@ -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 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 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 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 handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution) throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/SimpleStepExecutionSplitterTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/SimpleStepExecutionSplitterTests.java index e54b8b300..920cfb25e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/SimpleStepExecutionSplitterTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/SimpleStepExecutionSplitterTests.java @@ -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 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()); } diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/PartitionStepParserTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/PartitionStepParserTests-context.xml new file mode 100644 index 000000000..383dcc937 --- /dev/null +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/PartitionStepParserTests-context.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/partition/launch-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/partition/launch-context.xml index 1b6492452..ca6e10659 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/partition/launch-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/partition/launch-context.xml @@ -1,18 +1,21 @@ - - + - + - + @@ -21,9 +24,14 @@ - - - + + + + + + @@ -32,7 +40,8 @@ - +