【问题标题】:Return to a previous Step in Spring Batch返回到 Spring Batch 中的上一步
【发布时间】:2016-12-02 10:36:15
【问题描述】:

我想使用 Spring Batch 实现一个类似于以下的 Job:

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

在 Step2 中的某些条件下,由 Step2 的自定义 ExitCode 确定,要么再次启动 Step1,然后再启动 Step2,要么再次启动 Step2,否则处理将结束。

我的想象是这样的:

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

但是很明显,Step1经过Step2的condition2处理后,Step2就不会再启动了。

如何实现这样的递归批处理?

编辑:我设法找到了一个解决方案,但是,我还不知道它是否只是一个肮脏的解决方案,因为它似乎很简单:

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

因此,从使用 Fluent API 的 .start() 方法到其 .flow() 方法的简单更改似乎可以解决问题。

【问题讨论】:

    标签: java spring spring-batch


    【解决方案1】:

    SpringBatch 不适用于处理递归循环。虽然您可以绕过它,但在失败和重新启动时会遇到问题。

    SpringBatch 在其执行上下文中存储步骤的读取器和写入器的当前“位置”;为了能够在上次崩溃的位置重新启动作业。

    因此,在作业重新启动的情况下,SpringBatch 将假定这是作业的第一次执行。

    根据您的工作结构,这可能不是问题,但您必须牢记这一点。

    在我看来,更好的解决方案是在工作之外实现处理循环,在一个单独的类中处理启动工作。

    以下两个问题的答案可能有助于提出这样的解决方案:

    Make a spring-batch job exit with non-zero code if an exception is thrown

    Reset state before each Spring scheduled (@Scheduled) run

    【讨论】:

      【解决方案2】:

      我认为你可以扩展 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();
              }
          }
      }
      

      【讨论】:

      • 决策对我来说很清楚,但我想知道的是,如何回到某个步骤并从该步骤继续流程。据我了解,您在上面提供的 XML 配置将在 ExitStatus“Back”上启动 step1,然后,由于“next”属性,将启动 step2,这是所需的解决方案。但在我的 Java 配置中,相同步骤的情况并非如此,是吗?在 XML 配置中,“next”属性与步骤相关,而在 Java 配置中,它与流程相关,不是吗?
      猜你喜欢
      • 2018-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-20
      • 1970-01-01
      • 2017-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多