RESOLVED - issue BATCH-1187: Step shouldn't exit with status=EXECUTING

AbstractStep now sets the ExitStatus (by ANDing with the existing value), so a Tasklet does not have to set it manually.
This commit is contained in:
dsyer
2009-04-09 11:51:31 +00:00
parent df2f25b1d0
commit 82bc42d102
16 changed files with 61 additions and 32 deletions

View File

@@ -130,11 +130,6 @@
<groupId>javax.annotation</groupId>
<artifactId>com.springsource.javax.annotation</artifactId>
</dependency>
<dependency>
<groupId>org.apache.log4j</groupId>
<artifactId>com.springsource.org.apache.log4j</artifactId>
<optional>false</optional>
</dependency>
<dependency>
<groupId>org.apache.log4j</groupId>
<artifactId>com.springsource.org.apache.log4j</artifactId>

View File

@@ -500,11 +500,15 @@ public class StepExecution extends Entity {
}
public String toString() {
return String.format(getSummary() + ", exitDescription=%s", exitStatus.getExitDescription());
}
public String getSummary() {
return super.toString()
+ String.format(
", name=%s, status=%s, exitStatus=%s, readCount=%d, filterCount=%d, writeCount=%d readSkipCount=%d, writeSkipCount=%d"
+ ", commitCount=%d, rollbackCount=%d", stepName, status, exitStatus, readCount,
filterCount, writeCount, readSkipCount, writeSkipCount, commitCount, rollbackCount);
+ ", commitCount=%d, rollbackCount=%d", stepName, status, exitStatus.getExitCode(),
readCount, filterCount, writeCount, readSkipCount, writeSkipCount, commitCount, rollbackCount);
}
}

View File

@@ -235,6 +235,8 @@ public abstract class AbstractJob implements Job, StepLocator, BeanNameAware, In
*/
public final void execute(JobExecution execution) {
logger.debug("Job execution starting: "+execution);
try {
if (execution.getStatus() != BatchStatus.STOPPING) {
@@ -246,6 +248,7 @@ public abstract class AbstractJob implements Job, StepLocator, BeanNameAware, In
try {
doExecute(execution);
logger.debug("Job execution complete: "+execution);
} catch (RepeatException e) {
throw e.getCause();
}
@@ -256,6 +259,7 @@ public abstract class AbstractJob implements Job, StepLocator, BeanNameAware, In
// with it in the same way as any other interruption.
execution.setStatus(BatchStatus.STOPPED);
execution.setExitStatus(ExitStatus.COMPLETED);
logger.debug("Job execution was stopped: "+execution);
}
@@ -290,7 +294,6 @@ public abstract class AbstractJob implements Job, StepLocator, BeanNameAware, In
jobRepository.update(execution);
}
}

View File

