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