我是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);
...
}
}
我尝试将<end on="*" exit-status="COMPLETED"/>
添加到JSL中的<job>
和<flow>
,但这没有效果或导致状态为FAILED。
答案 0 :(得分:3)
好问题。让我谈谈@ cheng的答案。
首先,要理解为什么我们以这种方式实现它,请考虑JobListener抛出异常的情况。这会失败吗?在Liberty,我们决定应该这样做。但是,如果作业已经具有COMPLETED
状态,那么这意味着它已经完成,并且不应该在那时失败。
所以afterJob()
更像是“工作结束”(或者你可以把它想象成“在工作步骤之后”)。
其次,甚至提出这个问题的一个原因是因为你想在afterJob()
方法中知道作业是否成功执行。
好吧,至少在Liberty实现中(我为IBM工作),你确实可以看到这一点。之前的失败会将 BatchStatus 设置为FAILED
,而成功(此处)执行的状态仍为STARTED
。
(对于它的价值,这是我们意识到的一个领域,在1.0规范的努力中可能会使用更多的关注和标准化,我希望将来可以解决更多问题。)
如果它有帮助且你感兴趣,你可以看到流程中的基本逻辑,包括WorkUnitThreadControllerImpl.endOfWorkUnit
来电here。
答案 1 :(得分:2)
这是因为工作监听器的afterJob
方法是作业执行的一部分。因此,当您在getBatchStatus()
方法中调用afterJob()
时,作业执行仍在继续,但尚未完成,因此批处理状态为STARTED
。