Java 导致作业退出状态的Spring批处理条件流失败
我对执行以下操作的spring批处理流有问题(简化)Java 导致作业退出状态的Spring批处理条件流失败,java,spring-batch,Java,Spring Batch,我对执行以下操作的spring批处理流有问题(简化) 执行一个步骤(始终) 在运行时决定下一步要做什么(jobexecutiondecider) 如果决策者决定“继续”->执行更复杂的内部流 如果决策者确定“已完成”->,则不执行内部流,而只是完成作业 鉴于以下MVE: @Configuration @EnableBatchProcessing public class BatchExample { @Autowired private JobBuilderFactory jo
@Configuration
@EnableBatchProcessing
public class BatchExample {
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Bean
public Job exampleJob() {
final FlowBuilder<Flow> innerFlowBuilder = new FlowBuilder<>("innerFlow");
final Flow innerFlow = innerFlowBuilder
.start(dummyStep("first innerflow step"))
.next(dummyStep("second innerflow step"))
.next(dummyStep("last innerflow step"))
.build();
final FlowBuilder<Flow> outerFlowBuilder = new FlowBuilder<>("outerFlow");
final Flow outerFlow = outerFlowBuilder
.start(dummyStep("always execute me"))
.next(decide()).on("CONTINUE").to(innerFlow)
.from(decide()).on("COMPLETED").end("COMPLETED")
.build();
return jobBuilderFactory.get("exampleJob")
.start(outerFlow)
.end()
.build();
}
private Step dummyStep(String arg) {
return stepBuilderFactory.get("step_" + arg)
.tasklet(dummyTasklet(arg))
.build();
}
private Tasklet dummyTasklet(String arg) {
return new DummyTasklet(arg);
}
private DummyDecider decide() {
return new DummyDecider();
}
class DummyTasklet implements Tasklet {
private final String arg;
DummyTasklet(String arg) {
this.arg = arg;
}
@Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
System.out.println("hello from dummy tasklet: " + arg);
return RepeatStatus.FINISHED;
}
}
class DummyDecider implements JobExecutionDecider {
@Override
public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {
final Random random = new Random();
final int i = random.nextInt();
if (i % 2 == 0) {
return new FlowExecutionStatus("CONTINUE");
} else {
return FlowExecutionStatus.COMPLETED;
}
}
}
}
如何在状态为“已完成”的情况下完成作业?换句话说,我在流的编码方面做错了什么
该代码可以与spring引导应用程序一起运行
@SpringBootApplication
public class FlowApplication implements ApplicationRunner {
public static void main(String[] args) {
SpringApplication.run(FlowApplication.class, args);
}
@Autowired
private Job exampleJob;
@Autowired
private JobLauncher jobLauncher;
@Override
public void run(ApplicationArguments args) throws Exception {
jobLauncher.run(exampleJob, new JobParameters());
}
}
编辑
在实施建议的答案时:
final Flow outerFlow = outerFlowBuilder
.start(dummyStep("always execute me"))
.on("*").to(decide())
.from(decide()).on("CONTINUE").to(innerFlow)
.from(decide()).on("COMPLETED").end("COMPLETED")
.build();
并迫使决策者“继续”:
innerflow不再启动:
Executing step: [step_always execute me]
hello from dummy tasklet: always execute me
Job: [FlowJob: [name=exampleJob]] completed with the following parameters: [{}] and the following status: [FAILED]
Job: [FlowJob: [name=exampleJob]] launched with the following parameters: [{}]
Step already complete or not restartable, so no action to execute: StepExecution: id=0, version=3, name=step_always execute me, status=COMPLETED, exitStatus=COMPLETED, readCount=0, filterCount=0, writeCount=0 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
Job: [FlowJob: [name=exampleJob]] completed with the following parameters: [{}] and the following status: [FAILED]
您的
outerFlow
应定义如下:
final Flow outerFlow = outerFlowBuilder
.start(dummyStep("always execute me"))
.on("*").to(decide())
.from(decide()).on("CONTINUE").to(innerFlow)
.from(decide()).on("COMPLETED").end("COMPLETED")
.build();
我用您的示例对此进行了测试(感谢您的MVE!),当决策器返回COMPLETED
时,作业不会失败
原因是,如果没有将dummyStep(“始终执行我”)
步骤的所有结果路由到带有.on(“*”).to(decision())
的决策器,则流定义不正确
希望这有帮助。感谢您的快速帮助。“已完成”流的执行是正确的,并且确实没有失败,但是现在内部流不再工作了<代码>步骤已完成或不可重新启动,因此没有要执行的操作:步骤执行:id=0,版本=3,名称=Step\u始终执行我,作业:[FlowJob:[name=exampleJob]]已完成,具有以下参数:[{}],并且以下状态:[FAILED]多次运行程序会显示此不需要的行为@马哈茂德·本·哈辛:你知道哪里出了问题吗?我该怎么解决?这是正常的行为。除非将步骤标记为可重新启动,否则无法重新启动该步骤。因此,您需要使步骤重新启动。
Executing step: [step_always execute me]
hello from dummy tasklet: always execute me
Job: [FlowJob: [name=exampleJob]] completed with the following parameters: [{}] and the following status: [FAILED]
Job: [FlowJob: [name=exampleJob]] launched with the following parameters: [{}]
Step already complete or not restartable, so no action to execute: StepExecution: id=0, version=3, name=step_always execute me, status=COMPLETED, exitStatus=COMPLETED, readCount=0, filterCount=0, writeCount=0 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
Job: [FlowJob: [name=exampleJob]] completed with the following parameters: [{}] and the following status: [FAILED]
final Flow outerFlow = outerFlowBuilder
.start(dummyStep("always execute me"))
.on("*").to(decide())
.from(decide()).on("CONTINUE").to(innerFlow)
.from(decide()).on("COMPLETED").end("COMPLETED")
.build();