@@ -25,6 +25,8 @@ import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.JobExecutionException;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.job.flow.Flow;
@@ -47,6 +49,8 @@ import org.springframework.beans.factory.InitializingBean;
*/
public class SimpleFlow implements Flow, InitializingBean {
private static final Log logger = LogFactory.getLog(SimpleFlow.class);
private State startState;
private Map<String, SortedSet<StateTransition>> transitionMap = new HashMap<String, SortedSet<StateTransition>>();
@@ -128,12 +132,15 @@ public class SimpleFlow implements Flow, InitializingBean {
FlowExecutionStatus status = FlowExecutionStatus.UNKNOWN;
State state = stateMap.get(stateName);
logger.debug("Resuming state="+stateName+" with status="+status);
// Terminate if there are no more states
while (state != null && status!=FlowExecutionStatus.STOPPED) {
stateName = state.getName();
try {
logger.debug("Handling state="+stateName);
status = state.handle(executor);
}
catch (Exception e) {
@@ -141,6 +148,8 @@ public class SimpleFlow implements Flow, InitializingBean {
throw new FlowExecutionException(String.format("Ended flow=%s at state=%s with exception", name,
stateName), e);
}
logger.debug("Completed state="+stateName+" with status="+status);
state = nextState(stateName, status);

View File

@@ -199,7 +199,7 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
catch (RepeatException e) {
throw e.getCause();
}
exitStatus = stepExecution.getExitStatus();
exitStatus = ExitStatus.COMPLETED.and(stepExecution.getExitStatus());
// Check if someone is trying to stop us
if (stepExecution.isTerminateOnly()) {
@@ -218,6 +218,8 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
finally {
try {
// Update the step execution to the latest known value so the listeners can act on it
stepExecution.setExitStatus(exitStatus);
exitStatus = exitStatus.and(getCompositeListener().afterStep(stepExecution));
}
catch (Exception e) {
@@ -259,7 +261,7 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw
StepSynchronizationManager.release();
logger.debug("Step execution complete: " + stepExecution);
logger.debug("Step execution complete: " + stepExecution.getSummary());
}
}

View File

@@ -16,7 +16,6 @@
package org.springframework.batch.core.step.item;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
@@ -81,9 +80,6 @@ public class ChunkOrientedTasklet<I> implements Tasklet {
chunkContext.removeAttribute(INPUTS_KEY);
chunkContext.setComplete();
if (inputs.isEnd()) {
contribution.setExitStatus(ExitStatus.COMPLETED);
}
return RepeatStatus.continueIf(!inputs.isEnd());

View File

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

View File

@@ -17,7 +17,6 @@ package org.springframework.batch.core.configuration.xml;
import java.util.List;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.listener.StepExecutionListenerSupport;
@@ -44,7 +43,6 @@ public class NameStoringTasklet extends StepExecutionListenerSupport implements
if (stepNamesList != null) {
stepNamesList.add(stepName);
}
contribution.setExitStatus(ExitStatus.COMPLETED);
return RepeatStatus.FINISHED;
}

View File

@@ -1,6 +1,5 @@
package org.springframework.batch.core.configuration.xml;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
@@ -11,7 +10,6 @@ public class TestTasklet extends AbstractTestComponent implements Tasklet {
public RepeatStatus execute(StepContribution contribution,
ChunkContext chunkContext) throws Exception {
executed = true;
contribution.setExitStatus(ExitStatus.COMPLETED);
return RepeatStatus.FINISHED;
}

View File

@@ -85,7 +85,7 @@ public class AbstractStepTests {
public ExitStatus afterStep(StepExecution stepExecution) {
assertSame(execution, stepExecution);
events.add(getEvent("afterStep"));
events.add(getEvent("afterStep("+stepExecution.getExitStatus().getExitCode()+")"));
stepExecution.getExecutionContext().putString("afterStep", "afterStep");
return stepExecution.getExitStatus();
}
@@ -175,8 +175,8 @@ public class AbstractStepTests {
assertEquals("listener2#beforeStep", events.get(i++));
assertEquals("open", events.get(i++));
assertEquals("doExecute", events.get(i++));
assertEquals("listener2#afterStep", events.get(i++));
assertEquals("listener1#afterStep", events.get(i++));
assertEquals("listener2#afterStep(COMPLETED)", events.get(i++));
assertEquals("listener1#afterStep(COMPLETED)", events.get(i++));
assertEquals("close", events.get(i++));
assertEquals(7, events.size());
@@ -213,8 +213,8 @@ public class AbstractStepTests {
assertEquals("listener2#beforeStep", events.get(i++));
assertEquals("open", events.get(i++));
assertEquals("doExecute", events.get(i++));
assertEquals("listener2#afterStep", events.get(i++));
assertEquals("listener1#afterStep", events.get(i++));
assertEquals("listener2#afterStep(FAILED)", events.get(i++));
assertEquals("listener1#afterStep(FAILED)", events.get(i++));
assertEquals("close", events.get(i++));
assertEquals(7, events.size());
@@ -251,8 +251,8 @@ public class AbstractStepTests {
assertEquals("listener2#beforeStep", events.get(i++));
assertEquals("open", events.get(i++));
assertEquals("doExecute", events.get(i++));
assertEquals("listener2#afterStep", events.get(i++));
assertEquals("listener1#afterStep", events.get(i++));
assertEquals("listener2#afterStep(STOPPED)", events.get(i++));
assertEquals("listener1#afterStep(STOPPED)", events.get(i++));
assertEquals("close", events.get(i++));
assertEquals(7, events.size());

View File

@@ -100,8 +100,10 @@ public class ChunkOrientedTaskletTests {
});
StepContribution contribution = new StepContribution(new StepExecution("foo", new JobExecution(new JobInstance(
123L, new JobParameters(), "job"))));
ExitStatus expected = contribution.getExitStatus();
handler.execute(contribution, context);
assertEquals(ExitStatus.COMPLETED.getExitCode(), contribution.getExitStatus().getExitCode());
// The tasklet does not change the exit code
assertEquals(expected, contribution.getExitStatus());
}
}

View File

@@ -74,6 +74,7 @@ public class TaskletStepExceptionTests {
taskletStep.execute(stepExecution);
assertEquals(FAILED, stepExecution.getStatus());
assertEquals(FAILED.toString(), stepExecution.getExitStatus().getExitCode());
}
@Test
@@ -81,6 +82,7 @@ public class TaskletStepExceptionTests {
taskletStep.setStepExecutionListeners(new StepExecutionListener[] { new InterruptionListener() });
taskletStep.execute(stepExecution);
assertEquals(STOPPED, stepExecution.getStatus());
assertEquals(STOPPED.toString(), stepExecution.getExitStatus().getExitCode());
}
@Test
@@ -116,7 +118,7 @@ public class TaskletStepExceptionTests {
}
@Test
public void testAfterStepFailure() throws Exception {
public void testAfterStepFailureWhenTaskletSucceeds() throws Exception {
final RuntimeException exception = new RuntimeException();
taskletStep.setStepExecutionListeners(new StepExecutionListenerSupport[] { new StepExecutionListenerSupport() {
@@ -142,7 +144,7 @@ public class TaskletStepExceptionTests {
/*
* Exception in afterStep is ignored (only logged).
*/
public void testAfterStepFAilure() throws Exception {
public void testAfterStepFailureWhenTaskletFails() throws Exception {
final RuntimeException exception = new RuntimeException();
taskletStep.setStepExecutionListeners(new StepExecutionListenerSupport[] { new StepExecutionListenerSupport() {

View File

@@ -11,8 +11,10 @@
<job id="job">
<step id="s1" parent="step1" next="fail"/>
<step id="fail" parent="failingStep">
<fail on="FAILED" exit-code="FAILED EARLY TERMINATION"/>
<next on="*" to="s2"/>
<fail on="FAILED" exit-code="EARLY TERMINATION"/>
</step>
<step id="s2" parent="step1"/>
</job>
</beans:beans>

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.batch.integration.job;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
@@ -32,7 +31,6 @@ public class TestTasklet implements Tasklet {
*
*/
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
contribution.setExitStatus(ExitStatus.COMPLETED);
return RepeatStatus.FINISHED;
}

View File

@@ -72,6 +72,11 @@
<artifactId>com.springsource.org.apache.commons.collections
</artifactId>
</dependency>
<dependency>
<groupId>org.apache.log4j</groupId>
<artifactId>com.springsource.org.apache.log4j</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<reporting>

View File

@@ -0,0 +1,15 @@
log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2} - %m%n
log4j.category.org.apache.activemq=ERROR
log4j.category.org.springframework.batch=DEBUG
log4j.category.org.springframework.batch.support=INFO
# log4j.category.org.springframework.transaction=INFO
log4j.category.org.springframework.jdbc=DEBUG
# log4j.category.org.hibernate.SQL=DEBUG
# for debugging datasource initialization
# log4j.category.test.jdbc=DEBUG