简体   繁体   English

返回Spring Batch中的上一步

[英]Return to a previous Step in Spring Batch

I want to implement a Job similar to the following one, using Spring Batch: 我想使用Spring Batch实现类似于以下的Job:

Step1 -----> Step2 --> End
  ^            |
  |            |
   ------------

On some condition in Step2, determined by a custom ExitCode of Step2, either Step1 is started again and thus after it, Step2 again, or the processing will end. 在步骤2中的某些条件下,由步骤2的自定义ExitCode确定,或者再次启动步骤1,然后再启动步骤2,或者处理将结束。

What I've imagined is something like this: 我想象的是这样的:

return jobBuilderFactory.get("jobName").incrementer(new RunIdIncrementer())
                .start(step1()).next(step2())
                    .on("condition1").end()
                .from(step1())
                    .on("condition2").to(step1()).end().build();

But obviously, after Step1 was processed through the condition2 of Step2, Step2 won't be started again. 但显然,在Step2通过Step2的condition2处理后,Step2将不会再次启动。

How can I implement such a recursive Batch Processing? 如何实现这样的递归批处理?

EDIT: I managed to get a solution, however, I do not know yet if it's just a dirty one, because it seems to be just to easy: 编辑:我设法得到一个解决方案,但是,我还不知道它是否只是一个肮脏的,因为它似乎只是简单:

jobBuilderFactory.get("jobName")
            .flow(step1())
            .next(step2())
                .on("launchStep1Again")
                    .to(step1())
            .from(step2())
                .on("endJobExecution")
                    .end().build().build();

So the simple change from using the Fluent API's .start() method to its .flow() method seems to do the trick. 因此,从使用Fluent API的.start()方法到其.flow()方法的简单更改似乎可以解决问题。

SpringBatch was not intended for handling recursive loops. SpringBatch不用于处理递归循环。 Whilst you may be able to hack around it, you will run into problems when it comes to failures and restarting. 虽然您可能能够破解它,但在遇到故障和重新启动时会遇到问题。

SpringBatch stores the current "position" of it readers and writers of a step inside its execution context; SpringBatch将读取器的当前“位置”存储在其执行上下文中的步骤; in order to be able to restart the job at the very position it crashed the last time. 为了能够在最后一次崩溃的位置重新启动作业。

Therefore, in case of a restart of the job, SpringBatch will assume that this was the first execution of the job. 因此,在重新启动作业的情况下,SpringBatch将假定这是该作业的第一次执行。

Depending on your job structure, this may not be a problem, but it is something you have to keep in mind. 根据您的工作结构,这可能不是问题,但您必须牢记这一点。

In my opinion, a better solution would be to implement handling the loop outside of the job, in a separate class that handles starting job. 在我看来,更好的解决方案是在一个处理起始工作的单独类中实现处理作业外部的循环。

The answers to the following two questions may help in order to come up with such a solution: 以下两个问题的答案可能有助于提出这样的解决方案:

Make a spring-batch job exit with non-zero code if an exception is thrown 如果抛出异常,则使用非零代码创建一个spring-batch作业出口

Reset state before each Spring scheduled (@Scheduled) run 在每次Spring计划(@Scheduled)运行之前重置状态

I think you can extend the StepExecutionListenerSupport class and modify you configuration as follows: 我认为您可以扩展StepExecutionListenerSupport类并修改配置,如下所示:

<step id="step1" next="step2">
    <tasklet ref="step1Tasklet" allow-start-if-complete="true"/>
</step>
<step id="step2">
    <tasklet ref="step2Tasklet"/>
    <listeners>
        <listener ref="myListener"/>
    </listeners>
    <next on="Back" to="step1"/>
</step>

public class MyListener extends StepExecutionListenerSupport {
    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        if(wantToLoop) {
            return new ExitStatus("Back");
        } else {
            return stepExecution.getExitStatus();
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM