使用异步任务管理器处理作业/步骤异常



我找不到在异步上下文中处理弹簧批处理异常的正确方法。

当我为JobLauncher设置ThreadPoolTaskManager时,不再记录真正的作业/步骤异常。相反,日志将如下所示:

org.springframework.batch.core.JobInterruptedException: Job interrupted by step execution
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:165)
at ...

我试图解决这个问题,添加一个这样的JobExecutionListener

@Override
public void afterJob(JobExecution jobExecution) {
    List<Throwable> jobExceptions = jobExecution.getFailureExceptions();
    if (CollectionUtils.isNotEmpty(jobExceptions)) {
        Throwable lastJobException = jobExceptions.get(jobExceptions.size() - 1);
        LOGGER.error("Spring-Batch error at job level", lastJobException);
        String lastJobExceptionMessage = ExceptionUtils.getRootCauseMessage(lastJobException);
        // storing message in ExecutionContext for the batch-admin webapp
        String message = "";
        if (jobExecution.getExecutionContext().get(Consts.JOB_EXECUTION_MESSAGE_KEY) != null) {
            message = jobExecution.getExecutionContext().getString(Consts.JOB_EXECUTION_MESSAGE_KEY);
        }
        message += "n" + lastJobExceptionMessage;
        jobExecution.getExecutionContext().put(Consts.JOB_EXECUTION_MESSAGE_KEY, message);
    }
}

但我仍然以JobInterruptedException结束.有没有办法检索中断的初始原因(可能是读取器/处理器/写入器代码中的错误?

我认为你的诊断不正确。该异常仅在SimpleStepHandler中与该错误消息一起引发:

if (currentStepExecution.getStatus() == BatchStatus.STOPPING
        || currentStepExecution.getStatus() == BatchStatus.STOPPED) {
    // Ensure that the job gets the message that it is stopping
    execution.setStatus(BatchStatus.STOPPING);
    throw new JobInterruptedException("Job interrupted by step execution");
}

并且只有在步骤本身没有扔JobInterruptedException的情况下.发生这种情况的最明显情况是作业已停止。请参阅此示例,其输出以

信息:执行步骤:[步骤1]2016-2-24下午01:25:02 org.springframework.batch.core.repository.support.SimpleJobRepository checkForInterruption信息:父作业执行已停止,因此将消息传递给步骤执行2016-2-24下午01:25:02 org.springframework.batch.core.step.ThreadStepInterruptionPolicy isInterrupted信息:通过步骤执行中断的步骤2016-2-24下午01:25:02 org.springframework.batch.core.step.AbstractStep execute信息:在作业 myJob 中执行步骤 1 时遇到中断:检测到作业中断状态。2016-2-24下午01:25:02 org.springframework.batch.core.repository.support.SimpleJobRepository checkForInterruption信息:父作业执行已停止,因此将消息传递给步骤执行2016-2-24下午01:25:02 org.springframework.batch.core.job.AbstractJob execute信息:遇到中断执行作业:作业被步骤执行中断2016-2-24下午01:25:02 org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run信息:作业:[简单作业:[名称=我的作业]]已完成,参数如下:[{}]和以下状态:[已停止]状态为:已停止

另一个示例显示,在使用线程池时引发异常不会改变任何内容。最终输出为

信息:执行步骤:[步骤1]2016-2-24下午01:28:44 org.springframework.batch.core.step.AbstractStep executeSEVERE:在作业 myJob 中执行步骤 1 时遇到错误java.lang.RuntimeException: My exception    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)(...)2016-2-24下午01:28:44 org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run信息:作业:[简单作业:[名称=我的作业]]已完成,参数如下:[{}]和以下状态:[失败]状态为:失败,作业执行 ID 0  #1 步骤 1 失败步骤步骤1java.lang.RuntimeException: My exception    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)(...)

所以答案是如此简单,而不是当我理解它时感到非常愚蠢:@Artefacto是对的。作业已停止。在过程结束时。因为它到达了main()方法的末尾。

当我使用 ThreadPoolTaskManager 切换到异步模式时,我忘了在我的主方法中添加一个非常重要的行:

    // Wait for the end of the JobExecution
    main.endOfJobLatch.await();

希望这个答案能帮助其他人...

最新更新