【问题标题】:JSR-352 Java Batch: why does JobListener.afterJob() always get batch status STARTED?JSR-352 Java Batch:为什么 JobListener.afterJob() 总是获得批处理状态 STARTED?
【发布时间】:2018-01-17 23:07:02
【问题描述】:

我是 Java Batch 新手。我在 WebSphere Liberty 17.0.0.4 上部署了一个包含 JobListener 的简单批处理作业(请注意,我使用的是 IBM 的 JSR-352 实现,而不是 Spring Batch)。批处理作业本身按预期运行:它读取输入文件,进行简单的数据转换,然后写入数据库。但是在成功执行的 JobListener 的 afterJob() 方法中,我看到批处理状态为 STARTED,退出状态为 null。 (这些值与我在 beforeJob() 方法中看到的值相同)。我希望 afterJob() 看到 COMPLETED 状态,除非有异常。

afterJob() 记录的执行 ID 与 JobOperator.start() 在我开始作业时返回的值相同,所以我知道我得到了正确作业执行的状态。

我找不到任何获取批处理状态的 JobListener 示例,因此我的 JSL 中可能有一个简单的错误,或者我获取的批处理状态不正确。或者我是否需要在步骤的实施中明确设置状态?对于设置和获取作业执行的最终批处理状态和退出状态的正确技术,我将不胜感激。

这是 JSL:

<job ...>
    <properties>...</properties>

    <listeners>
        <listener ref="jobCompletionNotificationListener"/>
    </listeners>

    <flow id="flow1">
        <step id="step1">...</step>
    </flow>
</job>

这是batch.xml中监听器的定义:

<ref id="jobCompletionNotificationListener"
     class="com.llbean.batch.translatepersonnames.jobs.JobCompletedListener"/>    

这里是 JobListener 的实现:

@Dependent
@Named("jobCompletedListener")
public class JobCompletedListener implements JobListener {
    ...
    @Inject
    private JobContext jobContext;

    @Override
    public void afterJob() {
        long executionId = jobContext.getExecutionId();
        JobExecution jobExecution = BatchRuntime.getJobOperator().getJobExecution(executionId);
        BatchStatus batchStatus = jobExecution.getBatchStatus();
        String exitStatus = jobExecution.getExitStatus();
        logger.info("afterJob(): Job id " + executionId + " batch status = " + batchStatus + 
                ", exit status = " + exitStatus);
        ...
    }
}

我尝试将 &lt;end on="*" exit-status="COMPLETED"/&gt; 添加到 JSL 中的 &lt;job&gt;&lt;flow&gt;,但这没有效果或导致状态为 FAILED。

【问题讨论】:

    标签: jsr352 java-batch


    【解决方案1】:

    好问题。让我对@cheng 的回答补充几点。

    首先,要了解我们为什么以这种方式实现它,请考虑 JobListener 抛出异常的情况。那应该让工作失败吗?在 Liberty 中,我们决定应该这样做。但是,如果该工作已经具有COMPLETED 状态,那么这意味着它已经......完成了,并且不应该在那个时候失败。

    所以afterJob() 更像是“工作结束”(或者您可以将其视为“工作步骤之后”)。

    其次,问这个问题的一个原因是因为你想知道,在afterJob() 方法中,作业是否成功执行。

    好吧,至少在 Liberty 实现中(我为 IBM 工作),您确实可以看到这一点。先前的失败会将 BatchStatus 设置为 FAILED,而成功(到目前为止)执行的状态仍将是 STARTED

    (对于它的价值,这是我们意识到可以在 1.0 规范工作的后期使用更多关注和标准化的领域,我希望我们可以在未来解决更多问题。)

    如果它有帮助并且您有兴趣,您可以查看流程中的基本逻辑,直至并包括 WorkUnitThreadControllerImpl.endOfWorkUnit 调用 here

    【讨论】:

    • 感谢您提供非常全面和有用的回答。
    【解决方案2】:

    这是因为作业侦听器的 afterJob 方法是作业执行的一部分。所以当你在afterJob() 方法中调用getBatchStatus() 时,作业仍在执行中,尚未完成,因此批处理状态为STARTED

    【讨论】:

    • 啊。有趣的。这与 Spring Batch 的 JobExecutionListener 中的行为不同,如果没有错误,afterJob() 会看到作业执行状态为 COMPLETED。感谢您的洞察力。
    • 如果失败,我在 afterJob() 中看到批处理状态失败。它似乎仍然可以区分。
    • 当作业执行在中间失败时,批处理包含知道唯一的结果是失败,因此将批处理状态设置为 FAILED。如果在 afterJob() 之前一切顺利,我们仍然不知道在 afterJob() 期间的最后一刻是否会出现任何问题,因此批处理状态为 STARTED。
    猜你喜欢
    • 2014-07-15
    • 1970-01-01
    • 1970-01-01
    • 2017-01-22
    • 1970-01-01
    • 2014-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多