spring批处理:跳过后处理器调用两次

时间:2016-01-04 11:07:25

标签: spring-batch

我有一个定义的块,其commit-interval为10,skip-limit为10.处理器类通过应用一些算术运算来操作一个字段。在处理器类中,其中一条记录发生异常(例如第6条记录)。在此之后,再次处理从1到5的记录,跳过第6个,处理7-10个并写入XML(自定义XML编写器类)。由于处理器处理1-5次记录两次,因此预期的字段值是错误的,因为它被计算两次。您能否建议一个解决方案让处理器只处理一次记录,只跳过失败的记录并将处理过的记录写入XML?

使用onSkipInProcess(),onSkipInRead(),onSkipInWrite()实现了SkipListener。但输出仍然相同。

jobconfig.xml

<batch:job id="job">
    <batch:step id="step">
        <batch:tasklet>
            <batch:chunk reader="itemReader" writer="itemWriter" 
                processor="itemProcessor" commit-interval="10" skip-limit="5" retry-limit="0" >
                <batch:skippable-exception-classes>
                    <batch:include class="java.lang.Exception"/>
                </batch:skippable-exception-classes>
                <batch:listeners>
                    <batch:listener ref="skipListener" />
                </batch:listeners>
            </batch:chunk>
        </batch:tasklet>
    </batch:step>
</batch:job>  
<bean id="itemWriter" class="a.b.XWriter" scope="step"/>
<bean id="skipListener" class="a.b.SkipListener"/>
<bean id="itemProcessor" class="a.b.XProcessor" scope="step"/>
<bean id="itemReader" class="a.b.XReader"/>

ItemReader类:

public class XReader implements ItemReader {
@Autowired
private XRepository classDao;

private List lst = new ArrayList();
private int index= 0;

public Object read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
    if (lst.isEmpty()) {
           lst = classDao.findAll();
    } 
    if (index < lst.size()) {
        return lst.get(index++);
    } else return null;

}
}

ItemProcessor类:

public class XProcessor<T> implements ItemProcessor<T, T> {
public Object process(Object item) throws Exception {
    // logic here
}

ItemWriter类:

public class XWriter <T> implements ItemWriter<T> {
public void write(List<? extends T> items) throws Exception {
    // logic here to write to XML
}}

SkipListener类:

public class SkipListener<T,S> implements org.springframework.batch.core.SkipListener<T, S> {

public void onSkipInProcess(T arg0, Throwable arg1) {
}

public void onSkipInRead(Throwable arg0) {
}

public void onSkipInWrite(S arg0, Throwable arg1) {
}

}

2 个答案:

答案 0 :(得分:2)

在容错步骤中使用ItemProcessor时,它们应该是幂等的,因为存在多次调用它们的风险(如示例所示)。您可以在此处文档的第6.3.3节中详细了解这一点:http://docs.spring.io/spring-batch/reference/html/readersAndWriters.html

答案 1 :(得分:0)

您需要具有如下所示的侦听器实现。每当发生一些异常时,它会调用相应的方法,如果需要,您可以处理,否则只需将方法保留为空。所以它不会失败。

它也不会两次调用处理器。

xml配置:

<batch:listeners>
                    <batch:listener ref="recordSkipListener"/>
                  </batch:listeners>

听众课程:

public class RecordSkipListener implements SkipListener<Model> {



    @Override
    public void onSkipInRead(Throwable t) {


    }

    @Override
    public void onSkipInWrite(Model item, Throwable t) {

    }

    @Override
    public void onSkipInProcess(Model item, Throwable t) {


    }
}