问题
I've happened up the following design defect in Spring Batch.
- A Step must have a Next attribute unless it is the last Step or last Step of a Split Flow.
- A Decider block must handle all cases returned by the Decider.
Because of this, in a Split Flow, where the final Step would not have a Next attribute, if there is a Decider guarding it, then it must have a Next attribute. So it shouldn't have that attribute, but it also needs it. Catch 22.
Example:
<!-- Process parallel steps -->
<split id="split01">
<flow>
<step id="step1" next="step02">
<!-- Do something -->
</step>
<step id="step02">
<!-- Do something else -->
</step>
</flow>
<flow>
<step id="step03">
<!-- Do something -->
</step>
<!-- Only run under specific conditions -->
<decision id="decideToRunStep04" decider="isStepNeededDecider" >
<next on="RUN" to="step04"/>
<!-- Other state is "SKIP" -->
</decision>
<step id="step04">
<!-- Conditionally do something-->
</step>
</flow>
</split>
<step id="step05" >
<!-- Some more stuff -->
</step>
This seems like something the Spring guys would have thought of, so curious what the right, non-hack way to achieve this is. Thanks.
回答1:
Given no answers from anyone on this, I'll proffer the hack that I'm using. It's not pretty, but neither is Spring.
Create a No Op Tasklet to use in a No Op step.
public class NoopTasklet implements Tasklet {
@Override
public RepeatStatus execute(final StepContribution contribution,
final ChunkContext chunkContext) throws Exception {
return RepeatStatus.FINISHED;
}
}
The add NOOP tasklet to the decision block from the original example
<!-- Does nothing -->
<bean id="noopTasklet" class="com.foo.NoopTasklet" />
<!-- From example in question
<decision id="decideToRunStep04" decider="isStepNeededDecider" >
<next on="RUN" to="step04"/>
<next on="SKIP" to="noop01"/>
</decision>
<step id="step04">
<!-- Conditionally do something-->
</step>
<step id="noop01">
<!-- Does nothing in the SKIP case
<tasklet ref="noopTasklet" />
</step>
回答2:
Spring is the prettiest code in town. That said:
<step id="step1" parent="s1">
<end on="FAILED" />
<next on="COMPLETED WITH SKIPS" to="errorPrint1" />
<next on="*" to="step2" />
</step>
as it is documented at http://docs.spring.io/spring-batch/reference/html/configureStep.html.
回答3:
In XML
<batch:decision id="customerDecision" decider="customerDecider">
<batch:next on="FILE_FAILURE" to="fileFailureStep" />
<batch:next on="FILE_GENERATION" to="loadData" />
</batch:decision>
In customerDecider class
public class CustomerDecider implements JobExecutionDecider {
@Override
public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecutionStatus) {
If(x)
return new FlowExecutionStatus("FILE_FAILURE") ;
else
return new FlowExecutionStatus("FILE_GENERATION") ;
}
}
来源:https://stackoverflow.com/questions/21782008/how-to-terminate-step-within-a-spring-batch-split-flow-with-a-decider