JSR-352 Java 批处理:为什么 JobListener.afterJob() 总是获得批处理状态 STARTED?

JSR-352 Java Batch: why does JobListener.afterJob() always get batch status STARTED?

我是 Java 批处理新手。我在 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);
        ...
    }
}

我尝试将 <end on="*" exit-status="COMPLETED"/> 添加到 JSL 中的 <job><flow>,但这没有效果或导致状态失败。

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

好问题。让我针对@cheng 的回答强调几点。

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

所以 afterJob() 实际上更像 "end of job"(或者你可以把它想象成 "after job steps")。

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

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

(就其价值而言,这是我们意识到在 1.0 规范工作的后期需要更多关注和标准化的一个领域,我希望我们能在未来解决更多问题。)

如果对您有帮助并且您感兴趣,您可以查看导致并包括 WorkUnitThreadControllerImpl.endOfWorkUnit 调用 here.

的流程中的基本逻辑