BATCH-1923: add stop() methods to FlowBuilder

This commit is contained in:
Dave Syer
2012-12-17 10:33:34 +00:00
parent a65cc58117
commit 7b42d2c2af
2 changed files with 130 additions and 6 deletions

View File

@@ -66,10 +66,14 @@ public class FlowBuilder<Q> {
private EndState completedState;
private EndState stoppedState;
private int decisionCounter = 0;
private int splitCounter = 0;
private int endCounter = 0;
private Map<Object, State> states = new HashMap<Object, State>();
private SimpleFlow flow;
@@ -81,6 +85,7 @@ public class FlowBuilder<Q> {
this.prefix = name + ".";
this.failedState = new EndState(FlowExecutionStatus.FAILED, prefix + "FAILED");
this.completedState = new EndState(FlowExecutionStatus.COMPLETED, prefix + "COMPLETED");
this.stoppedState = new EndState(FlowExecutionStatus.STOPPED, prefix + "STOPPED");
}
/**
@@ -325,10 +330,8 @@ public class FlowBuilder<Q> {
for (String to : copy.keySet()) {
if (!froms.contains(to)) {
currentState = copy.get(to);
if (currentState != completedState) {
if (!currentState.isEndState()) {
addTransition("COMPLETED", completedState);
}
if (currentState != failedState) {
addTransition("*", failedState);
}
}
@@ -337,12 +340,10 @@ public class FlowBuilder<Q> {
// Then find the states that do not have a default transition
for (String from : copy.keySet()) {
currentState = copy.get(from);
if (currentState != failedState) {
if (!currentState.isEndState()) {
if (!hasFail(from)) {
addTransition("*", failedState);
}
}
if (currentState != completedState) {
if (!hasCompleted(from)) {
addTransition("*", completedState);
}
@@ -373,14 +374,33 @@ public class FlowBuilder<Q> {
if (transitions.size() == 1) {
transitions.add(StateTransition.createEndStateTransition(failedState));
transitions.add(StateTransition.createEndStateTransition(completedState));
transitions.add(StateTransition.createEndStateTransition(stoppedState));
}
if (next.isEndState()) {
transitions.add(StateTransition.createEndStateTransition(next));
}
dirty = true;
}
private void stop(String pattern) {
addTransition(pattern, stoppedState);
}
private void stop(String pattern, State restart) {
EndState next = new EndState(FlowExecutionStatus.STOPPED, "STOPPED", prefix + "stop" + (endCounter++), true);
addTransition(pattern, next);
currentState = next;
addTransition("*", restart);
}
private void end(String pattern) {
addTransition(pattern, completedState);
}
private void end(String pattern, String code) {
addTransition(pattern, new EndState(FlowExecutionStatus.COMPLETED, code, prefix + "end" + (endCounter++)));
}
private void fail(String pattern) {
addTransition(pattern, failedState);
}
@@ -471,6 +491,52 @@ public class FlowBuilder<Q> {
return parent;
}
/**
* Signal the successful end of the flow.
*
* @return a FlowBuilder
*/
public FlowBuilder<Q> stop() {
parent.stop(pattern);
return parent;
}
/**
* Stop the flow and provide a flow to start with if the flow is restarted.
*
* @param flow the flow to restart with
* @return a FlowBuilder
*/
public FlowBuilder<Q> stopAndRestart(Flow flow) {
State next = parent.createState(flow);
parent.stop(pattern, next);
return parent;
}
/**
* Stop the flow and provide a decider to start with if the flow is restarted.
*
* @param restart a decider to restart with
* @return a FlowBuilder
*/
public FlowBuilder<Q> stopAndRestart(JobExecutionDecider decider) {
State next = parent.createState(decider);
parent.stop(pattern, next);
return parent;
}
/**
* Stop the flow and provide a step to start with if the flow is restarted.
*
* @param restart the step to restart with
* @return a FlowBuilder
*/
public FlowBuilder<Q> stopAndRestart(Step restart) {
State next = parent.createState(restart);
parent.stop(pattern, next);
return parent;
}
/**
* Signal the successful end of the flow.
*
@@ -481,6 +547,16 @@ public class FlowBuilder<Q> {
return parent;
}
/**
* Signal the end of the flow with the status provided.
*
* @return a FlowBuilder
*/
public FlowBuilder<Q> end(String status) {
parent.end(pattern, status);
return parent;
}
/**
* Signal the end of the flow with an error condition.
*

View File

@@ -21,6 +21,7 @@ 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.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInterruptedException;
import org.springframework.batch.core.JobParameters;
@@ -54,6 +55,16 @@ public class FlowJobBuilderTests {
}
};
private StepSupport fails = new StepSupport("fails") {
@Override
public void execute(StepExecution stepExecution) throws JobInterruptedException,
UnexpectedJobExecutionException {
stepExecution.upgradeStatus(BatchStatus.FAILED);
stepExecution.setExitStatus(ExitStatus.FAILED);
jobRepository.update(stepExecution);
}
};
private StepSupport step2 = new StepSupport("step2") {
@Override
public void execute(StepExecution stepExecution) throws JobInterruptedException,
@@ -164,4 +175,41 @@ public class FlowJobBuilderTests {
assertEquals(2, execution.getStepExecutions().size());
}
@Test
public void testBuildWithCustomEndState() throws Exception {
SimpleJobBuilder builder = new JobBuilder("flow").repository(jobRepository).start(step1);
builder.on("COMPLETED").end("FOO");
builder.preventRestart();
builder.build().execute(execution);
assertEquals(BatchStatus.COMPLETED, execution.getStatus());
assertEquals("FOO", execution.getExitStatus().getExitCode());
assertEquals(1, execution.getStepExecutions().size());
}
@Test
public void testBuildWithStop() throws Exception {
SimpleJobBuilder builder = new JobBuilder("flow").repository(jobRepository).start(step1);
builder.on("COMPLETED").stop();
builder.preventRestart();
builder.build().execute(execution);
assertEquals(BatchStatus.STOPPED, execution.getStatus());
assertEquals("STOPPED", execution.getExitStatus().getExitCode());
assertEquals(1, execution.getStepExecutions().size());
}
@Test
public void testBuildWithStopAndRestart() throws Exception {
SimpleJobBuilder builder = new JobBuilder("flow").repository(jobRepository).start(fails);
builder.on("FAILED").stopAndRestart(step2);
Job job = builder.build();
job.execute(execution);
assertEquals(BatchStatus.STOPPED, execution.getStatus());
assertEquals(1, execution.getStepExecutions().size());
execution = jobRepository.createJobExecution("flow", new JobParameters());
job.execute(execution);
assertEquals(BatchStatus.COMPLETED, execution.getStatus());
assertEquals(1, execution.getStepExecutions().size());
assertEquals("step2", execution.getStepExecutions().iterator().next().getStepName());
}
}