Prevent NPE when checking for a re-runnable continued flow, remove usage of

state transition comparator in FlowParser, ensure custom exit code is set at
job level.

Fixes TCK test testDeciderExitStatusIsSetOnJobContext, contributes but does
not fix decider transition tests that include restart.
This commit is contained in:
Chris Schaefer
2013-12-17 17:20:51 -05:00
parent 3e5597717e
commit d76209df10
6 changed files with 58 additions and 5 deletions

View File

@@ -237,7 +237,7 @@ public class SimpleFlow implements Flow, InitializingBean {
if(stepExecution != null) {
Boolean reRun = (Boolean) stepExecution.getExecutionContext().get("batch.restart");
if(reRun != null && reRun && status == FlowExecutionStatus.STOPPED && !state.getName().endsWith(stepExecution.getStepName())) {
if(reRun != null && reRun && status == FlowExecutionStatus.STOPPED && stateNameEndsWithStepName(state, stepExecution)) {
continued = true;
}
}
@@ -245,6 +245,10 @@ public class SimpleFlow implements Flow, InitializingBean {
return continued;
}
private boolean stateNameEndsWithStepName(State state, StepExecution stepExecution) {
return !(stepExecution == null || state == null) && !state.getName().endsWith(stepExecution.getStepName());
}
/**
* Analyse the transitions provided and generate all the information needed
* to execute the flow.

View File

@@ -26,10 +26,8 @@ import java.util.Set;
import org.springframework.batch.core.configuration.xml.AbstractFlowParser;
import org.springframework.batch.core.configuration.xml.SimpleFlowFactoryBean;
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
import org.springframework.batch.core.job.flow.support.DefaultStateTransitionComparator;
import org.springframework.batch.core.jsr.job.flow.support.DefaultFlow;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.ParserContext;
@@ -143,7 +141,7 @@ public class FlowParser extends AbstractFlowParser {
builder.getRawBeanDefinition().setAttribute("flowName", idAttribute);
builder.addPropertyValue("name", idAttribute);
builder.addPropertyValue("stateTransitionComparator", new RuntimeBeanReference(DefaultStateTransitionComparator.STATE_TRANSITION_COMPARATOR));
doParse(element, parserContext, builder);
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

View File

@@ -60,6 +60,9 @@ public class JsrFlowExecutor extends JobFlowExecutor {
if(isNonDefaultExitStatus(curStatus.getExitCode())) {
exitStatus = exitStatus.and(new ExitStatus(status.getName()));
execution.setExitStatus(exitStatus);
} else {
exitStatus = exitStatus.and(curStatus);
execution.setExitStatus(exitStatus);
}
}

View File

@@ -71,7 +71,10 @@ public class DecisionStep extends AbstractStep {
executions[0] = new org.springframework.batch.core.jsr.StepExecution(lastExecution);
try {
stepExecution.setExitStatus(new ExitStatus(decider.decide(executions)));
ExitStatus exitStatus = new ExitStatus(decider.decide(executions));
stepExecution.getJobExecution().setExitStatus(exitStatus);
stepExecution.setExitStatus(exitStatus);
} catch (Exception e) {
stepExecution.setTerminateOnly();
stepExecution.addFailureException(e);

View File

@@ -86,6 +86,19 @@ public class DecisionStepTests {
}
}
@Test
public void testDecisionCustomExitStatus() throws Exception {
ApplicationContext context = new GenericXmlApplicationContext("classpath:/org/springframework/batch/core/jsr/step/DecisionStepTests-decisionCustomExitStatus-context.xml");
JobLauncher launcher = context.getBean(JobLauncher.class);
Job job = context.getBean(Job.class);
JobExecution execution = launcher.run(job, new JobParameters());
assertEquals(BatchStatus.FAILED, execution.getStatus());
assertEquals(2, execution.getStepExecutions().size());
assertEquals("CustomFail", execution.getExitStatus().getExitCode());
}
@Test
@Ignore("Flows as first steps are not supported yet")
public void testDecisionAfterFlow() throws Exception {
@@ -108,6 +121,12 @@ public class DecisionStepTests {
@Override
public String decide(StepExecution[] executions) throws Exception {
for(StepExecution stepExecution : executions) {
if ("customFailTest".equals(stepExecution.getStepName())) {
return "CustomFail";
}
}
return "next";
}
}

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/jobXML_1_0.xsd">
<job id="job1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
<step id="customFailTest" next="decision1">
<batchlet ref="doSomethingBatchlet"/>
</step>
<decision ref="nextDecider" id="decision1">
<fail on="CustomFail"/>
</decision>
</job>
<bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager"/>
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository"/>
</bean>
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean"/>
<bean id="nextDecider" class="org.springframework.batch.core.jsr.step.DecisionStepTests$NextDecider"/>
<bean id="doSomethingBatchlet" class="org.springframework.batch.core.jsr.step.batchlet.BatchletSupport"/>
</beans>