SkipListener不按顺序处理事件

时间:2014-11-21 08:51:52

标签: spring logging batch-processing spring-batch error-logging

我有一个弹出批处理作业,它使用SkipListener将任何错误输出到错误文件。在步骤(读取,处理,写入)期间可能发生各种类型的错误,并且跳过侦听器知道如何处理它们。这工作正常。

但是,我注意到错误正在按顺序写入输出。这意味着处理器的错误似乎是在读者发现任何错误之前写的。

这引起了我的极大关注,因为我需要错误要以读取的相同顺序写出(您会注意到跳过限制是疯狂的高和commit-interval是1所以它不是分块的问题。出于所有实际目的,这是一项非常平凡的工作,并且不会做任何会让我相信它在实际读者或处理器中导致这种情况发生的事情。

整件事令我感到困惑;这很奇怪。我希望有人可以指出我如何解决这个问题的正确方向。即使答案是“就是这样,你也无法改变它。”

以下是工作定义的相关部分:

<job id="devJob" xmlns="http://www.springframework.org/schema/batch">
    ... some steps ...
    <step id="devProcessStep" next="REMOVED_FOR_SO">
        <tasklet>
            <chunk reader="devFileReader" processor="devItemProcessor" writer="devOutputWriter" commit-interval="1" skip-limit="999999">
                <streams>
                    <stream ref="devInputReaderStream" />
                    <stream ref="devErrorOutputWriterStream" />
                    <stream ref="devOutputWriterStream" />
                </streams>
                <skippable-exception-classes>
                    <include class="org.springframework.batch.item.ItemReaderException"/>
                    ... others, but removed since it doesn't matter for this question ...
                    <exclude class="org.springframework.batch.item.NonTransientResourceException"/>
                </skippable-exception-classes>
            </chunk>
            <listeners>
                <listener ref="devSkipListener" />
            </listeners>
        </tasklet>
    </step>
    ... more steps ...
</job>
...
<bean id="devSkipListener" class="you.have.to.guess.DevSkipListener" scope="job">
    <property name="writer" ref="devErrorOutputWriterStream" />
    ... other properties that are based on job parameters ...
</bean>
...
<bean id="devErrorOutputWriter"
    class="org.springframework.batch.item.file.FlatFileItemWriter" scope="job">
    ... a bunch of properties based on job parameters etc.
</bean>

这里是SkipListener,只包含相关部分(注意我使用的是Groovy而不是Java,因为这是Grails应用程序)

package you.have.to.guess
// bunch of imports (removed for SO)
class DevSkipListener implements SkipListener {

    private static def log = LogFactory.getLog(this)
    ItemWriter writer
    // some other properties, not important

    @Override
    void onSkipInRead(Throwable e) {
        log.debug("Skip error in read", e)
        // some stuff here to figure out the lines
        writer.write(lines)
    }

    @Override
    void onSkipInProcess(Object item, Throwable e) {
        log.debug("Skip error in process", e)
        // some stuff here to figure out the lines
        writer.write(lines)
    }

    @Override
    void onSkipInWrite(Object item, Throwable e) {
        log.debug("Skip error in write", e)
        // some stuff here to figure out the lines
        writer.write(lines)
    }
}

1 个答案:

答案 0 :(得分:1)

简而言之,SkipListener的合同并不保证要处理的项目的顺序。只有每次跳过都会调用一次侦听器上的方法。