当前位置: 首页 > 知识库问答 >
问题:

导致作业退出状态的Spring批处理条件流失败

屈畅
2023-03-14
    null

鉴于以下MVE:

@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;
            }
        }
    }    
}

执行代码时,“Continue”流运行良好,但“Completed”流总是以失败的作业状态退出。

 Job: [FlowJob: [name=exampleJob]] completed with the following
 parameters: [{}] and the following status: [FAILED]

如何使作业在状态已完成的情况下完成?换句话说,我在流的编码上做错了什么?

@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();
class DummyDecider implements JobExecutionDecider {
        @Override
        public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {
            return new FlowExecutionStatus("CONTINUE");
        }
    }
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]

共有1个答案

单于奕
2023-03-14

您的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(“Always execute me”)步骤的所有结果路由到带有.on(“*”).to(decide())的decider,流定义就不正确。

 类似资料:
  • 我最近使用。我对DB表进行了必要的更改,并对一些与参数API相关的微小代码进行了更改。 现在,当我运行应用程序时,它正在工作,但是如果一个步骤的退出状态为失败,则作业的存在状态设置为完成。这会导致一些问题,因为我们的应用程序代码将其视为成功执行。我通过在中添加一个代码片段来解决这个问题,在这里我检查列表并手动设置作业退出状态,但是Spring批处理框架不应该处理退出状态吗?

  • 我有一个Spring批处理tasklet,我不知道如何从中失败。我想检查某些参数,如果它们不存在,则在该步骤中使作业失败。 注释掉的行是我试图让工作退出的行。有人有过这样的经历吗?

  • 当编写器抛出异常时,我希望能够将步骤和作业状态设置为失败。在做了一些调试和检查Spring批处理源代码后,我注意到配置了一个,它认为是一个致命的异常,因此将作业状态设置为FAILED,所以我将代码包装在我的编写器中的一个try-get中,将包装在中,现在作业和步骤状态设置为FAILED,这是我想要的。我不确定这是否是正确的方法,因为我在任何地方都找不到它的文档,的留档也没有提到它。所以,问题是:这

  • 我在我的JAVA应用程序中配置了Spring批处理作业,该应用程序在集群中运行。因此,相同的作业被执行两次,这是我不想要的。 所以我想在作业中配置一个步骤,它将检查CREATE_DATE是否在BATCH_JOB_EXECUTION表中存在,并将继续或故障转移。 如何在spring批处理步骤中进行配置?

  • 我有以下工作要处理在一定的时间间隔或特别的基础上。 作业中的步骤如下: 我也想要用户界面,在那里我可以触发一个特别的基础上的工作,而且我应该能够提供参数从用户界面。 我想用Spring batch来完成这个任务,但它更多的是用于读->处理->写之类的工作。这里,在第一步中,我正在生成由第二步读取的数据。我不确定我是否还可以使用Spring batch来实现这个,或者有更好的方法来实现这个。

  • [BatchJobCompletionNotificationListener]!!!工作完成了! [BatchJobCompletionNotificationListener]作业不再以状态[停止]退出状态[exitCode=completed;exitDescription=]运行。 [BatchJobCompletionNotificationListener]步骤[step1]状态[已完