【问题标题】:spring batch: processor called twice after skip春季批处理:跳过后调用两次处理器
【发布时间】:2016-04-07 23:34:11
【问题描述】:

我定义了一个块,提交间隔为 10,跳过限制为 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) {
}

}

【问题讨论】:

  • 你有实现SkipListener的监听类吗?是你的处理器scope=step?
  • 您是否尝试将retry-limit 设置为0?
  • scope="step" 和 retry-limit 只给出相同的结果

标签: spring-batch


【解决方案1】:

在容错步骤中使用ItemProcessors 时,它们应该是幂等的,因为它们有可能被多次调用(如您的示例所示)。您可以在此处的文档第 6.3.3 节中阅读更多相关信息:http://docs.spring.io/spring-batch/reference/html/readersAndWriters.html

【讨论】:

    【解决方案2】:

    你需要有一个像下面这样的监听器实现。每当发生异常时,它都会调用相应的方法,如果需要,您可以处理,否则只需将该方法留空。所以它不会失败。

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

    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) {
    
    
        }
    }
    

    【讨论】:

    • 是的,我已经这样做了。但仍然存在同样的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-15
    • 2018-05-27
    • 2015-05-13
    • 2017-06-25
    • 1970-01-01
    • 2018-04-03
    相关资源
    最近更新 更多