diff --git a/spring-batch-core/.settings/com.springsource.sts.config.flow.prefs b/spring-batch-core/.settings/com.springsource.sts.config.flow.prefs
index b9cbc174d..7d8c1c6cd 100644
--- a/spring-batch-core/.settings/com.springsource.sts.config.flow.prefs
+++ b/spring-batch-core/.settings/com.springsource.sts.config.flow.prefs
@@ -1,6 +1,7 @@
-#Tue Feb 01 21:15:00 GMT 2011
+#Tue Mar 15 12:05:10 GMT 2011
//com.springsource.sts.config.flow.coordinates\:http\://www.springframework.org/schema/batch\:/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobExecutionListenerMethodAttributeParserTests-context.xml=\n\n\n\n\n\n
//com.springsource.sts.config.flow.coordinates\:http\://www.springframework.org/schema/batch\:/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryDefaultParserTests-context.xml=\n
+//com.springsource.sts.config.flow.coordinates\:http\://www.springframework.org/schema/batch\:/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/PartitionStepParserTests-context.xml=\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
//com.springsource.sts.config.flow.coordinates\:http\://www.springframework.org/schema/batch\:/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepListenerInStepParserTests-context.xml=\n\n\n\n\n\n
//com.springsource.sts.config.flow.coordinates\:http\://www.springframework.org/schema/batch\:/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepListenerMethodAttributeParserTests-context.xml=\n\n\n\n\n\n
//com.springsource.sts.config.flow.coordinates\:http\://www.springframework.org/schema/batch\:/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StepListenerParserTests-context.xml=\n\n\n\n\n\n
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 b38ecc29d..8cfc4123a 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
@@ -157,24 +157,11 @@ public abstract class AbstractStepParser {
return;
}
- Element inlineStepElement = DomUtils.getChildElementByTagName(partitionElement, STEP_ELE);
- if (inlineStepElement == null && !StringUtils.hasText(stepRef)) {
- parserContext.getReaderContext().error("You must specify a step", partitionElement);
- return;
- }
-
-
MutablePropertyValues propertyValues = bd.getPropertyValues();
- if (StringUtils.hasText(stepRef)) {
- propertyValues.addPropertyValue("step", new RuntimeBeanReference(stepRef));
- } else if( inlineStepElement!=null) {
- AbstractBeanDefinition stepDefinition = parseStep(inlineStepElement, parserContext, jobFactoryRef);
- propertyValues.addPropertyValue("step", stepDefinition );
- }
-
propertyValues.addPropertyValue("partitioner", new RuntimeBeanReference(partitionerRef));
+ boolean customHandler = false;
if (!StringUtils.hasText(handlerRef)) {
Element handlerElement = DomUtils.getChildElementByTagName(partitionElement, HANDLER_ELE);
if (handlerElement != null) {
@@ -188,7 +175,24 @@ public abstract class AbstractStepParser {
}
}
} else {
- propertyValues.addPropertyValue("partitionHandler", new RuntimeBeanReference(handlerRef));
+ customHandler = true;
+ BeanDefinition partitionHandler = BeanDefinitionBuilder.genericBeanDefinition().getRawBeanDefinition();
+ partitionHandler.setParentName(handlerRef);
+ propertyValues.addPropertyValue("partitionHandler", partitionHandler);
+ }
+
+ Element inlineStepElement = DomUtils.getChildElementByTagName(partitionElement, STEP_ELE);
+ if (inlineStepElement == null && !StringUtils.hasText(stepRef) && !customHandler) {
+ parserContext.getReaderContext().error("You must specify a step", partitionElement);
+ return;
+ }
+
+ if (StringUtils.hasText(stepRef)) {
+ propertyValues.addPropertyValue("step", new RuntimeBeanReference(stepRef));
+ } else if( inlineStepElement!=null) {
+ AbstractBeanDefinition stepDefinition = parseStep(inlineStepElement, parserContext, jobFactoryRef);
+ stepDefinition.getPropertyValues().addPropertyValue("name", stepElement.getAttribute(ID_ATTR));
+ propertyValues.addPropertyValue("step", stepDefinition );
}
}
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 33909794e..9544aac34 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
@@ -22,6 +22,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.batch.classify.BinaryExceptionClassifier;
import org.springframework.batch.core.ChunkListener;
import org.springframework.batch.core.Job;
@@ -59,6 +61,7 @@ import org.springframework.batch.retry.RetryPolicy;
import org.springframework.batch.retry.backoff.BackOffPolicy;
import org.springframework.batch.retry.policy.MapRetryContextCache;
import org.springframework.batch.retry.policy.RetryContextCache;
+import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.core.task.SyncTaskExecutor;
@@ -85,6 +88,8 @@ import org.springframework.util.Assert;
*/
class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
+ private static final Log logger = LogFactory.getLog(StepParserStepFactoryBean.class);
+
//
// Step Attributes
//
@@ -234,15 +239,11 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
configureJobStep(ts);
return ts;
}
- else if (step != null) {
+ else {
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.");
- }
}
public boolean requiresTransactionManager() {
@@ -277,7 +278,6 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
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);
PartitionHandler handler;
@@ -300,17 +300,39 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
// BATCH-1659
if (handler instanceof TaskExecutorPartitionHandler) {
+ // Only for a local partition handler is the step required
+ Assert.state(step != null,
+ "A Step must be provided for a partition step with a TaskExecutorPartitionHandler");
try {
TaskExecutorPartitionHandler taskExecutorPartitionHandler = (TaskExecutorPartitionHandler) handler;
taskExecutorPartitionHandler.setStep(step);
taskExecutorPartitionHandler.afterPropertiesSet();
}
catch (Exception e) {
- throw new RuntimeException(e);
+ throw new BeanCreationException("Could not configure TaskExecutorPartitionHandler", e);
}
}
+ else {
+ // Only for a local partition handler is the step required
+ Assert.state(step == null,
+ "A Step must not be provided for a custom partition handler (unless it extends TaskExecutorPartitionHandler). "
+ + "It should be configured with its own step reference.");
+ }
- SimpleStepExecutionSplitter splitter = new SimpleStepExecutionSplitter(jobRepository, step, partitioner);
+ boolean allowStartIfComplete = this.allowStartIfComplete !=null ? this.allowStartIfComplete : false;
+ String name = this.name;
+ if (step != null) {
+ try {
+ allowStartIfComplete = step.isAllowStartIfComplete();
+ name = step.getName();
+ }
+ catch (Exception e) {
+ logger.info("Ignored exception from step asking for name and allowStartIfComplete flag. "
+ + "Using default from enclosing PartitionStep ("+name+","+allowStartIfComplete+").");
+ }
+ }
+ SimpleStepExecutionSplitter splitter = new SimpleStepExecutionSplitter(jobRepository, allowStartIfComplete,
+ name, partitioner);
ts.setStepExecutionSplitter(splitter);
}
@@ -578,6 +600,13 @@ class StepParserStepFactoryBean implements FactoryBean, BeanNameAware {
}
}
+ /**
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
// =========================================================
// Flow 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 6f9cf20d7..2cc8e302b 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
@@ -66,6 +66,23 @@ public class SimpleStepExecutionSplitter implements StepExecutionSplitter, Initi
public SimpleStepExecutionSplitter() {
}
+ /**
+ * Construct a {@link SimpleStepExecutionSplitter} from its mandatory
+ * properties.
+ *
+ * @param jobRepository the {@link JobRepository}
+ * @param allowStartIfComplete flag specifying preferences on restart
+ * @param stepName the target step name
+ * @param partitioner a {@link Partitioner} to use for generating input
+ * parameters
+ */
+ public SimpleStepExecutionSplitter(JobRepository jobRepository, boolean allowStartIfComplete, String stepName, Partitioner partitioner) {
+ this.jobRepository = jobRepository;
+ this.allowStartIfComplete = allowStartIfComplete;
+ this.partitioner = partitioner;
+ this.stepName = stepName;
+ }
+
/**
* Construct a {@link SimpleStepExecutionSplitter} from its mandatory
* properties.
@@ -75,7 +92,10 @@ public class SimpleStepExecutionSplitter implements StepExecutionSplitter, Initi
* name and allowStartIfComplete flags
* @param partitioner a {@link Partitioner} to use for generating input
* parameters
+ *
+ * @deprecated use {@link #SimpleStepExecutionSplitter(JobRepository, boolean, String, Partitioner)} instead
*/
+ @Deprecated
public SimpleStepExecutionSplitter(JobRepository jobRepository, Step step, Partitioner partitioner) {
this.jobRepository = jobRepository;
this.allowStartIfComplete = step.isAllowStartIfComplete();
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandler.java b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandler.java
index a82308a37..3eacc1b71 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandler.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandler.java
@@ -34,12 +34,13 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.task.SyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.core.task.TaskRejectedException;
+import org.springframework.util.Assert;
/**
* A {@link PartitionHandler} that uses a {@link TaskExecutor} to execute the
- * partitioned {@link Step} locally in multiple threads. This can be an effective
- * approach for scaling batch steps that are IO intensive, like directory and
- * filesystem scanning and copying.
+ * partitioned {@link Step} locally in multiple threads. This can be an
+ * effective approach for scaling batch steps that are IO intensive, like
+ * directory and filesystem scanning and copying.
*
* @author Dave Syer
* @since 2.0
@@ -53,15 +54,14 @@ public class TaskExecutorPartitionHandler implements PartitionHandler, Initializ
private Step step;
public void afterPropertiesSet() throws Exception {
-// Assert.notNull(step, "A Step must be provided.");
}
/**
* Passed to the {@link StepExecutionSplitter} in the
* {@link #handle(StepExecutionSplitter, StepExecution)} method, instructing
* it how many {@link StepExecution} instances are required, ideally. The
- * {@link StepExecutionSplitter} is allowed to ignore the grid size in the case of
- * a restart, since the input data partitions must be preserved.
+ * {@link StepExecutionSplitter} is allowed to ignore the grid size in the
+ * case of a restart, since the input data partitions must be preserved.
*
* @param gridSize the number of step executions that will be created
*/
@@ -96,6 +96,8 @@ public class TaskExecutorPartitionHandler implements PartitionHandler, Initializ
public Collection handle(StepExecutionSplitter stepExecutionSplitter,
StepExecution masterStepExecution) throws Exception {
+ Assert.notNull(step, "A Step must be provided.");
+
Set> tasks = new HashSet>(gridSize);
Collection result = new ArrayList();
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepParserTests.java
index 7470cf176..4fd8e24f3 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepParserTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepParserTests.java
@@ -20,6 +20,8 @@ import static org.junit.Assert.assertNotNull;
import java.lang.reflect.Field;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -27,6 +29,8 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.batch.core.*;
+import org.springframework.batch.core.partition.PartitionHandler;
+import org.springframework.batch.core.partition.StepExecutionSplitter;
import org.springframework.batch.core.partition.support.PartitionStep;
import org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler;
import org.springframework.batch.core.repository.JobRepository;
@@ -41,7 +45,6 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.ReflectionUtils;
-
/**
* @author Dave Syer
* @author Josh Long
@@ -50,102 +53,185 @@ import org.springframework.util.ReflectionUtils;
@RunWith(SpringJUnit4ClassRunner.class)
public class PartitionStepParserTests implements ApplicationContextAware {
- @Autowired
- @Qualifier("job1")
- private Job job1;
+ @Autowired
+ @Qualifier("job1")
+ private Job job1;
- @Autowired
- @Qualifier("job2")
- private Job job2;
+ @Autowired
+ @Qualifier("job2")
+ private Job job2;
- @Autowired
- @Qualifier("job3")
- private Job job3;
+ @Autowired
+ @Qualifier("job3")
+ private Job job3;
- @Autowired
- private JobRepository jobRepository;
+ @Autowired
+ @Qualifier("job4")
+ private Job job4;
- @Autowired
- private MapJobRepositoryFactoryBean mapJobRepositoryFactoryBean;
+ @Autowired
+ @Qualifier("job5")
+ private Job job5;
- private ApplicationContext applicationContext;
+ @Autowired
+ @Qualifier("nameStoringTasklet")
+ private NameStoringTasklet nameStoringTasklet;
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- this.applicationContext = applicationContext;
- }
+ @Autowired
+ private JobRepository jobRepository;
- @Before
- public void setUp() {
- mapJobRepositoryFactoryBean.clear();
- }
+ @Autowired
+ private MapJobRepositoryFactoryBean mapJobRepositoryFactoryBean;
- @SuppressWarnings("unchecked")
- private T accessPrivateField(Object o, String fieldName) {
- Field field = ReflectionUtils.findField(o.getClass(), fieldName);
- boolean previouslyAccessibleValue = field.isAccessible();
- field.setAccessible(true);
- T val = (T) ReflectionUtils.getField(field, o);
- field.setAccessible(previouslyAccessibleValue);
- return val;
- }
+ private ApplicationContext applicationContext;
- /**
- * BATCH-1509 we now support the ability define steps inline for partitioned steps.
- * this demonstates that the execution proceeds as expected and that the partitionhandler has a reference to the inline step definition
- */
- @Test
- public void testNestedPartitionStepStepReference() throws Throwable {
- assertNotNull("the reference to the job3 configured in the XML file must not be null", job3);
- JobExecution jobExecution = jobRepository.createJobExecution(job3.getName(), new JobParameters());
+ private List savedStepNames = new ArrayList();
- job3.execute(jobExecution);
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+ }
- for (StepExecution se : jobExecution.getStepExecutions()) {
- String stepExecutionName = se.getStepName();
- if (stepExecutionName.equalsIgnoreCase("j3s1")) { // the partitioned step
- PartitionStep partitionStep = (PartitionStep) this.applicationContext.getBean(stepExecutionName);
+ @Before
+ public void setUp() {
+ nameStoringTasklet.setStepNamesList(savedStepNames);
+ mapJobRepositoryFactoryBean.clear();
+ }
- // prove that the reference in the {@link TaskExecutorPartitionHandler} is the step configured inline
- TaskExecutorPartitionHandler taskExecutorPartitionHandler = accessPrivateField(partitionStep, "partitionHandler");
- TaskletStep taskletStep = accessPrivateField(taskExecutorPartitionHandler, "step");
+ @SuppressWarnings("unchecked")
+ private T accessPrivateField(Object o, String fieldName) {
+ Field field = ReflectionUtils.findField(o.getClass(), fieldName);
+ boolean previouslyAccessibleValue = field.isAccessible();
+ field.setAccessible(true);
+ T val = (T) ReflectionUtils.getField(field, o);
+ field.setAccessible(previouslyAccessibleValue);
+ return val;
+ }
- assertNotNull("the taskletStep wasn't configured with a step. " +
- "We're trusting that the factory ensured " +
- "a reference was given.", taskletStep);
- }
- }
- assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
- }
+ @Test
+ public void testCustomHandlerRefStep() throws Exception {
+ assertNotNull(job5);
+ JobExecution jobExecution = jobRepository.createJobExecution(job5.getName(), new JobParameters());
+ job5.execute(jobExecution);
+ assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
+ List stepNames = getStepNames(jobExecution);
+ assertEquals(1, stepNames.size());
+ assertEquals("[j5s1]", stepNames.toString());
+ }
- @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 stepNames = getStepNames(jobExecution);
- assertEquals(3, stepNames.size());
- assertEquals("[s1, step1:partition0, step1:partition1]", stepNames.toString());
- }
+ /**
+ * BATCH-1509 we now support the ability define steps inline for partitioned
+ * steps. this demonstates that the execution proceeds as expected and that
+ * the partitionhandler has a reference to the inline step definition
+ */
+ @Test
+ public void testNestedPartitionStep() throws Throwable {
+ assertNotNull("the reference to the job4 configured in the XML file must not be null", job4);
+ JobExecution jobExecution = jobRepository.createJobExecution(job4.getName(), new JobParameters());
- @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(5, stepNames.size());
- assertEquals("[s2, s3, step1:partition0, step1:partition1, step1:partition2]", stepNames.toString());
- }
+ job4.execute(jobExecution);
- private List getStepNames(JobExecution jobExecution) {
- List list = new ArrayList();
- for (StepExecution stepExecution : jobExecution.getStepExecutions()) {
- list.add(stepExecution.getStepName());
- }
- Collections.sort(list);
- return list;
- }
+ for (StepExecution se : jobExecution.getStepExecutions()) {
+ String stepExecutionName = se.getStepName();
+ if (stepExecutionName.equalsIgnoreCase("j4s1")) { // the partitioned
+ // step
+ PartitionStep partitionStep = (PartitionStep) this.applicationContext.getBean(stepExecutionName);
+
+ // prove that the reference in the {@link
+ // TaskExecutorPartitionHandler} is the step configured inline
+ TaskExecutorPartitionHandler taskExecutorPartitionHandler = accessPrivateField(partitionStep,
+ "partitionHandler");
+ TaskletStep taskletStep = accessPrivateField(taskExecutorPartitionHandler, "step");
+
+ assertNotNull("the taskletStep wasn't configured with a step. "
+ + "We're trusting that the factory ensured " + "a reference was given.", taskletStep);
+ }
+ }
+ assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
+ // Step names not saved by this one (it geosn't have that tasklet)
+ assertEquals("[]", savedStepNames.toString());
+ List stepNames = getStepNames(jobExecution);
+ assertEquals(4, stepNames.size());
+ assertEquals("[j4s1, j4s1:partition0, j4s1:partition1, j4s1:partition2]", stepNames.toString());
+ }
+
+ /**
+ * BATCH-1509 we now support the ability define steps inline for partitioned
+ * steps. this demonstates that the execution proceeds as expected and that
+ * the partitionhandler has a reference to the inline step definition
+ */
+ @Test
+ public void testNestedPartitionStepStepReference() throws Throwable {
+ assertNotNull("the reference to the job3 configured in the XML file must not be null", job3);
+ JobExecution jobExecution = jobRepository.createJobExecution(job3.getName(), new JobParameters());
+
+ job3.execute(jobExecution);
+
+ for (StepExecution se : jobExecution.getStepExecutions()) {
+ String stepExecutionName = se.getStepName();
+ if (stepExecutionName.equalsIgnoreCase("j3s1")) { // the partitioned
+ // step
+ PartitionStep partitionStep = (PartitionStep) this.applicationContext.getBean(stepExecutionName);
+
+ // prove that the reference in the {@link
+ // TaskExecutorPartitionHandler} is the step configured inline
+ TaskExecutorPartitionHandler taskExecutorPartitionHandler = accessPrivateField(partitionStep,
+ "partitionHandler");
+ TaskletStep taskletStep = accessPrivateField(taskExecutorPartitionHandler, "step");
+
+ assertNotNull("the taskletStep wasn't configured with a step. "
+ + "We're trusting that the factory ensured " + "a reference was given.", taskletStep);
+ }
+ }
+ assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
+ Collections.sort(savedStepNames);
+ assertEquals("[j3s1:partition0, j3s1:partition1, j3s1:partition2]", savedStepNames.toString());
+ List stepNames = getStepNames(jobExecution);
+ assertEquals(4, stepNames.size());
+ assertEquals("[j3s1, j3s1:partition0, j3s1:partition1, j3s1:partition2]", stepNames.toString());
+ }
+
+ @Test
+ public void testDefaultHandlerStep() throws Exception {
+ assertNotNull(job1);
+ JobExecution jobExecution = jobRepository.createJobExecution(job1.getName(), new JobParameters());
+ job1.execute(jobExecution);
+ assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
+ Collections.sort(savedStepNames);
+ assertEquals("[step1:partition0, step1:partition1]", savedStepNames.toString());
+ List stepNames = getStepNames(jobExecution);
+ assertEquals(3, stepNames.size());
+ assertEquals("[s1, step1:partition0, step1:partition1]", 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());
+ Collections.sort(savedStepNames);
+ assertEquals("[s3, step1:partition0, step1:partition1, step1:partition2]", savedStepNames.toString());
+ List stepNames = getStepNames(jobExecution);
+ assertEquals(5, stepNames.size());
+ assertEquals("[s2, s3, step1:partition0, step1:partition1, step1:partition2]", 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;
+ }
+
+ public static class CustomPartitionHandler implements PartitionHandler {
+
+ public Collection handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution)
+ throws Exception {
+ return Arrays.asList(stepExecution);
+ }
+
+ }
}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandlerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandlerTests.java
index 7d4285871..859a50f2b 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandlerTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandlerTests.java
@@ -10,7 +10,6 @@ import java.util.Set;
import java.util.TreeSet;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
@@ -60,12 +59,11 @@ public class TaskExecutorPartitionHandlerTests {
handler.afterPropertiesSet();
}
- @Ignore //TODO update or simply remove?
@Test
- public void testAfterPropertiesSet() throws Exception {
+ public void testNullStep() throws Exception {
handler = new TaskExecutorPartitionHandler();
try {
- handler.afterPropertiesSet();
+ handler.handle(stepExecutionSplitter, stepExecution);
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
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
index 7a931a393..ca3be0e34 100644
--- 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
@@ -1,6 +1,6 @@
-
@@ -16,39 +16,48 @@
-
+
-
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
+
\ No newline at end of file