From 7c4953f2bedbef7774d295fe683437c923b68065 Mon Sep 17 00:00:00 2001 From: dhgarrette Date: Sun, 8 Feb 2009 18:32:03 +0000 Subject: [PATCH] BATCH-1067: * FlowJob waits until the Job is finished before updating BatchStatus and ExitStatus. This is required so that individual flows in a split don't modifify the JobExecution prematurely. * Removed FlowExecution$Status and replaced it with FlowExecutionStatus, a class that holds both a BatchStatus and an ExitStatus. This is required by the EndState because the handle() method needs to be able to return both BatchStatus and ExitStatus so that they can be applied correctly to the JobExecution when ending the job. --- .../batch/core/BatchStatus.java | 18 +++ .../batch/core/job/flow/FlowExecution.java | 66 +++------ .../core/job/flow/FlowExecutionStatus.java | 135 ++++++++++++++++++ .../batch/core/job/flow/FlowJob.java | 11 +- .../core/job/flow/support/SimpleFlow.java | 13 +- .../batch/core/job/flow/support/State.java | 5 +- .../job/flow/support/state/AbstractState.java | 3 +- .../job/flow/support/state/DecisionState.java | 6 +- .../core/job/flow/support/state/EndState.java | 23 ++- .../state/FlowExecutionAggregator.java | 3 +- .../MaxValueFlowExecutionAggregator.java | 13 +- .../job/flow/support/state/SplitState.java | 3 +- .../job/flow/support/state/StepState.java | 5 +- ...ferentResultsFailSecondJobParserTests.java | 11 +- .../core/job/flow/FlowExecutionTests.java | 6 +- .../flow/support/JobFlowExecutorSupport.java | 5 +- .../job/flow/support/SimpleFlowTests.java | 60 +++----- .../core/job/flow/support/StateSupport.java | 7 +- .../job/flow/support/state/EndStateTests.java | 2 +- .../SimpleFlowExecutionAggregatorTests.java | 10 +- .../flow/support/state/SplitStateTests.java | 18 +-- ...esultsFailSecondJobParserTests-context.xml | 4 + 22 files changed, 270 insertions(+), 157 deletions(-) create mode 100644 spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecutionStatus.java diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/BatchStatus.java b/spring-batch-core/src/main/java/org/springframework/batch/core/BatchStatus.java index 86f8c7915..92d1c6793 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/BatchStatus.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/BatchStatus.java @@ -16,6 +16,7 @@ package org.springframework.batch.core; + /** * Enumeration representing the status of a an Execution. * @@ -115,4 +116,21 @@ public enum BatchStatus { return this.compareTo(other) <= 0; } + /** + * Find a BatchStatus that matches the beginning of the given value. If + * no match is found, return COMPLETED as the default because has is low + * precedence. + * + * @param value a string representing a status + * @return a BatchStatus + */ + public static BatchStatus match(String value) { + for (BatchStatus status : values()) { + if (value.startsWith(status.toString())) { + return status; + } + } + // Default match should be the lowest priority + return COMPLETED; + } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecution.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecution.java index 0e92b9b09..778698a6d 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecution.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecution.java @@ -15,61 +15,35 @@ */ package org.springframework.batch.core.job.flow; + /** * @author Dave Syer * */ public class FlowExecution implements Comparable { - /** - * Special well-known status value. - */ - public static final String COMPLETED = Status.COMPLETED.toString(); - - /** - * Special well-known status value. - */ - public static final String PAUSED = Status.PAUSED.toString(); - - /** - * Special well-known status value. - */ - public static final String FAILED = Status.FAILED.toString(); - - /** - * Special well-known status value. - */ - public static final String UNKNOWN = Status.UNKNOWN.toString(); - private final String name; - - private final String status; - - private enum Status { - - COMPLETED, PAUSED, FAILED, UNKNOWN; - - static Status match(String value) { - for (int i = 0; i < values().length; i++) { - Status status = values()[i]; - if (value.startsWith(status.toString())) { - return status; - } - } - // Default match should be the lowest priority - return COMPLETED; - } - - }; + private final FlowExecutionStatus status; /** - * + * @param name + * @param status */ - public FlowExecution(String name, String status) { + public FlowExecution(String name, FlowExecutionStatus status) { this.name = name; this.status = status; } + /** + * Convenience constructor that converts a String status to a {@link FlowExecutionStatus}. + * + * @param name + * @param status + */ + public FlowExecution(String name, String status) { + this(name, new FlowExecutionStatus(status)); + } + /** * @return the name of the end state reached */ @@ -80,7 +54,7 @@ public class FlowExecution implements Comparable { /** * @return the exit status */ - public String getStatus() { + public FlowExecutionStatus getStatus() { return status; } @@ -94,13 +68,7 @@ public class FlowExecution implements Comparable { * @return negative, zero or positive as per the contract */ public int compareTo(FlowExecution other) { - Status one = Status.match(this.getStatus()); - Status two = Status.match(other.getStatus()); - int comparison = one.compareTo(two); - if (comparison==0) { - return this.getStatus().compareTo(other.getStatus()); - } - return comparison; + return this.status.compareTo(other.getStatus()); } @Override diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecutionStatus.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecutionStatus.java new file mode 100644 index 000000000..b32f18a5c --- /dev/null +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecutionStatus.java @@ -0,0 +1,135 @@ +/* + * 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.job.flow; + +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; + +/** + * This class is used as a holder for a BatchStatus/ExitStatus pair. + * + * @author Dan Garrette + * @since 2.0 + */ +public class FlowExecutionStatus implements Comparable { + + private final String status; + private final ExitStatus exitStatus; + + /** + * Special well-known status value. + */ + public static final FlowExecutionStatus COMPLETED = new FlowExecutionStatus(BatchStatus.COMPLETED, + ExitStatus.COMPLETED); + + /** + * Special well-known status value. + */ + public static final FlowExecutionStatus STOPPED = new FlowExecutionStatus(BatchStatus.STOPPED, ExitStatus.FAILED); + + /** + * Special well-known status value. + */ + public static final FlowExecutionStatus FAILED = new FlowExecutionStatus(BatchStatus.FAILED, ExitStatus.FAILED); + + /** + * Special well-known status value. + */ + public static final FlowExecutionStatus UNKNOWN = new FlowExecutionStatus(BatchStatus.UNKNOWN, ExitStatus.UNKNOWN); + + /** + * @param status + */ + public FlowExecutionStatus(String status) { + this(status, null); + } + + /** + * @param status + * @param exitStatus + */ + public FlowExecutionStatus(String status, ExitStatus exitStatus) { + this.status = status; + this.exitStatus = exitStatus; + } + + /** + * Convenience constructor that accepts a {@link BatchStatus} and + * {@link ExitStatus}. + * + * @param batchStatus + * @param exitStatus + */ + public FlowExecutionStatus(BatchStatus batchStatus, ExitStatus exitStatus) { + this(batchStatus.toString(), exitStatus); + } + + /** + * Convenience getter for the {@link BatchStatus}. + * + * @return a {@link BatchStatus} representing the status + */ + public BatchStatus getBatchStatus() { + return BatchStatus.match(status); + } + + /** + * Create an ordering on {@link FlowExecutionStatus} instances by comparing + * their statuses. + * + * @see Comparable#compareTo(Object) + * + * @param other + * @return negative, zero or positive as per the contract + */ + public int compareTo(FlowExecutionStatus other) { + BatchStatus one = this.getBatchStatus(); + BatchStatus two = other.getBatchStatus(); + int comparison = one.compareTo(two); + if (comparison == 0) { + return status.compareTo(other.getStatus()); + } + return comparison; + } + + /** + * Check the equality of the statuses. + * + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object other) { + if (other == this) { + return true; + } + if (!(other instanceof FlowExecutionStatus)) { + return false; + } + FlowExecutionStatus flowExecutionStatus = (FlowExecutionStatus) other; + return status.equals(flowExecutionStatus.getStatus()); + } + + public String toString() { + return "FlowExecutionStatus: status=[" + status + "] exitstatus=[" + exitStatus + "]"; + } + + public String getStatus() { + return status; + } + + public ExitStatus getExitStatus() { + return exitStatus; + } +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowJob.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowJob.java index feda8ff0b..f261fab2c 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowJob.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowJob.java @@ -16,6 +16,7 @@ package org.springframework.batch.core.job.flow; import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobExecutionException; import org.springframework.batch.core.JobInterruptedException; @@ -76,7 +77,13 @@ public class FlowJob extends AbstractJob { @Override protected void doExecute(final JobExecution execution) throws JobExecutionException { try { - flow.start(new JobFlowExecutor(execution)); + FlowExecution flowExecution = flow.start(new JobFlowExecutor(execution)); + + synchronized (execution) { + FlowExecutionStatus status = flowExecution.getStatus(); + execution.upgradeStatus(status.getBatchStatus()); + execution.setExitStatus(status.getExitStatus()); + } } catch (FlowExecutionException e) { if (e.getCause() instanceof JobExecutionException) { @@ -111,7 +118,7 @@ public class FlowJob extends AbstractJob { } StepExecution stepExecution = handleStep(step, execution); stepExecutionHolder.set(stepExecution); - return stepExecution==null ? FlowExecution.COMPLETED : stepExecution.getExitStatus().getExitCode(); + return stepExecution==null ? ExitStatus.COMPLETED.getExitCode() : stepExecution.getExitStatus().getExitCode(); } public JobExecution getJobExecution() { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/SimpleFlow.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/SimpleFlow.java index 28fb04ff4..2f78cb394 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/SimpleFlow.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/SimpleFlow.java @@ -28,6 +28,7 @@ import org.springframework.batch.core.Step; import org.springframework.batch.core.job.flow.Flow; import org.springframework.batch.core.job.flow.FlowExecution; import org.springframework.batch.core.job.flow.FlowExecutionException; +import org.springframework.batch.core.job.flow.FlowExecutionStatus; import org.springframework.batch.core.job.flow.FlowExecutor; import org.springframework.beans.factory.InitializingBean; @@ -115,7 +116,7 @@ public class SimpleFlow implements Flow, InitializingBean { */ public FlowExecution resume(String stateName, FlowExecutor executor) throws FlowExecutionException { - String status = FlowExecution.UNKNOWN; + FlowExecutionStatus status = FlowExecutionStatus.UNKNOWN; State state = stateMap.get(stateName); // Terminate if there are no more states @@ -146,13 +147,7 @@ public class SimpleFlow implements Flow, InitializingBean { * @return the next {@link Step} (or null if this is the end) * @throws JobExecutionException */ - private State nextState(String stateName, String status) throws FlowExecutionException { - - // Special status value indicating that a state wishes to pause - // execution - if (status.equals(FlowExecution.PAUSED)) { - return null; - } + private State nextState(String stateName, FlowExecutionStatus status) throws FlowExecutionException { Set set = transitionMap.get(stateName); @@ -163,7 +158,7 @@ public class SimpleFlow implements Flow, InitializingBean { String next = null; for (StateTransition stateTransition : set) { - if (stateTransition.matches(status)) { + if (stateTransition.matches(status.getStatus())) { if (stateTransition.isEnd()) { // End of job return null; diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/State.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/State.java index be00a7a2f..f340173f8 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/State.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/State.java @@ -16,6 +16,7 @@ package org.springframework.batch.core.job.flow.support; import org.springframework.batch.core.job.flow.FlowExecution; +import org.springframework.batch.core.job.flow.FlowExecutionStatus; import org.springframework.batch.core.job.flow.FlowExecutor; @@ -42,9 +43,9 @@ public interface State { * context is thread safe, or used in a thread safe manner. * * @param executor the context passed in by the caller - * @return a status for the execution + * @return a {@link FlowExecutionStatus} for the execution * @throws Exception if anything goes wrong */ - String handle(FlowExecutor executor) throws Exception; + FlowExecutionStatus handle(FlowExecutor executor) throws Exception; } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/AbstractState.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/AbstractState.java index 2fe14db1d..518066be5 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/AbstractState.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/AbstractState.java @@ -15,6 +15,7 @@ */ package org.springframework.batch.core.job.flow.support.state; +import org.springframework.batch.core.job.flow.FlowExecutionStatus; import org.springframework.batch.core.job.flow.FlowExecutor; import org.springframework.batch.core.job.flow.support.State; @@ -46,6 +47,6 @@ public abstract class AbstractState implements State { return getClass().getSimpleName()+": name=["+name+"]"; } - public abstract String handle(FlowExecutor executor) throws Exception; + public abstract FlowExecutionStatus handle(FlowExecutor executor) throws Exception; } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/DecisionState.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/DecisionState.java index 19240aa33..53c152cf6 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/DecisionState.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/DecisionState.java @@ -16,10 +16,10 @@ package org.springframework.batch.core.job.flow.support.state; +import org.springframework.batch.core.job.flow.FlowExecutionStatus; import org.springframework.batch.core.job.flow.FlowExecutor; import org.springframework.batch.core.job.flow.JobExecutionDecider; - /** * @author Dave Syer * @@ -37,8 +37,8 @@ public class DecisionState extends AbstractState { } @Override - public String handle(FlowExecutor executor) throws Exception { - return decider.decide(executor.getJobExecution(), executor.getStepExecution()); + public FlowExecutionStatus handle(FlowExecutor executor) throws Exception { + return new FlowExecutionStatus(decider.decide(executor.getJobExecution(), executor.getStepExecution())); } } \ No newline at end of file diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/EndState.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/EndState.java index 2e58379b0..ae8d5e262 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/EndState.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/EndState.java @@ -19,7 +19,7 @@ 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.FlowExecution; +import org.springframework.batch.core.job.flow.FlowExecutionStatus; import org.springframework.batch.core.job.flow.FlowExecutor; import org.springframework.batch.core.job.flow.support.State; @@ -57,32 +57,25 @@ public class EndState extends AbstractState { } /** - * 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). + * Return the {@link BatchStatus} and {@link ExitStatus} stored. If the + * {@link BatchStatus} is {@link BatchStatus#STOPPED}, then mark it on the + * {@link JobExecution} so that the job will know to stop. * * @see State#handle(FlowExecutor) */ @Override - public String handle(FlowExecutor executor) throws Exception { + public FlowExecutionStatus handle(FlowExecutor executor) throws Exception { JobExecution jobExecution = executor.getJobExecution(); // If there are no step executions, then we are at the beginning of a // restart synchronized (jobExecution) { if (!jobExecution.getStepExecutions().isEmpty()) { - BatchStatus beforeStatus = jobExecution.getStatus(); - - jobExecution.upgradeStatus(status); - - // - // If the status was changed or the target status is the same as the old - // - if(beforeStatus != jobExecution.getStatus() || beforeStatus == status) - { + if (status == BatchStatus.STOPPED) { + jobExecution.upgradeStatus(status); jobExecution.setExitStatus(exitStatus); } } - return FlowExecution.COMPLETED; + return new FlowExecutionStatus(status, exitStatus); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/FlowExecutionAggregator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/FlowExecutionAggregator.java index 0f0167964..1bba9e9e1 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/FlowExecutionAggregator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/FlowExecutionAggregator.java @@ -18,6 +18,7 @@ package org.springframework.batch.core.job.flow.support.state; import java.util.Collection; import org.springframework.batch.core.job.flow.FlowExecution; +import org.springframework.batch.core.job.flow.FlowExecutionStatus; /** * Strategy interface for aggregating {@link FlowExecution} instances into a @@ -32,6 +33,6 @@ public interface FlowExecutionAggregator { * @param executions the executions to aggregate * @return a summary status for the whole lot */ - String aggregate(Collection executions); + FlowExecutionStatus aggregate(Collection executions); } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/MaxValueFlowExecutionAggregator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/MaxValueFlowExecutionAggregator.java index 24a39ceff..6cff4d912 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/MaxValueFlowExecutionAggregator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/MaxValueFlowExecutionAggregator.java @@ -19,19 +19,24 @@ import java.util.Collection; import java.util.Collections; import org.springframework.batch.core.job.flow.FlowExecution; +import org.springframework.batch.core.job.flow.FlowExecutionStatus; /** * @author Dave Syer - * + * */ public class MaxValueFlowExecutionAggregator implements FlowExecutionAggregator { /** + * Aggregate all of the {@link FlowExecutionStatus}es of the + * {@link FlowExecution}s into one status. The aggregate status will be the + * status with the highest precedence. + * * @see FlowExecutionAggregator#aggregate(Collection) */ - public String aggregate(Collection executions) { - if (executions==null || executions.size()==0) { - return FlowExecution.UNKNOWN; + public FlowExecutionStatus aggregate(Collection executions) { + if (executions == null || executions.size() == 0) { + return FlowExecutionStatus.UNKNOWN; } return Collections.max(executions).getStatus(); } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/SplitState.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/SplitState.java index 2097cfa3d..1d07216d9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/SplitState.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/SplitState.java @@ -24,6 +24,7 @@ import java.util.concurrent.FutureTask; import org.springframework.batch.core.job.flow.Flow; import org.springframework.batch.core.job.flow.FlowExecution; import org.springframework.batch.core.job.flow.FlowExecutionException; +import org.springframework.batch.core.job.flow.FlowExecutionStatus; import org.springframework.batch.core.job.flow.FlowExecutor; import org.springframework.batch.core.job.flow.support.State; import org.springframework.core.task.SyncTaskExecutor; @@ -68,7 +69,7 @@ public class SplitState extends AbstractState { * @see State#handle(FlowExecutor) */ @Override - public String handle(final FlowExecutor executor) throws Exception { + public FlowExecutionStatus handle(final FlowExecutor executor) throws Exception { Collection> tasks = new ArrayList>(); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/StepState.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/StepState.java index 90c2ef781..288267605 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/StepState.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/StepState.java @@ -17,6 +17,7 @@ package org.springframework.batch.core.job.flow.support.state; import org.springframework.batch.core.Step; +import org.springframework.batch.core.job.flow.FlowExecutionStatus; import org.springframework.batch.core.job.flow.FlowExecutor; import org.springframework.batch.core.job.flow.support.State; @@ -49,8 +50,8 @@ public class StepState extends AbstractState { } @Override - public String handle(FlowExecutor executor) throws Exception { - return executor.executeStep(step); + public FlowExecutionStatus handle(FlowExecutor executor) throws Exception { + return new FlowExecutionStatus(executor.executeStep(step)); } /** diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests.java index e66b1d1ed..87cbe8152 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests.java @@ -40,12 +40,13 @@ public class SplitDifferentResultsFailSecondJobParserTests extends AbstractJobPa JobExecution jobExecution = createJobExecution(); job.execute(jobExecution); - assertEquals(2, stepNamesList.size()); + assertEquals(3, stepNamesList.size()); assertTrue(stepNamesList.contains("step1")); assertTrue(stepNamesList.contains("failingStep")); + assertTrue(stepNamesList.contains("step3")); - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - assertEquals(ExitStatus.FAILED, jobExecution.getExitStatus()); + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); StepExecution stepExecution1 = getStepExecution(jobExecution, "step1"); assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); @@ -55,6 +56,10 @@ public class SplitDifferentResultsFailSecondJobParserTests extends AbstractJobPa assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2.getExitStatus().getExitCode()); + StepExecution stepExecution3 = getStepExecution(jobExecution, "step3"); + assertEquals(BatchStatus.COMPLETED, stepExecution3.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution3.getExitStatus()); + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowExecutionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowExecutionTests.java index 3ad49a9dc..459020562 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowExecutionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowExecutionTests.java @@ -31,7 +31,7 @@ public class FlowExecutionTests { public void testBasicProperties() throws Exception { FlowExecution execution = new FlowExecution("foo", "BAR"); assertEquals("foo",execution.getName()); - assertEquals("BAR",execution.getStatus()); + assertEquals("BAR",execution.getStatus().getStatus()); } @Test @@ -44,8 +44,8 @@ public class FlowExecutionTests { @Test public void testEnumOrdering() throws Exception { - FlowExecution first = new FlowExecution("foo", FlowExecution.COMPLETED); - FlowExecution second = new FlowExecution("foo", FlowExecution.FAILED); + FlowExecution first = new FlowExecution("foo", FlowExecutionStatus.COMPLETED); + FlowExecution second = new FlowExecution("foo", FlowExecutionStatus.FAILED); assertTrue("Should be negative",first.compareTo(second)<0); assertTrue("Should be positive",second.compareTo(first)>0); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/JobFlowExecutorSupport.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/JobFlowExecutorSupport.java index 9a6e809ed..0b6bd10f2 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/JobFlowExecutorSupport.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/JobFlowExecutorSupport.java @@ -15,6 +15,7 @@ */ package org.springframework.batch.core.job.flow.support; +import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobInterruptedException; import org.springframework.batch.core.StartLimitExceededException; @@ -26,13 +27,13 @@ import org.springframework.batch.core.repository.JobRestartException; /** * @author Dave Syer - * + * */ public class JobFlowExecutorSupport implements FlowExecutor { public String executeStep(Step step) throws JobInterruptedException, JobRestartException, StartLimitExceededException { - return FlowExecution.COMPLETED; + return ExitStatus.COMPLETED.getExitCode(); } public JobExecution getJobExecution() { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/SimpleFlowTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/SimpleFlowTests.java index 9bec2771f..da1f9012a 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/SimpleFlowTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/SimpleFlowTests.java @@ -26,9 +26,13 @@ import java.util.Collections; import java.util.List; import org.junit.Test; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.job.flow.FlowExecution; import org.springframework.batch.core.job.flow.FlowExecutionException; +import org.springframework.batch.core.job.flow.FlowExecutionStatus; import org.springframework.batch.core.job.flow.FlowExecutor; +import org.springframework.batch.core.job.flow.support.state.EndState; /** * @author Dave Syer @@ -56,17 +60,17 @@ public class SimpleFlowTests { @Test public void testStepLoop() throws Exception { flow.setStateTransitions(collect(StateTransition.createStateTransition(new StateSupport("step"), - FlowExecution.FAILED, "step"), StateTransition.createEndStateTransition(new StateSupport("step")))); + ExitStatus.FAILED.getExitCode(), "step"), StateTransition.createEndStateTransition(new StateSupport("step")))); flow.afterPropertiesSet(); FlowExecution execution = flow.start(executor); - assertEquals(FlowExecution.COMPLETED, execution.getStatus()); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); assertEquals("step", execution.getName()); } @Test(expected = IllegalArgumentException.class) public void testNoEndStep() throws Exception { flow.setStateTransitions(Collections.singletonList(StateTransition.createStateTransition(new StateSupport( - "step"), FlowExecution.FAILED, "step"))); + "step"), ExitStatus.FAILED.getExitCode(), "step"))); flow.afterPropertiesSet(); } @@ -76,7 +80,7 @@ public class SimpleFlowTests { StateTransition.createEndStateTransition(new StubState("step2")))); flow.afterPropertiesSet(); FlowExecution execution = flow.start(executor); - assertEquals(FlowExecution.COMPLETED, execution.getStatus()); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); assertEquals("step1", execution.getName()); } @@ -102,7 +106,7 @@ public class SimpleFlowTests { "step1")))); flow.afterPropertiesSet(); FlowExecution execution = flow.start(executor); - assertEquals(FlowExecution.COMPLETED, execution.getStatus()); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); assertEquals("step1", execution.getName()); } @@ -120,17 +124,17 @@ public class SimpleFlowTests { }; FlowExecution execution = flow.start(executor); assertEquals(1, list.size()); - assertEquals(FlowExecution.COMPLETED, execution.getStatus()); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); assertEquals("step1", execution.getName()); } @Test public void testExplicitStartStep() throws Exception { flow.setStateTransitions(collect(StateTransition.createStateTransition(new StubState("step"), - FlowExecution.FAILED, "step"), StateTransition.createEndStateTransition(new StubState("step")))); + ExitStatus.FAILED.getExitCode(), "step"), StateTransition.createEndStateTransition(new StubState("step")))); flow.afterPropertiesSet(); FlowExecution execution = flow.start(executor); - assertEquals(FlowExecution.COMPLETED, execution.getStatus()); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); assertEquals("step", execution.getName()); } @@ -140,7 +144,7 @@ public class SimpleFlowTests { StateTransition.createEndStateTransition(new StubState("step2")))); flow.afterPropertiesSet(); FlowExecution execution = flow.start(executor); - assertEquals(FlowExecution.COMPLETED, execution.getStatus()); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); assertEquals("step2", execution.getName()); } @@ -150,7 +154,7 @@ public class SimpleFlowTests { StateTransition.createEndStateTransition(new StubState("step2")))); flow.afterPropertiesSet(); FlowExecution execution = flow.resume("step2", executor); - assertEquals(FlowExecution.COMPLETED, execution.getStatus()); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); assertEquals("step2", execution.getName()); } @@ -158,54 +162,28 @@ public class SimpleFlowTests { public void testFailedStep() throws Exception { flow.setStateTransitions(collect(StateTransition.createStateTransition(new StubState("step1") { @Override - public String handle(FlowExecutor executor) { - return FlowExecution.FAILED; + public FlowExecutionStatus handle(FlowExecutor executor) { + return FlowExecutionStatus.FAILED; } }, "step2"), StateTransition.createEndStateTransition(new StubState("step2")))); flow.afterPropertiesSet(); FlowExecution execution = flow.start(executor); - assertEquals(FlowExecution.COMPLETED, execution.getStatus()); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); assertEquals("step2", execution.getName()); } @Test public void testBranching() throws Exception { flow.setStateTransitions(collect(StateTransition.createStateTransition(new StubState("step1"), "step2"), - StateTransition.createStateTransition(new StubState("step1"), FlowExecution.COMPLETED, "step3"), + StateTransition.createStateTransition(new StubState("step1"), ExitStatus.COMPLETED.getExitCode(), "step3"), StateTransition.createEndStateTransition(new StubState("step2")), StateTransition .createEndStateTransition(new StubState("step3")))); flow.afterPropertiesSet(); FlowExecution execution = flow.start(executor); - assertEquals(FlowExecution.COMPLETED, execution.getStatus()); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); assertEquals("step3", execution.getName()); } - @Test - public void testPause() throws Exception { - flow.setStateTransitions(collect(StateTransition.createStateTransition(new StubState("step1"), "step2"), - StateTransition.createStateTransition(new StubState("step2") { - private boolean paused = false; - - @Override - public String handle(FlowExecutor executor) throws Exception { - if (!paused) { - paused = true; - return FlowExecution.PAUSED; - } - paused = false; - return FlowExecution.COMPLETED; - } - - }, "step3"), StateTransition.createEndStateTransition(new StubState("step3")))); - flow.afterPropertiesSet(); - FlowExecution execution = flow.start(executor); - assertEquals(FlowExecution.PAUSED, execution.getStatus()); - assertEquals("step2", execution.getName()); - execution = flow.resume(execution.getName(), executor); - assertEquals(FlowExecution.COMPLETED, execution.getStatus()); - assertEquals("step3", execution.getName()); - } - @Test public void testGetStateExists() throws Exception { flow.setStateTransitions(Collections.singletonList(StateTransition.createEndStateTransition(new StubState( diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/StateSupport.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/StateSupport.java index 22edefc81..fd1e1fd57 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/StateSupport.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/StateSupport.java @@ -15,9 +15,8 @@ */ package org.springframework.batch.core.job.flow.support; -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.job.flow.support.State; import org.springframework.batch.core.job.flow.support.state.AbstractState; /** @@ -36,8 +35,8 @@ public class StateSupport extends AbstractState { } @Override - public String handle(FlowExecutor executor) throws Exception { - return FlowExecution.COMPLETED; + public FlowExecutionStatus handle(FlowExecutor executor) throws Exception { + return FlowExecutionStatus.COMPLETED; } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/EndStateTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/EndStateTests.java index 6c98d2dc0..7178a377d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/EndStateTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/EndStateTests.java @@ -76,7 +76,7 @@ public class EndStateTests { } }); - assertEquals(BatchStatus.UNKNOWN, jobExecution.getStatus()); + assertEquals(BatchStatus.STARTING, jobExecution.getStatus()); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SimpleFlowExecutionAggregatorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SimpleFlowExecutionAggregatorTests.java index e0838084a..c70d93713 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SimpleFlowExecutionAggregatorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SimpleFlowExecutionAggregatorTests.java @@ -23,7 +23,7 @@ import java.util.Collections; import org.junit.Test; import org.springframework.batch.core.job.flow.FlowExecution; -import org.springframework.batch.core.job.flow.support.state.MaxValueFlowExecutionAggregator; +import org.springframework.batch.core.job.flow.FlowExecutionStatus; /** * @author Dave Syer @@ -35,16 +35,16 @@ public class SimpleFlowExecutionAggregatorTests { @Test public void testFailed() throws Exception { - FlowExecution first = new FlowExecution("foo", FlowExecution.COMPLETED); - FlowExecution second = new FlowExecution("foo", FlowExecution.FAILED); + FlowExecution first = new FlowExecution("foo", FlowExecutionStatus.COMPLETED); + FlowExecution second = new FlowExecution("foo", FlowExecutionStatus.FAILED); assertTrue("Should be negative", first.compareTo(second)<0); assertTrue("Should be positive", second.compareTo(first)>0); - assertEquals(FlowExecution.FAILED, aggregator.aggregate(Arrays.asList(first, second))); + assertEquals(FlowExecutionStatus.FAILED, aggregator.aggregate(Arrays.asList(first, second))); } @Test public void testEmpty() throws Exception { - assertEquals(FlowExecution.UNKNOWN, aggregator.aggregate(Collections. emptySet())); + assertEquals(FlowExecutionStatus.UNKNOWN, aggregator.aggregate(Collections. emptySet())); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SplitStateTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SplitStateTests.java index 22cae8351..ae53b4667 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SplitStateTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SplitStateTests.java @@ -24,7 +24,7 @@ import org.easymock.EasyMock; import org.junit.Test; import org.springframework.batch.core.job.flow.Flow; import org.springframework.batch.core.job.flow.FlowExecution; -import org.springframework.batch.core.job.flow.support.state.SplitState; +import org.springframework.batch.core.job.flow.FlowExecutionStatus; import org.springframework.core.task.SimpleAsyncTaskExecutor; @@ -45,12 +45,12 @@ public class SplitStateTests { SplitState state = new SplitState(flows, "foo"); - EasyMock.expect(flow1.start(null)).andReturn(new FlowExecution("step1", FlowExecution.COMPLETED)); - EasyMock.expect(flow2.start(null)).andReturn(new FlowExecution("step1", FlowExecution.COMPLETED)); + EasyMock.expect(flow1.start(null)).andReturn(new FlowExecution("step1", FlowExecutionStatus.COMPLETED)); + EasyMock.expect(flow2.start(null)).andReturn(new FlowExecution("step1", FlowExecutionStatus.COMPLETED)); EasyMock.replay(flow1, flow2); - String result = state.handle(null); - assertEquals(FlowExecution.COMPLETED, result); + FlowExecutionStatus result = state.handle(null); + assertEquals(FlowExecutionStatus.COMPLETED, result); EasyMock.verify(flow1, flow2); @@ -68,12 +68,12 @@ public class SplitStateTests { SplitState state = new SplitState(flows, "foo"); state.setTaskExecutor(new SimpleAsyncTaskExecutor()); - EasyMock.expect(flow1.start(null)).andReturn(new FlowExecution("step1", FlowExecution.COMPLETED)); - EasyMock.expect(flow2.start(null)).andReturn(new FlowExecution("step1", FlowExecution.COMPLETED)); + EasyMock.expect(flow1.start(null)).andReturn(new FlowExecution("step1", FlowExecutionStatus.COMPLETED)); + EasyMock.expect(flow2.start(null)).andReturn(new FlowExecution("step1", FlowExecutionStatus.COMPLETED)); EasyMock.replay(flow1, flow2); - String result = state.handle(null); - assertEquals(FlowExecution.COMPLETED, result); + FlowExecutionStatus result = state.handle(null); + assertEquals(FlowExecutionStatus.COMPLETED, result); EasyMock.verify(flow1, flow2); diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests-context.xml index b13658951..968404df1 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests-context.xml @@ -10,6 +10,9 @@ + + + @@ -17,6 +20,7 @@ + \ No newline at end of file