使用异步TaskManager

时间:2016-02-24 11:01:47

标签: java asynchronous exception-handling spring-batch

我找不到在异步上下文中处理spring-batch异常的正确方法。

当我将ThreadPoolTask​​Manager设置为JobLauncher时,不再记录真正的作业/步骤异常。相反,日志将类似于:

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结束。 有没有办法检索中断的初始原因(可能是读取器/处理器/编写器代码中的错误?

谢谢,

西里尔

2 个答案:

答案 0 :(得分:1)

我认为您的诊断不正确。仅在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时。最明显的情况是,如果工作停止了。请参阅this example,其输出以

结尾
INFO: Executing step: [step1]
Feb 24, 2016 1:25:02 PM org.springframework.batch.core.repository.support.SimpleJobRepository checkForInterruption
INFO: Parent JobExecution is stopped, so passing message on to StepExecution
Feb 24, 2016 1:25:02 PM org.springframework.batch.core.step.ThreadStepInterruptionPolicy isInterrupted
INFO: Step interrupted through StepExecution
Feb 24, 2016 1:25:02 PM org.springframework.batch.core.step.AbstractStep execute
INFO: Encountered interruption executing step step1 in job myJob : Job interrupted status detected.
Feb 24, 2016 1:25:02 PM org.springframework.batch.core.repository.support.SimpleJobRepository checkForInterruption
INFO: Parent JobExecution is stopped, so passing message on to StepExecution
Feb 24, 2016 1:25:02 PM org.springframework.batch.core.job.AbstractJob execute
INFO: Encountered interruption executing job: Job interrupted by step execution
Feb 24, 2016 1:25:02 PM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [SimpleJob: [name=myJob]] completed with the following parameters: [{}] and the following status: [STOPPED]
Status is: STOPPED

This other example表明在使用线程池时抛出异常不会改变任何内容。最终输出是

INFO: Executing step: [step1]
Feb 24, 2016 1:28:44 PM org.springframework.batch.core.step.AbstractStep execute
SEVERE: Encountered an error executing step step1 in job myJob
java.lang.RuntimeException: My exception
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
(...)

Feb 24, 2016 1:28:44 PM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [SimpleJob: [name=myJob]] completed with the following parameters: [{}] and the following status: [FAILED]
Status is: FAILED, job execution id 0
  #1 step1 FAILED
Step step1
java.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)
(...)

答案 1 :(得分:0)

所以当我理解答案时,答案非常简单: @Artefacto是对的。工作停止了。到过程结束。因为它到达了main()方法的末尾。

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

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

希望这个答案可以帮助别人...