RESOLVED - issue BATCH-1011: Need distinction between "stop" and "end" transitions?

Push JobExecution status update out of the EndState and back into FlowJob (via FlowExecutor).
This commit is contained in:
dsyer
2009-02-17 13:11:33 +00:00
parent 3836cd9597
commit 365fd46744
23 changed files with 263 additions and 399 deletions

View File

@@ -19,8 +19,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
import org.springframework.batch.core.job.flow.support.SimpleFlow;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
@@ -172,10 +171,10 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
}
if (!transitionElementExists) {
list.addAll(createTransition(BatchStatus.FAILED, ExitStatus.FAILED.getExitCode(), null, null, stateDef,
parserContext, false));
list.addAll(createTransition(FlowExecutionStatus.FAILED, FlowExecutionStatus.FAILED.toString(), null, null, stateDef, parserContext, false));
if (!hasNextAttribute) {
list.addAll(createTransition(BatchStatus.COMPLETED, null, null, null, stateDef, parserContext, false));
list.addAll(createTransition(FlowExecutionStatus.COMPLETED, null, null, null, stateDef, parserContext,
false));
}
}
else if (hasNextAttribute) {
@@ -213,7 +212,7 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
private static Collection<BeanDefinition> parseTransitionElement(Element transitionElement, String stateId,
BeanDefinition stateDef, ParserContext parserContext) {
BatchStatus batchStatus = getBatchStatusFromEndTransitionName(transitionElement.getNodeName());
FlowExecutionStatus batchStatus = getBatchStatusFromEndTransitionName(transitionElement.getNodeName());
String onAttribute = transitionElement.getAttribute("on");
String nextAttribute = transitionElement.getAttribute("to");
String restartAttribute = transitionElement.getAttribute("restart");
@@ -243,24 +242,28 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
* {@link org.springframework.batch.core.job.flow.support.StateTransition}
* references
*/
private static Collection<BeanDefinition> createTransition(BatchStatus batchStatus, String on, String next,
private static Collection<BeanDefinition> createTransition(FlowExecutionStatus batchStatus, String on, String next,
String exitCode, BeanDefinition stateDef, ParserContext parserContext, boolean abandon) {
BeanDefinition endState = null;
// TODO: revise this for clarity
if (batchStatus == BatchStatus.STOPPED || batchStatus == BatchStatus.COMPLETED
|| batchStatus == BatchStatus.FAILED) {
if (batchStatus == FlowExecutionStatus.STOPPED || batchStatus == FlowExecutionStatus.COMPLETED
|| batchStatus == FlowExecutionStatus.FAILED) {
BeanDefinitionBuilder endBuilder = BeanDefinitionBuilder
.genericBeanDefinition("org.springframework.batch.core.job.flow.support.state.EndState");
endBuilder.addConstructorArgValue(batchStatus);
boolean exitCodeExists = StringUtils.hasText(exitCode);
endBuilder.addConstructorArgValue(exitCodeExists ? new ExitStatus(exitCode)
: convertToExitStatus(batchStatus));
// Make sure exit code is consistent with status for aggregation
// purposes
if (exitCodeExists && !exitCode.startsWith(batchStatus.toString())) {
exitCode = batchStatus.toString() + (exitCode.contains(" ") ? " " : "_") + exitCode;
}
endBuilder.addConstructorArgValue(exitCodeExists ? new FlowExecutionStatus(exitCode) : batchStatus);
String endName = (batchStatus == BatchStatus.STOPPED ? STOP : batchStatus == BatchStatus.FAILED ? FAIL : END)
String endName = (batchStatus == FlowExecutionStatus.STOPPED ? STOP
: batchStatus == FlowExecutionStatus.FAILED ? FAIL : END)
+ (endCounter++);
endBuilder.addConstructorArgValue(endName);
@@ -288,31 +291,18 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
* @param elementName An end transition element name
* @return the BatchStatus corresponding to the transition name
*/
private static BatchStatus getBatchStatusFromEndTransitionName(String elementName) {
private static FlowExecutionStatus getBatchStatusFromEndTransitionName(String elementName) {
if (STOP.equals(elementName)) {
return BatchStatus.STOPPED;
return FlowExecutionStatus.STOPPED;
}
else if (END.equals(elementName)) {
return BatchStatus.COMPLETED;
return FlowExecutionStatus.COMPLETED;
}
else if (FAIL.equals(elementName)) {
return BatchStatus.FAILED;
return FlowExecutionStatus.FAILED;
}
else {
return BatchStatus.UNKNOWN;
}
}
/**
* @param batchStatus A BatchStatus
* @return the ExitStatus corresponding to the BatchStatus
*/
private static ExitStatus convertToExitStatus(BatchStatus batchStatus) {
if (batchStatus == BatchStatus.FAILED) {
return ExitStatus.FAILED;
}
else {
return new ExitStatus(batchStatus.toString());
return FlowExecutionStatus.UNKNOWN;
}
}

View File

@@ -70,7 +70,21 @@ public class FlowExecutionStatus implements Comparable<FlowExecutionStatus> {
public FlowExecutionStatus(String status) {
this.status = status;
}
/**
* @return true if the status starts with "STOPPED"
*/
public boolean isStop() {
return status.startsWith(STOPPED.getStatus());
}
/**
* @return true if the status starts with "FAILED"
*/
public boolean isFail() {
return status.startsWith(FAILED.toString());
}
/**
* Create an ordering on {@link FlowExecutionStatus} instances by comparing
* their statuses.
@@ -107,7 +121,7 @@ public class FlowExecutionStatus implements Comparable<FlowExecutionStatus> {
}
public String toString() {
return "FlowExecutionStatus: " + status;
return status;
}
public String getStatus() {

View File

@@ -32,15 +32,13 @@ import org.springframework.batch.core.repository.JobRestartException;
public interface FlowExecutor {
/**
* @param step
* a {@link Step} to execute
* @param step a {@link Step} to execute
* @return the exit status that drives the surrounding {@link Flow}
* @throws StartLimitExceededException
* @throws JobRestartException
* @throws JobInterruptedException
*/
String executeStep(Step step) throws JobInterruptedException,
JobRestartException, StartLimitExceededException;
String executeStep(Step step) throws JobInterruptedException, JobRestartException, StartLimitExceededException;
/**
* @return the current {@link JobExecution}
@@ -56,29 +54,19 @@ public interface FlowExecutor {
* Chance to clean up resources at the end of a flow (whether it completed
* successfully or not).
*
* @param result
* the final {@link FlowExecution}
* @param result the final {@link FlowExecution}
*/
void close(FlowExecution result);
/**
* Handle any status changes that might be needed at the start of a state.
*/
void updateStepExecutionStatus();
void abandonStepExecution();
/**
* Push a token onto a stack to indicate that the context is being nested.
* Handle any status changes that might be needed in the
* {@link JobExecution}.
*/
void nest();
/**
* Pop a token off a stack to indicate that the context is being un-nested.
*/
void unnest();
/**
* @return indicate whether the execution context is nested
*/
boolean isNested();
void updateJobExecutionStatus(FlowExecutionStatus status);
}

View File

@@ -80,7 +80,8 @@ public class FlowJob extends AbstractJob {
protected void doExecute(final JobExecution execution)
throws JobExecutionException {
try {
flow.start(new JobFlowExecutor(execution));
JobFlowExecutor executor = new JobFlowExecutor(execution);
executor.updateJobExecutionStatus(flow.start(executor).getStatus());
} catch (FlowExecutionException e) {
if (e.getCause() instanceof JobExecutionException) {
throw (JobExecutionException) e.getCause();
@@ -100,8 +101,6 @@ public class FlowJob extends AbstractJob {
private final JobExecution execution;
private volatile boolean nested = false;
/**
* @param execution
*/
@@ -118,7 +117,7 @@ public class FlowJob extends AbstractJob {
: stepExecution.getExitStatus().getExitCode();
}
public void updateStepExecutionStatus() {
public void abandonStepExecution() {
StepExecution lastStepExecution = stepExecutionHolder.get();
if (lastStepExecution != null
&& lastStepExecution.getStatus().isGreaterThan(
@@ -127,6 +126,11 @@ public class FlowJob extends AbstractJob {
updateStepExecution(lastStepExecution);
}
}
public void updateJobExecutionStatus(FlowExecutionStatus status) {
execution.setStatus(findBatchStatus(status));
execution.setExitStatus(new ExitStatus(status.getStatus()));
}
public JobExecution getJobExecution() {
return execution;
@@ -140,16 +144,17 @@ public class FlowJob extends AbstractJob {
stepExecutionHolder.set(null);
}
public boolean isNested() {
return nested;
}
public void nest() {
nested = true;
}
public void unnest() {
nested = false;
/**
* @param status
* @return
*/
private BatchStatus findBatchStatus(FlowExecutionStatus status) {
for (BatchStatus batchStatus : BatchStatus.values()) {
if (status.getStatus().startsWith(batchStatus.toString())) {
return batchStatus;
}
}
return BatchStatus.UNKNOWN;
}
}

View File

@@ -33,6 +33,6 @@ public interface JobExecutionDecider {
* @param stepExecution the latest step execution (may be null)
* @return the exit status code
*/
String decide(JobExecution jobExecution, StepExecution stepExecution);
FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution);
}

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.batch.core.job.flow;
/**
* @author Dave Syer
*
@@ -46,10 +44,12 @@ public interface State {
FlowExecutionStatus handle(FlowExecutor executor) throws Exception;
/**
* Validate that the transition attributes are appropriate for this State.
* Inquire as to whether a {@link State} is an end state. Implementations
* should return false if processing can continue, even if that would
* require a restart.
*
* @param pattern
* @param nextState
* @return true if this {@link State} is the end of processing
*/
void validate(String pattern, String nextState);
boolean isEndState();
}

View File

@@ -100,7 +100,9 @@ public class StateTransition implements Comparable<StateTransition> {
}
Assert.notNull(state, "A state is required for a StateTransition");
state.validate(pattern, next);
if (state.isEndState() && StringUtils.hasText(next)) {
throw new IllegalStateException("End state cannot have next: "+state);
}
this.next = next;
this.state = state;

View File

@@ -38,16 +38,14 @@ public class DecisionState extends AbstractState {
@Override
public FlowExecutionStatus handle(FlowExecutor executor) throws Exception {
return new FlowExecutionStatus(decider.decide(executor.getJobExecution(), executor.getStepExecution()));
return decider.decide(executor.getJobExecution(), executor.getStepExecution());
}
/* (non-Javadoc)
* @see org.springframework.batch.core.job.flow.State#isEndState()
*/
public boolean isEndState() {
return false;
}
/* (non-Javadoc)
* @see org.springframework.batch.core.job.flow.State#validate(java.lang.String)
*/
public void validate(String pattern, String nextState) {
if (nextState == null) {
throw new IllegalStateException("The transition for " + getClass().getSimpleName() + " [" + getName()
+ "] requires a 'next' state.");
}
}
}

View File

@@ -16,8 +16,6 @@
package org.springframework.batch.core.job.flow.support.state;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
import org.springframework.batch.core.job.flow.FlowExecutor;
@@ -32,40 +30,33 @@ import org.springframework.batch.core.job.flow.State;
*/
public class EndState extends AbstractState {
private final BatchStatus status;
private final ExitStatus exitStatus;
private final FlowExecutionStatus status;
private final boolean abandon;
/**
* @param status The BatchStatus to end with
* @param exitStatus The ExitStatus to end with
* @param status The {@link FlowExecutionStatus} to end with
* @param name The name of the state
*/
public EndState(BatchStatus status, ExitStatus exitStatus, String name) {
this(status, exitStatus, name, false);
public EndState(FlowExecutionStatus status, String name) {
this(status, name, false);
}
/**
* @param status The BatchStatus to end with
* @param exitStatus The ExitStatus to end with
* @param status The {@link FlowExecutionStatus} to end with
* @param name The name of the state
* @param abandon flag to indicate that previous step execution can be
* marked as abandoned (if there is one)
*
*/
public EndState(BatchStatus status, ExitStatus exitStatus, String name, boolean abandon) {
public EndState(FlowExecutionStatus status, String name, boolean abandon) {
super(name);
this.status = status;
this.exitStatus = exitStatus;
this.abandon = abandon;
}
/**
* Return the {@link BatchStatus} and {@link ExitStatus} stored. If the
* {@link BatchStatus} is {@link BatchStatus#FAILED}, then mark it on the
* {@link JobExecution} so that the job will know to stop.
* Return the {@link FlowExecutionStatus} stored.
*
* @see State#handle(FlowExecutor)
*/
@@ -73,51 +64,41 @@ public class EndState extends AbstractState {
public FlowExecutionStatus handle(FlowExecutor executor) throws Exception {
JobExecution jobExecution = executor.getJobExecution();
synchronized (jobExecution) {
if (!jobExecution.getStepExecutions().isEmpty()) {
/*
* If there are step executions, then we are not at the
* beginning of a restart.
*/
if (!executor.isNested()) {
jobExecution.setStatus(status);
jobExecution.setExitStatus(exitStatus);
}
if (status == BatchStatus.STOPPED) {
if (status.isStop()) {
if (!jobExecution.getStepExecutions().isEmpty()) {
/*
* If there are step executions, then we are not at the
* beginning of a restart.
*/
if (abandon) {
/*
* Only if instructed to do so upgrade the status of
* Only if instructed to do so, upgrade the status of
* last step execution so it is not replayed on a
* restart...
*/
executor.updateStepExecutionStatus();
executor.abandonStepExecution();
}
}
else {
/*
* If we are in flight (not a restart) and we are supposed
* to signal a stop, then make sure that happens
* irrespective of the exit status.
* If we are a stop state and we got this far then it must
* be a restart, so return COMPLETED.
*/
return FlowExecutionStatus.STOPPED;
return FlowExecutionStatus.COMPLETED;
}
}
return new FlowExecutionStatus(exitStatus.getExitCode());
return status;
}
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.batch.core.job.flow.State#validate(java.lang.String)
/* (non-Javadoc)
* @see org.springframework.batch.core.job.flow.State#isEndState()
*/
public void validate(String pattern, String nextState) {
if (status != BatchStatus.STOPPED && nextState != null) {
throw new IllegalStateException("The transition for " + getClass().getSimpleName() + " [" + getName()
+ "] may not have a 'next' state.");
}
if (pattern != null) {
throw new IllegalStateException("The transition for " + getClass().getSimpleName() + " [" + getName()
+ "] may not have a 'pattern'.");
}
public boolean isEndState() {
return !status.isStop();
}
/*
@@ -127,6 +108,6 @@ public class EndState extends AbstractState {
*/
@Override
public String toString() {
return super.toString() + " status=[" + status + "] exitcode=[" + exitStatus.getExitCode() + "] ";
return super.toString() + " status=[" + status + "]";
}
}

View File

@@ -71,10 +71,6 @@ public class SplitState extends AbstractState {
@Override
public FlowExecutionStatus handle(final FlowExecutor executor) throws Exception {
try {
executor.nest();
// TODO: collect the last StepExecution from the flows as well, so they
// can be abandoned if necessary
Collection<Future<FlowExecution>> tasks = new ArrayList<Future<FlowExecution>>();
@@ -107,22 +103,14 @@ public class SplitState extends AbstractState {
return aggregator.aggregate(results);
} finally {
executor.unnest();
}
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.batch.core.job.flow.State#validate(java.lang.String)
* @see org.springframework.batch.core.job.flow.State#isEndState()
*/
public void validate(String pattern, String nextState) {
if (nextState == null) {
throw new IllegalStateException("The transition for " + getClass().getSimpleName() + " [" + getName()
+ "] requires a 'next' state.");
}
public boolean isEndState() {
return false;
}
}

View File

@@ -52,7 +52,11 @@ public class StepState extends AbstractState implements StepHolder {
@Override
public FlowExecutionStatus handle(FlowExecutor executor) throws Exception {
executor.updateStepExecutionStatus();
/*
* On starting a new step, possibly upgrade the last execution to make
* sure it is abandoned on restart if it failed.
*/
executor.abandonStepExecution();
return new FlowExecutionStatus(executor.executeStep(step));
}
@@ -62,14 +66,12 @@ public class StepState extends AbstractState implements StepHolder {
public Step getStep() {
return step;
}
/* (non-Javadoc)
* @see org.springframework.batch.core.job.flow.State#validate(java.lang.String)
* @see org.springframework.batch.core.job.flow.State#isEndState()
*/
public void validate(String pattern, String nextState) {
if (nextState == null) {
throw new IllegalStateException("The transition for " + getClass().getSimpleName() + " [" + getName()
+ "] requires a 'next' state.");
}
public boolean isEndState() {
return false;
}
}

View File

@@ -26,6 +26,7 @@ import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
import org.springframework.batch.core.job.flow.JobExecutionDecider;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
@@ -34,22 +35,21 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Dave Syer
*
*
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class DecisionJobParserTests {
@Autowired
@Qualifier("job")
private Job job;
@Autowired
private JobRepository jobRepository;
@Before
public void setUp() {
MapJobRepositoryFactoryBean.clear();
@@ -63,10 +63,10 @@ public class DecisionJobParserTests {
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
assertEquals(1, jobExecution.getStepExecutions().size());
}
public static class TestDecider implements JobExecutionDecider {
public String decide(JobExecution jobExecution, StepExecution stepExecution) {
return "FOO";
public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {
return new FlowExecutionStatus("FOO");
}
}

View File

@@ -50,7 +50,7 @@ public class EndTransitionJobParserTests extends AbstractJobParserTests {
assertTrue(stepNamesList.contains("fail"));
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
assertEquals("EARLY TERMINATION (FAIL)", jobExecution.getExitStatus().getExitCode());
assertEquals("COMPLETED EARLY TERMINATION", jobExecution.getExitStatus().getExitCode());
StepExecution stepExecution1 = getStepExecution(jobExecution, "s1");
assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus());

View File

@@ -48,7 +48,7 @@ public class FailTransitionJobParserTests extends AbstractJobParserTests {
assertTrue(stepNamesList.contains("fail"));
assertEquals(BatchStatus.FAILED, jobExecution.getStatus());
assertEquals("EARLY TERMINATION (FAIL)", jobExecution.getExitStatus()
assertEquals("FAILED EARLY TERMINATION", jobExecution.getExitStatus()
.getExitCode());
StepExecution stepExecution1 = getStepExecution(jobExecution, "s1");

View File

@@ -24,6 +24,7 @@ import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
import org.springframework.batch.core.job.flow.JobExecutionDecider;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -73,8 +74,8 @@ public class StopJobParserTests extends AbstractJobParserTests {
}
public static class TestDecider implements JobExecutionDecider {
public String decide(JobExecution jobExecution, StepExecution stepExecution) {
return "FOO";
public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {
return new FlowExecutionStatus("FOO");
}
}

View File

@@ -64,26 +64,20 @@ public class FlowJobTests {
factory.afterPropertiesSet();
jobRepository = (JobRepository) factory.getObject();
job.setJobRepository(jobRepository);
jobExecution = jobRepository.createJobExecution("job",
new JobParameters());
jobExecution = jobRepository.createJobExecution("job", new JobParameters());
}
@Test
public void testTwoSteps() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
List<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step1")), "step2"));
transitions.add(StateTransition
.createStateTransition(new StepState(new StubStep("step2")),
ExitStatus.FAILED.getExitCode(), "end0"));
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step2")), ExitStatus.COMPLETED.getExitCode(),
"end1"));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.FAILED, ExitStatus.FAILED, "end0")));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.COMPLETED, ExitStatus.COMPLETED, "end1")));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), ExitStatus.FAILED
.getExitCode(), "end0"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")),
ExitStatus.COMPLETED.getExitCode(), "end1"));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end0")));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1")));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
@@ -97,18 +91,14 @@ public class FlowJobTests {
public void testFailedStep() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
List<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StateSupport(
"step1", FlowExecutionStatus.FAILED), "step2"));
transitions.add(StateTransition
.createStateTransition(new StepState(new StubStep("step2")),
ExitStatus.FAILED.getExitCode(), "end0"));
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step2")), ExitStatus.COMPLETED.getExitCode(),
"end1"));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.FAILED, ExitStatus.FAILED, "end0")));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.COMPLETED, ExitStatus.COMPLETED, "end1")));
transitions.add(StateTransition.createStateTransition(new StateSupport("step1", FlowExecutionStatus.FAILED),
"step2"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), ExitStatus.FAILED
.getExitCode(), "end0"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")),
ExitStatus.COMPLETED.getExitCode(), "end1"));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end0")));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1")));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
@@ -123,30 +113,24 @@ public class FlowJobTests {
public void testFailedStepRestarted() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
List<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step1")), "step2"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2"));
State step2State = new StateSupport("step2") {
@Override
public FlowExecutionStatus handle(FlowExecutor executor)
throws Exception {
public FlowExecutionStatus handle(FlowExecutor executor) throws Exception {
JobExecution jobExecution = executor.getJobExecution();
jobExecution.getStepExecutions().add(
new StepExecution(getName(), jobExecution));
jobExecution.getStepExecutions().add(new StepExecution(getName(), jobExecution));
if (fail) {
return FlowExecutionStatus.FAILED;
} else {
}
else {
return FlowExecutionStatus.COMPLETED;
}
}
};
transitions.add(StateTransition.createStateTransition(step2State,
ExitStatus.COMPLETED.getExitCode(), "end0"));
transitions.add(StateTransition.createStateTransition(step2State,
ExitStatus.FAILED.getExitCode(), "end1"));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.COMPLETED, ExitStatus.COMPLETED, "end0")));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.FAILED, ExitStatus.FAILED, "end1")));
transitions.add(StateTransition.createStateTransition(step2State, ExitStatus.COMPLETED.getExitCode(), "end0"));
transitions.add(StateTransition.createStateTransition(step2State, ExitStatus.FAILED.getExitCode(), "end1"));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0")));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end1")));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
@@ -155,8 +139,7 @@ public class FlowJobTests {
assertEquals(ExitStatus.FAILED, jobExecution.getExitStatus());
assertEquals(2, jobExecution.getStepExecutions().size());
jobRepository.update(jobExecution);
jobExecution = jobRepository.createJobExecution("job",
new JobParameters());
jobExecution = jobRepository.createJobExecution("job", new JobParameters());
fail = false;
job.execute(jobExecution);
assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
@@ -167,21 +150,15 @@ public class FlowJobTests {
public void testStoppingStep() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
List<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step1")), "step2"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2"));
State state2 = new StateSupport("step2", FlowExecutionStatus.FAILED);
transitions.add(StateTransition.createStateTransition(state2,
ExitStatus.FAILED.getExitCode(), "end0"));
transitions.add(StateTransition.createStateTransition(state2,
ExitStatus.COMPLETED.getExitCode(), "end1"));
transitions.add(StateTransition.createStateTransition(new EndState(
BatchStatus.STOPPED, ExitStatus.STOPPED, "end0"), "step3"));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.COMPLETED, ExitStatus.COMPLETED, "end1")));
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step3")), "end2"));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.COMPLETED, ExitStatus.COMPLETED, "end2")));
transitions.add(StateTransition.createStateTransition(state2, ExitStatus.FAILED.getExitCode(), "end0"));
transitions.add(StateTransition.createStateTransition(state2, ExitStatus.COMPLETED.getExitCode(), "end1"));
transitions.add(StateTransition.createStateTransition(new EndState(FlowExecutionStatus.STOPPED, "end0"),
"step3"));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1")));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step3")), "end2"));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end2")));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
@@ -194,20 +171,15 @@ public class FlowJobTests {
public void testEndStateStopped() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
List<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step1")), "end"));
transitions.add(StateTransition.createStateTransition(new EndState(
BatchStatus.STOPPED, ExitStatus.STOPPED, "end"), "step2"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end"));
transitions.add(StateTransition
.createStateTransition(new StepState(new StubStep("step2")),
ExitStatus.FAILED.getExitCode(), "end0"));
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step2")), ExitStatus.COMPLETED.getExitCode(),
"end1"));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.FAILED, ExitStatus.FAILED, "end0")));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.COMPLETED, ExitStatus.COMPLETED, "end1")));
.createStateTransition(new EndState(FlowExecutionStatus.STOPPED, "end"), "step2"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), ExitStatus.FAILED
.getExitCode(), "end0"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")),
ExitStatus.COMPLETED.getExitCode(), "end1"));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end0")));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1")));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
@@ -219,20 +191,15 @@ public class FlowJobTests {
public void testEndStateFailed() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
List<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step1")), "end"));
transitions.add(StateTransition.createStateTransition(new EndState(
BatchStatus.FAILED, ExitStatus.FAILED, "end"), "step2"));
transitions.add(StateTransition
.createStateTransition(new StepState(new StubStep("step2")),
ExitStatus.FAILED.getExitCode(), "end0"));
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step2")), ExitStatus.COMPLETED.getExitCode(),
"end1"));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.FAILED, ExitStatus.FAILED, "end0")));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.COMPLETED, ExitStatus.COMPLETED, "end1")));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end"));
transitions
.add(StateTransition.createStateTransition(new EndState(FlowExecutionStatus.FAILED, "end"), "step2"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), ExitStatus.FAILED
.getExitCode(), "end0"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")),
ExitStatus.COMPLETED.getExitCode(), "end1"));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end0")));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1")));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
@@ -245,20 +212,15 @@ public class FlowJobTests {
public void testEndStateStoppedWithRestart() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
List<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step1")), "end"));
transitions.add(StateTransition.createStateTransition(new EndState(
BatchStatus.STOPPED, ExitStatus.STOPPED, "end"), "step2"));
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step2")), ExitStatus.COMPLETED.getExitCode(),
"end0"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end"));
transitions.add(StateTransition
.createStateTransition(new StepState(new StubStep("step2")),
ExitStatus.FAILED.getExitCode(), "end1"));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.COMPLETED, ExitStatus.COMPLETED, "end0")));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.FAILED, ExitStatus.FAILED, "end1")));
.createStateTransition(new EndState(FlowExecutionStatus.STOPPED, "end"), "step2"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")),
ExitStatus.COMPLETED.getExitCode(), "end0"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), ExitStatus.FAILED
.getExitCode(), "end1"));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0")));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end1")));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
@@ -268,8 +230,7 @@ public class FlowJobTests {
assertEquals(BatchStatus.STOPPED, jobExecution.getStatus());
assertEquals(1, jobExecution.getStepExecutions().size());
jobExecution = jobRepository.createJobExecution("job",
new JobParameters());
jobExecution = jobRepository.createJobExecution("job", new JobParameters());
job.execute(jobExecution);
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
assertEquals(1, jobExecution.getStepExecutions().size());
@@ -280,30 +241,21 @@ public class FlowJobTests {
public void testBranching() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
List<StateTransition> transitions = new ArrayList<StateTransition>();
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("step2")), ExitStatus.COMPLETED.getExitCode(),
"end0"));
transitions.add(StateTransition
.createStateTransition(new StepState(new StubStep("step2")),
ExitStatus.FAILED.getExitCode(), "end1"));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.COMPLETED, ExitStatus.COMPLETED, "end0")));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.FAILED, ExitStatus.FAILED, "end1")));
transitions.add(StateTransition
.createStateTransition(new StepState(new StubStep("step3")),
ExitStatus.FAILED.getExitCode(), "end2"));
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step3")), ExitStatus.COMPLETED.getExitCode(),
"end3"));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.FAILED, ExitStatus.FAILED, "end2")));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.COMPLETED, ExitStatus.COMPLETED, "end3")));
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("step2")),
ExitStatus.COMPLETED.getExitCode(), "end0"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), ExitStatus.FAILED
.getExitCode(), "end1"));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0")));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end1")));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step3")), ExitStatus.FAILED
.getExitCode(), "end2"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step3")),
ExitStatus.COMPLETED.getExitCode(), "end3"));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end2")));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end3")));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.afterPropertiesSet();
@@ -317,10 +269,8 @@ public class FlowJobTests {
public void testBasicFlow() throws Throwable {
SimpleFlow flow = new SimpleFlow("job");
List<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step")), "end0"));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.COMPLETED, ExitStatus.COMPLETED, "end0")));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step")), "end0"));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0")));
flow.setStateTransitions(transitions);
job.setFlow(flow);
job.execute(jobExecution);
@@ -335,40 +285,29 @@ public class FlowJobTests {
SimpleFlow flow = new SimpleFlow("job");
JobExecutionDecider decider = new JobExecutionDecider() {
public String decide(JobExecution jobExecution,
StepExecution stepExecution) {
public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {
assertNotNull(stepExecution);
return "SWITCH";
return new FlowExecutionStatus("SWITCH");
}
};
List<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step1")), "decision"));
transitions.add(StateTransition.createStateTransition(
new DecisionState(decider, "decision"), "step2"));
transitions.add(StateTransition.createStateTransition(
new DecisionState(decider, "decision"), "SWITCH", "step3"));
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step2")), ExitStatus.COMPLETED.getExitCode(),
"end0"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "decision"));
transitions.add(StateTransition.createStateTransition(new DecisionState(decider, "decision"), "step2"));
transitions.add(StateTransition
.createStateTransition(new StepState(new StubStep("step2")),
ExitStatus.FAILED.getExitCode(), "end1"));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.COMPLETED, ExitStatus.COMPLETED, "end0")));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.FAILED, ExitStatus.FAILED, "end1")));
transitions.add(StateTransition
.createStateTransition(new StepState(new StubStep("step3")),
ExitStatus.FAILED.getExitCode(), "end2"));
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step3")), ExitStatus.COMPLETED.getExitCode(),
"end3"));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.FAILED, ExitStatus.FAILED, "end2")));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.COMPLETED, ExitStatus.COMPLETED, "end3")));
.createStateTransition(new DecisionState(decider, "decision"), "SWITCH", "step3"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")),
ExitStatus.COMPLETED.getExitCode(), "end0"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), ExitStatus.FAILED
.getExitCode(), "end1"));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0")));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end1")));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step3")), ExitStatus.FAILED
.getExitCode(), "end2"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step3")),
ExitStatus.COMPLETED.getExitCode(), "end3"));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end2")));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end3")));
flow.setStateTransitions(transitions);
job.setFlow(flow);
@@ -387,12 +326,9 @@ public class FlowJobTests {
public void testGetStepExists() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
List<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step1")), "step2"));
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step2")), "end0"));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.COMPLETED, ExitStatus.COMPLETED, "end0")));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), "end0"));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0")));
flow.setStateTransitions(transitions);
flow.afterPropertiesSet();
job.setFlow(flow);
@@ -407,12 +343,9 @@ public class FlowJobTests {
public void testGetStepNotExists() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
List<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step1")), "step2"));
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step2")), "end0"));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.COMPLETED, ExitStatus.COMPLETED, "end0")));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), "end0"));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0")));
flow.setStateTransitions(transitions);
flow.afterPropertiesSet();
job.setFlow(flow);
@@ -426,12 +359,9 @@ public class FlowJobTests {
public void testGetStepNotStepState() throws Exception {
SimpleFlow flow = new SimpleFlow("job");
List<StateTransition> transitions = new ArrayList<StateTransition>();
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step1")), "step2"));
transitions.add(StateTransition.createStateTransition(new StepState(
new StubStep("step2")), "end0"));
transitions.add(StateTransition.createEndStateTransition(new EndState(
BatchStatus.COMPLETED, ExitStatus.COMPLETED, "end0")));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2"));
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), "end0"));
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0")));
flow.setStateTransitions(transitions);
flow.afterPropertiesSet();
job.setFlow(flow);
@@ -451,8 +381,7 @@ public class FlowJobTests {
super(name);
}
public void execute(StepExecution stepExecution)
throws JobInterruptedException {
public void execute(StepExecution stepExecution) throws JobInterruptedException {
stepExecution.setStatus(BatchStatus.COMPLETED);
stepExecution.setExitStatus(ExitStatus.COMPLETED);
jobRepository.update(stepExecution);
@@ -465,8 +394,7 @@ public class FlowJobTests {
* @param stepName
* @return the StepExecution corresponding to the specified step
*/
private StepExecution getStepExecution(JobExecution jobExecution,
String stepName) {
private StepExecution getStepExecution(JobExecution jobExecution, String stepName) {
for (StepExecution stepExecution : jobExecution.getStepExecutions()) {
if (stepExecution.getStepName().equals(stepName)) {
return stepExecution;

View File

@@ -17,13 +17,10 @@ package org.springframework.batch.core.job.flow;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
import org.springframework.batch.core.job.flow.FlowExecutor;
import org.springframework.batch.core.job.flow.State;
import org.springframework.batch.core.job.flow.support.state.AbstractState;
/**
* Base class for {@link State} implementations.
* Base class for {@link State} implementations in test cases.
*
* @author Dave Syer
*
@@ -49,7 +46,9 @@ public class StateSupport extends AbstractState {
}
return this.status;
}
public void validate(String pattern, String nextState) {
public boolean isEndState() {
return false;
}
}

View File

@@ -22,6 +22,7 @@ import org.springframework.batch.core.StartLimitExceededException;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.job.flow.FlowExecution;
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
import org.springframework.batch.core.job.flow.FlowExecutor;
import org.springframework.batch.core.repository.JobRestartException;
@@ -31,8 +32,6 @@ import org.springframework.batch.core.repository.JobRestartException;
*/
public class JobFlowExecutorSupport implements FlowExecutor {
private volatile boolean nested = false;
public String executeStep(Step step) throws JobInterruptedException, JobRestartException,
StartLimitExceededException {
return ExitStatus.COMPLETED.getExitCode();
@@ -49,19 +48,10 @@ public class JobFlowExecutorSupport implements FlowExecutor {
public void close(FlowExecution result) {
}
public void updateStepExecutionStatus() {
public void abandonStepExecution() {
}
public boolean isNested() {
return nested;
}
public void nest() {
nested= true;
}
public void unnest() {
nested = false;
public void updateJobExecutionStatus(FlowExecutionStatus status) {
}
}

View File

@@ -20,11 +20,10 @@ import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
import org.springframework.batch.core.job.flow.FlowExecutor;
import org.springframework.batch.core.job.flow.support.JobFlowExecutorSupport;
import org.springframework.batch.core.job.flow.support.state.EndState;
/**
* @author Dave Syer
@@ -48,7 +47,7 @@ public class EndStateTests {
BatchStatus status = jobExecution.getStatus();
EndState state = new EndState(BatchStatus.UNKNOWN, ExitStatus.UNKNOWN, "end");
EndState state = new EndState(FlowExecutionStatus.UNKNOWN, "end");
state.handle(new JobFlowExecutorSupport() {
@Override
public JobExecution getJobExecution() {
@@ -69,38 +68,15 @@ public class EndStateTests {
jobExecution.createStepExecution("foo");
EndState state = new EndState(BatchStatus.UNKNOWN, ExitStatus.UNKNOWN, "end");
state.handle(new JobFlowExecutorSupport() {
EndState state = new EndState(FlowExecutionStatus.UNKNOWN, "end");
FlowExecutionStatus status = state.handle(new JobFlowExecutorSupport() {
@Override
public JobExecution getJobExecution() {
return jobExecution;
}
});
assertEquals(BatchStatus.UNKNOWN, jobExecution.getStatus());
}
/**
* Test method for {@link EndState#handle(FlowExecutor)}.
* @throws Exception
*/
@Test
public void testHandleOngoingAttemptedDowngrade() throws Exception {
jobExecution.setStatus(BatchStatus.FAILED);
jobExecution.createStepExecution("foo");
EndState state = new EndState(BatchStatus.COMPLETED, ExitStatus.COMPLETED, "end");
state.handle(new JobFlowExecutorSupport() {
@Override
public JobExecution getJobExecution() {
return jobExecution;
}
});
// An EndState can downgrade a status - if it failed then it can be unfailed
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
assertEquals(FlowExecutionStatus.UNKNOWN, status);
}

View File

@@ -11,7 +11,7 @@
<job id="job">
<step id="s1" ref="step1" next="fail"/>
<step id="fail" ref="failingStep">
<end on="*" status="EARLY TERMINATION (FAIL)"/>
<end on="*" status="COMPLETED EARLY TERMINATION"/>
</step>
</job>

View File

@@ -11,7 +11,7 @@
<job id="job">
<step id="s1" ref="step1" next="fail"/>
<step id="fail" ref="failingStep">
<fail on="FAILED" status="EARLY TERMINATION (FAIL)"/>
<fail on="FAILED" status="FAILED EARLY TERMINATION"/>
</step>
</job>

View File

@@ -17,6 +17,7 @@ package org.springframework.batch.sample.loopFlow;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
import org.springframework.batch.core.job.flow.JobExecutionDecider;
/**
@@ -37,12 +38,12 @@ public class LimitDecider implements JobExecutionDecider {
* @see org.springframework.batch.core.job.flow.support.state.JobExecutionDecider#decide(org.springframework.batch.core.JobExecution,
* org.springframework.batch.core.StepExecution)
*/
public String decide(JobExecution jobExecution, StepExecution stepExecution) {
public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {
if (++count >= limit) {
return "COMPLETE";
return new FlowExecutionStatus("COMPLETE");
}
else {
return "CONTINUE";
return new FlowExecutionStatus("CONTINUE");
}
}

View File

@@ -3,17 +3,18 @@ package org.springframework.batch.sample.common;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
import org.springframework.batch.core.job.flow.JobExecutionDecider;
public class SkipCheckingDecider implements JobExecutionDecider {
public String decide(JobExecution jobExecution, StepExecution stepExecution) {
public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {
if (!stepExecution.getExitStatus().getExitCode().equals(
ExitStatus.FAILED.getExitCode())
&& stepExecution.getSkipCount() > 0) {
return "COMPLETED WITH SKIPS";
return new FlowExecutionStatus("COMPLETED WITH SKIPS");
} else {
return ExitStatus.COMPLETED.getExitCode();
return new FlowExecutionStatus(ExitStatus.COMPLETED.getExitCode());
}
}
}