在Spring Batch中使用单步批处理作业结束

时间:2017-11-07 13:39:28

标签: java spring-batch

我们已经单步配置了批处理作业。一般结构如,

<batch:job id="mainJob">
    <batch:step id="step1">
        <batch:tasklet>
            <batch:chunk reader="fileReader" writer="jmsItemWriter" >
                <batch:retryable-exception-classes>
                    <batch:include class="org.springframework.dao.CannotAcquireLockException"/>
                </batch:retryable-exception-classes>
            </batch:chunk>
        </batch:tasklet>
        <batch:end on="UNKNOWN"/>
        <batch:next on="*" to="step1"/>
        <batch:listeners>
            <batch:listener ref="listener1"/>
            <batch:listener ref="listener2"/>
        </batch:listeners>

    </batch:step>
   <batch:listeners>
        <batch:listener ref="jobListener"/>
   </batch:listeners>
  </batch:job>

fileReader是FlatFileItemReader,它逐行读取文件并将每一行传递给&#39; listener2&#39;。在listener2中,如果行中有错误,则应将状态设置为“未知”。 (没有失败,因为工作不应该再次开始)然后停止工作。

要做到这一点,我们有。

<batch:end on="UNKNOWN"/>
<batch:next on="*" to="step1"/>

但批处理作业不会以未知结束并因为下一步而进入循环。如果&#39; next&#39;则会有例外。没有提到。

我们如何解决这个问题?

编辑:

对Dean的回答有更多解释。

Listener2逐行获取FieldSet即文件条目。处理这些条目时,如果满足某些条件(也涉及数据库查询),则作业不应读取更多文件并停止。由于处理是在覆盖方法中完成的,因此mapFieldSet&#39;它不会抛出任何异常,不能使用新的异常,返回null只读取下一行。通常,文件有数千行,但在前2行中,确定是否需要进一步读取。

1 个答案:

答案 0 :(得分:0)

你所做的非常不合标准。这就是我要做的......

  • 删除侦听器2(这不是应该如何处理错误)
  • 验证是否在ItemProcessor中进行,而不是等待JMS编写器失败
  • 抛出异常或从处理器返回null以获取无效项
  • 创建一个异常侦听器(StepExecutionListener),用于检查失败异常并翻转ExitStatus

示例步骤执行侦听器afterStep方法:

public ExitStatus afterStep(StepExecution stepExecution) {
    for (Throwable t : stepExecution.getFailureExceptions()) {
        if ("EXPECTED MESSAGE".equals(t.getMessage())) {
            return ExitStatus.UNKNOWN;
        }
     }
    return null;
}

根据问题中的新信息进行更新

根据您的指示,似乎Decider可能实际上是您最干净的解决方案。

对工作流程的修改:

<batch:job id="mainJob">
    <batch:decision id="decision" decider="someDecider">
        <next on="PROCESS" to="step1" />
        <end on="STOP" />
        <fail on="*" />
    </batch:decision>
    <batch:step id="step1">
        <!-- . . . -->
    </batch:step>
    <!-- . . . -->
</batch:job>

示例Decider类:

public class ProcessFileDecider implements JobExecutionDecider {

    private Resource resource;

    @Override
    public FlowExecutionStatus decide(final JobExecution jobExecution, final StepExecution stepExecution) {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()))) {
            final String lineOne = reader.readLine();
            final String lineTwo = (lineOne != null) ? reader.readLine() : null;

            final boolean processFile = true; //some logic here
            if (processFile) {
                return new FlowExecutionStatus("PROCESS");
            }
            return new FlowExecutionStatus("STOP");

        } catch (final IOException e) {
            throw new IllegalStateException("Hit error deciding whether to process the resource!", e);
        }
    }

    public void setResource(Resource resource) {
        this.resource = resource;
    }

}