Spring Batch Step不执行

时间:2016-05-05 15:42:42

标签: spring spring-batch

我试图解决最近困扰我们系统的Spring Batch中的一个问题。我们有一份工作,大部分工作都很好。这是一个下载和处理数据的多步骤工作。

问题是有时这项工作会爆炸。也许我们尝试连接的服务器会抛出错误,或者我们在作业中间关闭服务器。此时,下次我们的石英调度程序尝试运行时,它似乎无法执行任何操作。以下是此职位定义的简略版本:

<batch:job id="job.download-stuff" restartable="true">
<batch:validator ref="downloadValidator"/>
<batch:step id="job.download-stuff.download">
    <batch:tasklet ref="salesChannelOrderDownloader" transaction-manager="transactionManager">
        <batch:transaction-attributes isolation="READ_UNCOMMITTED" propagation="NOT_SUPPORTED"/>
        <batch:listeners>
            <batch:listener ref="downloadListener"/>
            <batch:listener ref="loggingContextStepListener" />
        </batch:listeners>
    </batch:tasklet>
    <batch:next on="CONTINUE" to="job.download-stuff.process-stuff.step" />
    <batch:end on="*" />
</batch:step>
<batch:step id="job.download-stuff.process-stuff.step">
    ...
</batch:step>
<batch:listeners>
    <batch:listener ref="loggingContextJobListener"/>
</batch:listeners>

一旦进入此状态,downloadValidator就会运行,但它永远不会进入第一步download-stuff.download。我在tasklet中设置了一个断点,它永远不会在里面。

如果我清除了存储在我们的mysql数据库中的所有弹簧批处理表,并重新启动服务器,它将重新开始工作,但我还要明白是什么阻止它在这一点,而不是采用焦土战术来推动工作。

我是Spring Batch的新手,温和地说,如果我省略重要细节,请原谅我。我设置了断点并开启了记录以了解我能做什么。

到目前为止,我通过数据库观察到的是条目似乎不再写入BATCH_STEP_EXECUTION和BATCH_JOB_EXECUTION表。

作业中没有BATCH_JOB_EXECUTION条目未处于COMPLETED状态且没有未完成的BATCH_STEP_EXECUTION条目

您将看到有一个批处理:验证器已定义,我已确认spring批处理调用验证器并且它成功完成(设置断点并逐步完成)。第一步没有执行。

loggingContextJobListener和loggingContextStepListener似乎都没有触发。可能导致这种情况的原因是什么?

更新 我仔细研究了作为批处理者添加的downloadListener:监听器。这是afterStep的源代码:

@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public ExitStatus afterStep(StepExecution stepExecution) {
    long runSeconds = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - nanoStart);

    // If Success - we're good
    if (stepExecution.getStatus() == BatchStatus.COMPLETED) {
        Long endTs = stepExecution.getExecutionContext().getLong("toTime");
        Date toTime = new Date(endTs);
        handleSuccess(toTime, stepExecution.getWriteCount());
        return null;
    }

    // Otherwise - record errors
    List<Throwable> failures = stepExecution.getFailureExceptions();
    handleError(failures);
    return ExitStatus.FAILED;
}

我确认执行了return ExitStatus.FAILED行,并且在failureExceptions中记录了引发的异常。似乎一旦发生BATCH_JOB_EXECUTION条目处于COMPLETED状态(和exit_code)并且STEP_EXECUTION失败。

此时,BATCH_JOB_EXECUTION_PARAMS表中的条目仍然存在。我实际上尝试修改其KEY_NAME和值列的值,但这仍然不允许作业运行。 只要有参数绑定到JOB_EXECUTION_ID,属于同一BATCH_JOB_INSTANCE的另一个作业就无法运行。

删除 BATCH_JOB_EXECUTION_PARAMS 中针对该特定JOB_EXECUTION_ID的条目后,即使所有BATCH_JOB_EXECUTION条目都处于已完成状态,也可以运行另一个 BATCH_JOB_EXECUTION

所以我猜我有两个问题 - 这是正确的行为吗?如果是这样,是什么阻止了BATCH_JOB_EXECUTION_PARAMS的删除以及如何删除它们?

2 个答案:

答案 0 :(得分:2)

JobParametersValidator,在你的情况下,downloadValidator bean在作业开始之前运行。

在您的情况下发生的事情是您传递的工作参数与“炸毁”JobInstance相同。但是,由于这项工作以戏剧性的方式失败,它可能没有陷入失败的状态。

您可以使用不同的参数运行作业(以获取新的作业实例),也可以在重新启动之前尝试将BATCH_STEP_EXECUTION或BATCH_JOB_EXECUTION中的前一步/作业的状态更新为FAILED。

更新(新信息已添加至问题) 你必须小心你的工作流程。是的,您的步骤失败,但您的上下文文件表明该作业应END(完成)除CONTINUE以外的任何内容。

<batch:next on="CONTINUE" to="job.download-stuff.process-stuff.step" />
<batch:end on="*" />

首先,要非常小心结束*。在您的方案中,它导致您完成ExitCode FAILED的{​​{1}}工作(“成功”)。此外,成功步骤的默认ExitCodeCOMPLETED,而非CONTINUE,因此请小心。

<!-- nothing to me indicates you'd get CONTINUE here, so I changed it -->
<batch:next on="COMPLETED" to="job.download-stuff.process-stuff.step" />

<!-- if you ever have reason to stop here -->
<batch:end on="END" /> 

<!-- always fail on anything unexpected -->
<batch:fail on="*" />

答案 1 :(得分:1)

如果出现同样的问题,在测试/调试过程中我保持作业名称和参数相同,请确保更改作业名称或作业参数以获得不同的JobExecution