diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/DecisionParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/DecisionParser.java index 7ca06d1e9..363cdcc50 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/DecisionParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/DecisionParser.java @@ -15,9 +15,7 @@ */ package org.springframework.batch.core.configuration.xml; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; import org.springframework.batch.core.job.flow.DecisionState; import org.springframework.batch.core.job.flow.JobExecutionDecider; @@ -25,7 +23,6 @@ import org.springframework.batch.flow.StateTransition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; /** @@ -52,23 +49,12 @@ public class DecisionParser { public Collection parse(Element element, ParserContext parserContext) { String refAttribute = element.getAttribute("decider"); + String idAttribute = element.getAttribute("id"); - Collection list = new ArrayList(); - - @SuppressWarnings("unchecked") - List nextElements = (List) DomUtils.getChildElementsByTagName(element, "next"); - - for (Element nextElement : nextElements) { - String onAttribute = nextElement.getAttribute("on"); - String nextAttribute = nextElement.getAttribute("to"); - BeanDefinitionBuilder stateBuilder = BeanDefinitionBuilder.genericBeanDefinition(DecisionState.class); - stateBuilder.addConstructorArgValue(new RuntimeBeanReference(refAttribute)); - stateBuilder.addConstructorArgValue(parserContext.getReaderContext().generateBeanName(stateBuilder.getBeanDefinition())); - list.add(StepParser.getStateTransitionReference(parserContext, stateBuilder.getBeanDefinition(), - onAttribute, nextAttribute)); - } - - return list; + BeanDefinitionBuilder stateBuilder = BeanDefinitionBuilder.genericBeanDefinition(DecisionState.class); + stateBuilder.addConstructorArgValue(new RuntimeBeanReference(refAttribute)); + stateBuilder.addConstructorArgValue(idAttribute); + return StepParser.getNextElements(parserContext, stateBuilder.getBeanDefinition(), element); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/FlowParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/FlowParser.java index 7df142b58..40dffdf4a 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/FlowParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/FlowParser.java @@ -57,13 +57,6 @@ public class FlowParser { stateTransitions.addAll(decisionParser.parse(stepElement, parserContext)); } - @SuppressWarnings("unchecked") - List pauseElements = (List) DomUtils.getChildElementsByTagName(element, "pause"); - PauseParser pauseParser = new PauseParser(); - for (Element stepElement : pauseElements) { - stateTransitions.add(pauseParser.parse(stepElement, parserContext)); - } - @SuppressWarnings("unchecked") List splitElements = (List) DomUtils.getChildElementsByTagName(element, "split"); SplitParser splitParser = new SplitParser(); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/PauseParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/PauseParser.java deleted file mode 100644 index 70ab87a3a..000000000 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/PauseParser.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 org.springframework.batch.core.job.flow.PauseState; -import org.springframework.batch.flow.StateTransition; -import org.springframework.beans.factory.config.RuntimeBeanReference; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.xml.ParserContext; -import org.w3c.dom.Element; - -/** - * Internal parser for the <pause/> elements inside a job. A pause element - * causes the job flow to end and will resume on the next execution at the next - * state. Used by the {@link JobParser}. - * - * @see JobParser - * - * @author Dave Syer - * - */ -public class PauseParser { - - /** - * Parse the pause and turn it into a transition. - * - * @param element the <pause/gt; element to parse - * @param parserContext the parser context for the bean factory - * @return a bean definitions for a {@link StateTransition} - * instances objects - */ - public RuntimeBeanReference parse(Element element, ParserContext parserContext) { - - String nextAttribute = element.getAttribute("next"); - String idAttribute = element.getAttribute("id"); - - BeanDefinitionBuilder stateBuilder = BeanDefinitionBuilder.genericBeanDefinition(PauseState.class); - stateBuilder.addConstructorArgValue(idAttribute); - return StepParser.getStateTransitionReference(parserContext, stateBuilder.getBeanDefinition(), "*", - nextAttribute); - - } -} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SplitParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SplitParser.java index 96bc48b6d..7bea42bd4 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SplitParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SplitParser.java @@ -22,13 +22,11 @@ import java.util.List; import org.springframework.batch.core.job.flow.JobExecutionDecider; import org.springframework.batch.flow.SplitState; import org.springframework.batch.flow.StateTransition; -import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; @@ -76,40 +74,8 @@ public class SplitParser { stateBuilder.addConstructorArgValue(managedList); stateBuilder.addConstructorArgValue(idAttribute); - // TODO: extract common code from StepParser // TODO: allow TaskExecutor etc. to be set - - Collection list = new ArrayList(); - - String shortNextAttribute = element.getAttribute("next"); - boolean hasNextAttribute = StringUtils.hasText(shortNextAttribute); - if (hasNextAttribute) { - list.add(StepParser.getStateTransitionReference(parserContext, stateBuilder.getBeanDefinition(), null, - shortNextAttribute)); - } - - @SuppressWarnings("unchecked") - List nextElements = (List) DomUtils.getChildElementsByTagName(element, "next"); - - // If there are no next elements then this must be an end state - if (nextElements.isEmpty() && !hasNextAttribute) { - list.add(StepParser.getStateTransitionReference(parserContext, stateBuilder.getBeanDefinition(), null, null)); - } - else { - // Otherwise we need to capture the "to" state - for (Element nextElement : nextElements) { - String onAttribute = nextElement.getAttribute("on"); - String nextAttribute = nextElement.getAttribute("to"); - if (hasNextAttribute && onAttribute.equals("*")) { - throw new BeanCreationException("Duplicate transition pattern found for '*' " - + "(only specify one of next= attribute at step level and next element with on='*')"); - } - list.add(StepParser.getStateTransitionReference(parserContext, stateBuilder.getBeanDefinition(), - onAttribute, nextAttribute)); - } - } - - return list; + return StepParser.getNextElements(parserContext, stateBuilder.getBeanDefinition(), element); } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParser.java index ab993037b..cb6600ce2 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParser.java @@ -19,7 +19,9 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import org.springframework.batch.core.BatchStatus; import org.springframework.batch.core.Step; +import org.springframework.batch.core.job.flow.EndState; import org.springframework.batch.core.job.flow.StepState; import org.springframework.batch.flow.StateTransition; import org.springframework.beans.factory.BeanCreationException; @@ -46,6 +48,9 @@ import org.w3c.dom.Element; */ public class StepParser { + // For generating unique state names for end transitions + private static int endCounter = 0; + /** * Parse the step and turn it into a list of transitions. * @@ -56,55 +61,73 @@ public class StepParser { */ public Collection parse(Element element, ParserContext parserContext) { - String refAttribute = element.getAttribute("name"); + RuntimeBeanReference stateDef = new RuntimeBeanReference(element.getAttribute("name")); + BeanDefinitionBuilder stateBuilder = BeanDefinitionBuilder.genericBeanDefinition(StepState.class); + stateBuilder.addConstructorArgValue(stateDef); + return getNextElements(parserContext, stateBuilder.getBeanDefinition(), element); + + } + + /** + * @param parserContext + * @param stateDef + * @param element + * @return a collection of {@link StateTransition} references + */ + public static Collection getNextElements(ParserContext parserContext, + BeanDefinition stateDef, Element element) { Collection list = new ArrayList(); String shortNextAttribute = element.getAttribute("next"); boolean hasNextAttribute = StringUtils.hasText(shortNextAttribute); if (hasNextAttribute) { - list.add(getStateTransitionReference(parserContext, new RuntimeBeanReference(refAttribute), null, - shortNextAttribute)); + list.add(getStateTransitionReference(parserContext, stateDef, null, shortNextAttribute)); } @SuppressWarnings("unchecked") List nextElements = (List) DomUtils.getChildElementsByTagName(element, "next"); + @SuppressWarnings("unchecked") + List stopElements = (List) DomUtils.getChildElementsByTagName(element, "stop"); + nextElements.addAll(stopElements); + @SuppressWarnings("unchecked") + List endElements = (List) DomUtils.getChildElementsByTagName(element, "end"); + nextElements.addAll(endElements); - // If there are no next elements then this must be an end state - if (nextElements.isEmpty() && !hasNextAttribute) { - list.add(getStateTransitionReference(parserContext, new RuntimeBeanReference(refAttribute), null, null)); - } - else { - // Otherwise we need to capture the "to" state - for (Element nextElement : nextElements) { - String onAttribute = nextElement.getAttribute("on"); - String nextAttribute = nextElement.getAttribute("to"); - if (hasNextAttribute && onAttribute.equals("*")) { - throw new BeanCreationException("Duplicate transition pattern found for '*' " - + "(only specify one of next= attribute at step level and next element with on='*')"); - } - list.add(getStateTransitionReference(parserContext, new RuntimeBeanReference(refAttribute), - onAttribute, nextAttribute)); + for (Element nextElement : nextElements) { + String onAttribute = nextElement.getAttribute("on"); + String nextAttribute = nextElement.getAttribute("to"); + if (hasNextAttribute && onAttribute.equals("*")) { + throw new BeanCreationException("Duplicate transition pattern found for '*' " + + "(only specify one of next= attribute at step level and next element with on='*')"); } + + String name = nextElement.getNodeName(); + if ("stop".equals(name) || "end".equals(name)) { + + String statusName = nextElement.getAttribute("status"); + BatchStatus status = StringUtils.hasText(statusName) ? BatchStatus.valueOf(statusName) + : BatchStatus.STOPPED; + String nextOnEnd = StringUtils.hasText(statusName) ? null : nextAttribute; + + BeanDefinitionBuilder endBuilder = BeanDefinitionBuilder.genericBeanDefinition(EndState.class); + endBuilder.addConstructorArgValue(status); + String endName = "end" + endCounter; + endCounter++; + + endBuilder.addConstructorArgValue(endName); + list.add(getStateTransitionReference(parserContext, endBuilder.getBeanDefinition(), onAttribute, nextOnEnd)); + nextAttribute = endName; + + } + list.add(getStateTransitionReference(parserContext, stateDef, onAttribute, nextAttribute)); + } + + if (list.isEmpty() && !hasNextAttribute) { + list.add(getStateTransitionReference(parserContext, stateDef, null, null)); } return list; - - } - - /** - * @param parserContext - * @param runtimeBeanReference - * @param onAttribute - * @param nextAttribute - * @return - */ - private RuntimeBeanReference getStateTransitionReference(ParserContext parserContext, - RuntimeBeanReference runtimeBeanReference, String onAttribute, String nextAttribute) { - BeanDefinitionBuilder stateBuilder = BeanDefinitionBuilder.genericBeanDefinition(StepState.class); - stateBuilder.addConstructorArgValue(runtimeBeanReference); - return getStateTransitionReference(parserContext, stateBuilder.getBeanDefinition(), onAttribute, - nextAttribute); } /** @@ -115,8 +138,7 @@ public class StepParser { * @return a bean definition for a {@link StateTransition} */ public static RuntimeBeanReference getStateTransitionReference(ParserContext parserContext, - BeanDefinition stateDefinition, String on, - String next) { + BeanDefinition stateDefinition, String on, String next) { BeanDefinitionBuilder nextBuilder = BeanDefinitionBuilder.genericBeanDefinition(StateTransition.class); nextBuilder.addConstructorArgValue(stateDefinition); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/EndState.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/EndState.java new file mode 100644 index 000000000..b0038003e --- /dev/null +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/EndState.java @@ -0,0 +1,46 @@ +package org.springframework.batch.core.job.flow; + +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.flow.AbstractState; +import org.springframework.batch.flow.FlowExecution; +import org.springframework.batch.flow.State; + +/** + * {@link State} implementation for ending a job if it is in progress and + * continuing if just starting. + * + * @author Dave Syer + * + */ +public class EndState extends AbstractState { + + private final BatchStatus status; + + /** + * @param name + */ + EndState(BatchStatus status, String name) { + super(name); + this.status = status; + } + + /** + * Set the status as long the {@link JobExecution} is in progress. If this + * is the first place we came after a restart we do nothing (otherwise the + * same outcome that ended the job on the last run will occur). + * + * @see State#handle(Object) + */ + @Override + public String handle(JobFlowExecutor context) throws Exception { + JobExecution jobExecution = context.getJobExecution(); + // If there are no step executions, then we are at the beginning of a + // restart + if (!jobExecution.getStepExecutions().isEmpty()) { + jobExecution.setStatus(status); + } + return FlowExecution.COMPLETED; + } + +} \ No newline at end of file diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.0.xsd b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.0.xsd index 7b4e70dd3..162d6ec28 100644 --- a/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.0.xsd +++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.0.xsd @@ -84,21 +84,52 @@ specific match will be chosen to select the next step. Hint: always include a de - + - Declares job should be paused at this point and provides pointer where execution should continue. + Declares job should be stop at this point and provides pointer where execution should continue. - + - - + A pattern to match against the exit status code. Use * and ? as wildcard characters. When a step finishes the most +specific match will be chosen to select the next step. Hint: always include a default transition with on="*". + + + + The name of the step to go to next. + Must resolve to one of the other steps in this job. - + + + + + + + Declares job should be stop at this point and provides optional pointer where execution should continue. + + + + + + A pattern to match against the exit status code. Use * and ? as wildcard characters. When a step finishes the most +specific match will be chosen to select the next step. Hint: always include a default transition with on="*". + + + + + The BatchStatus value to end on, defaults to COMPLETED. + + + + + + + + + @@ -111,6 +142,7 @@ specific match will be chosen to select the next step. Hint: always include a de + @@ -151,7 +183,6 @@ The decider is a reference to a JobExecutionDecider that can produce a status to - @@ -173,11 +204,11 @@ The decider is a reference to a JobExecutionDecider that can produce a status to - - - A sequence of next elements specifies the possible transitions from this step to the next one. - - + + + + + diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PauseJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopJobParserTests.java similarity index 80% rename from spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PauseJobParserTests.java rename to spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopJobParserTests.java index 6e96dffda..c4e858e89 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PauseJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopJobParserTests.java @@ -25,6 +25,7 @@ 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.job.flow.JobExecutionDecider; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean; import org.springframework.beans.factory.annotation.Autowired; @@ -38,7 +39,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -public class PauseJobParserTests { +public class StopJobParserTests { @Autowired @Qualifier("job") @@ -53,15 +54,22 @@ public class PauseJobParserTests { } @Test - public void testPauseState() throws Exception { + public void testStopState() throws Exception { assertNotNull(job); JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters()); job.execute(jobExecution); - assertEquals(BatchStatus.PAUSED, jobExecution.getStatus()); + assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); assertEquals(1, jobExecution.getStepExecutions().size()); + jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters()); job.execute(jobExecution); assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - assertEquals(2, jobExecution.getStepExecutions().size()); + assertEquals(1, jobExecution.getStepExecutions().size()); + } + + public static class TestDecider implements JobExecutionDecider { + public String decide(JobExecution jobExecution) { + return "FOO"; + } } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowJobTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowJobTests.java index 06476c718..8debfa572 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowJobTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowJobTests.java @@ -123,12 +123,70 @@ public class FlowJobTests { assertEquals(1, jobExecution.getStepExecutions().size()); } + @Test + public void testEndStateStopped() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + Collection> transitions = new ArrayList>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end")); + transitions.add(StateTransition.createStateTransition(new EndState(BatchStatus.STOPPED, "end"), "step2")); + transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2")))); + flow.setStateTransitions(transitions); + job.setFlow(flow); + job.afterPropertiesSet(); + try { + job.doExecute(jobExecution); + fail("Expected JobInterruptedException"); + } + catch (JobInterruptedException e) { + // expected + } + assertEquals(1, jobExecution.getStepExecutions().size()); + } + + public void testEndStateFailed() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + Collection> transitions = new ArrayList>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end")); + transitions.add(StateTransition.createStateTransition(new EndState(BatchStatus.FAILED, "end"), "step2")); + transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2")))); + flow.setStateTransitions(transitions); + job.setFlow(flow); + job.afterPropertiesSet(); + job.doExecute(jobExecution); + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + assertEquals(1, jobExecution.getStepExecutions().size()); + } + + @Test + public void testEndStateStoppedWithRestart() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + Collection> transitions = new ArrayList>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end")); + transitions.add(StateTransition.createStateTransition(new EndState(BatchStatus.STOPPED, "end"), "step2")); + transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2")))); + flow.setStateTransitions(transitions); + job.setFlow(flow); + job.afterPropertiesSet(); + + // To test a restart we have to use the AbstractJob.execute()... + job.execute(jobExecution); + assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); + assertEquals(1, jobExecution.getStepExecutions().size()); + + jobExecution = jobRepository.createJobExecution("job", new JobParameters()); + job.execute(jobExecution); + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + assertEquals(1, jobExecution.getStepExecutions().size()); + + } + @Test public void testBranching() throws Exception { SimpleFlow flow = new SimpleFlow("job"); Collection> transitions = new ArrayList>(); transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "COMPLETED", "step3")); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "COMPLETED", + "step3")); transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step2")))); transitions.add(StateTransition.createEndStateTransition(new StepState(new StubStep("step3")))); flow.setStateTransitions(transitions); diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/DecisionJobParserTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/DecisionJobParserTests-context.xml index b1d23c297..4bb1dc5c1 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/DecisionJobParserTests-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/DecisionJobParserTests-context.xml @@ -9,7 +9,7 @@ - + diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/PauseJobParserTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StopJobParserTests-context.xml similarity index 64% rename from spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/PauseJobParserTests-context.xml rename to spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StopJobParserTests-context.xml index 05adbafac..2b531f566 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/PauseJobParserTests-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/StopJobParserTests-context.xml @@ -6,9 +6,16 @@ + + - - + + + + + + + diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/flow/AbstractState.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/flow/AbstractState.java index 7b3f5cc3b..c786e0366 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/flow/AbstractState.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/flow/AbstractState.java @@ -35,6 +35,14 @@ public abstract class AbstractState implements State { return name; } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return getClass().getSimpleName()+": name=["+name+"]"; + } + public abstract String handle(T context) throws Exception; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/flow/SplitState.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/flow/SplitState.java index 806ecba57..eb79da66d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/flow/SplitState.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/flow/SplitState.java @@ -77,11 +77,7 @@ public class SplitState extends AbstractState { tasks.add(task); try { - taskExecutor.execute(new Runnable() { - public void run() { - task.run(); - } - }); + taskExecutor.execute(task); } catch (TaskRejectedException e) { throw new FlowExecutionException("TaskExecutor rejected task for flow=" + flow.getName());