繁体   English   中英

如何从 StepExecutionListener 中的 beforeStep 方法中跳过步骤执行?

[英]How to skip a step execution from beforeStep method in StepExecutionListener?

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

在下面:

public void beforeStep(StepExecution stepExecution)

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

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

提前致谢。

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

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

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

让我知道你用什么 go !

编辑:

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

<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 的提议,我定义了一个这样的决策者:

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

在我的上下文中将它放在首位。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 的帮助。

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

什么不起作用

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

好吧, StepExecutionListener.execute()在执行之前将StepXyz执行放在您的手上。 听起来很有希望......但是, API 没有任何机制告诉 spring 批处理不要运行StepXyz 为了说明这一点,下面的任何陈述都不会做我们想要的。

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

结论

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

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

(我正在使用 Spring 引导 2.3.9。)

我的简单解决方案

在我的情况下,要测试的条件是一个或多个功能标志 我已经有一个 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
}

暂无
暂无

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

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