【问题标题】:How to skip a step execution from beforeStep method in StepExecutionListener?如何从 StepExecutionListener 中的 beforeStep 方法中跳过步骤执行?
【发布时间】:2020-05-25 09:22:11
【问题描述】:

我想为任何步骤实现一个通用的 StepExecutionListener,所以在 beforeStep 方法中(也就是说,在当前步骤 tasklet 开始之前)它可以检查一些与数据库相关的条件:如果不成功,它将跳过当前步骤并继续下一个。

下:

public void beforeStep(StepExecution stepExecution)

目前我没有在“stepExecution”对象中找到任何可以做到这一点的东西。我只是将退出状态更改为 COMPLETED,但仍然执行相应的 tasklet。

有没有办法做到这一点?我也听说过决策者,但我不喜欢在我的 XML 中添加太多冗长的配置。

提前致谢。

【问题讨论】:

  • @Priteesh 的回答是正确的,决策者比侦听器更适合您的用例。

标签: java spring-batch


【解决方案1】:

在这种情况下,决策者是更好的选择,因为它们的唯一目的是决定是否执行您的步骤。他们确实使 xml 变得冗长,但这更好,因为其他人一眼就能理解。

我认为 beforeStep 可以处理此问题的唯一方法是,如果您在任务名称属于您要忽略的名称时抛出异常。但是,即使上一步失败,您的下一步也可能需要配置为运行(如果未跳过该步骤时这不是您想要的,则不推荐)。

不过,如果你的任务扩展,你需要决定 3-4 个步骤,在 beforeStep 中处理会变得很麻烦。

让我知道你要做什么!

编辑:

决策者的使用示例以及步骤

<batch:decision id="decider1" decider="deciderClass1">
        <batch:next on="FAILED" to="decider2" />
        <batch:next on="COMPLETED" to="task1"/>
    </batch:decision>
    <batch:step id="step1" next="decider2" parent="step1Class"/>

    <batch:decision id="decider2" decider="deciderClass2">
        <batch:next on="FAILED" to="step3" />
        <batch:next on="COMPLETED" to="step2"/>
    </batch:decision>
    <batch:step id="step2" parent="step2Class" next="step3"/>
.....

【讨论】:

  • 非常感谢您,Priteesh!我对您的回答有一个问题:难道不是决策者在执行步骤后做出决定并根据退出状态做出决定吗?问题是我不希望在检查前提条件之前执行该步骤。问候。
  • 决策者独立于步骤或其他决策者。一旦你执行了你的决策者,你可以在这里决定接下来的过程是否应该取决于决策者给出的是真还是假。我会用它的例子来更新答案。
  • 感谢您的新回复和添加示例。我会尝试在我的代码中使用你的方法,并会让你知道。请接受我的感谢:)
  • @J.. 欢迎来到 SO:请阅读 stackoverflow.com/help/someone-answers 了解如何接受答案。
  • 事实上,决策者不是原始问题的解决方案。文档中很清楚:StepExecutionListener.beforeStep()JobExecutionDecider.decide() 都有一个 StepExecution 参数。但是,对于beforeStep(),此参数是要执行的NEXT 步骤,而对于decide(),它是刚刚执行的PREVIOUS 步骤。
【解决方案2】:

我会回答自己以介绍一些代码。

根据 Priteesh 的提议,我定义了一个这样的决策者:

    <decision id="deciderId" decider="deciderDeclaration">
        <next on="CONTINUE" to="step1" />
        <next on="SKIP" to="finalStep" />
    </decision>

将它放在我的 context.xml 中的首位。这很重要,因为如果不满足条件,step1 永远不会执行。

而我的决策者是这样的:

public class StepExecutionDecider implements JobExecutionDecider{

    /** LOGGER. */
    private Logger LOGGER = ...

    private static final String FLOW_STATUS_CONTINUE = "CONTINUE";
    private static final String FLOW_STATUS_SKIP = "SKIP";

    @Override
    public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {

        String status = FLOW_STATUS_CONTINUE;

        String condition = ....

        if (Constants.NO.equals(condition)){

            LOGGER.warn(jobExecution.getJobInstance().getJobName(), " -> The Step execution is disabled. Continuing with the next Step.");

            status = FLOW_STATUS_SKIP;
        }

        return new FlowExecutionStatus(status);
    }

    ...
}

奇怪的是,每当我的条件不满足时,LOGGER 消息就会在我的日志中打印两次,时间戳完全相同...

无论如何,非常感谢 Priteesh 的热心帮助。

【讨论】:

    【解决方案3】:

    我有同样的目标:在StepExecutionListener 中使用beforeStep() 来检查非弹簧批处理相关的条件,以决定该步骤是否应该运行。

    什么不起作用

    使用决策程序 (JobExecutionDecider) 不起作用,因为JobExecutionDecider.decide() 接收先前执行的步骤作为参数。决策者的目的是让您检查上一步执行的状态以选择下一步做什么。如果我正在测试特定于 StepXYZ 的条件,我需要在手头执行该步骤在它执行之前

    好吧,StepExecutionListener.execute() 在执行之前将 StepXyz 执行放在您的手上。听起来很有希望……但是,API 没有任何机制告诉 Spring Batch 不要运行 StepXyz。为了说明这一点,下面的语句都不能满足我们的要求。

    stepExecution.status = BatchStatus.ABANDONED
    stepExecution.exitStatus = ExitStatus.NOOP
    stepExecution.setTerminateOnly()   
    

    结论

    在搜索了所有框架代码、SO和spring文档之后,我的结论是:

    不能使用beforeStep() 优雅地告诉spring batch 不要运行该步骤。

    (我使用的是 Spring Boot 2.3.9。)

    我的简单解决方案

    在我的情况下,要测试的条件是一个或多个feature flags。我已经有一个 FeatureFlags Component,所以我将它注入到 tasklet 中,并在 execute() 开头测试了前置条件:

    override fun execute(contribution: StepContribution, chunkContext: ChunkContext): RepeatStatus? {
        if (!featureFlags.stepShouldRun) {
            contribution.exitStatus = ExitStatus("SKIPPED BASED ON FEATURE FLAGS")
            return RepeatStatus.FINISHED
        }
        return execute()
    }
    
    fun execute(): RepeatStatus {
        // the actual step logic goes here
        // add StepContribution as a param if necessary
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-17
      • 1970-01-01
      相关资源
      最近更新 更多