2012-02-07 46 views
5

我有一个spring批处理程序。关于跳过策略执行的一批奇怪行为

跳跃限制设置为5,块大小为1000

我有两个步骤的工作如下:

<step id="myFileGenerator" next="myReportGenerator"> 
     <tasklet transaction-manager="jobRepository-transactionManager"> 
      <chunk reader="myItemReader" processor="myItemProcessor" writer="myItemWriter" commit-interval="1000" skip-policy="skipPolicy"/> 
     </tasklet> 
     <listeners> 
      <listener ref="mySkipListener"/> 
     </listeners> 
    </step> 

    <step id="myReportGenerator"> 
     <tasklet ref="myReportTasklet" transaction-manager="jobRepository-transactionManager"/> 
    </step> 

跳跃政策如下:

<beans:bean id="skipPolicy" class="com.myPackage.util.Skip_Policy"> 
    <beans:property name="skipLimit" value="5"/> 
</beans:bean> 

的SkipPolicy类是如下:

public class Skip_Policy implements SkipPolicy { 

private int skipLimit; 

public void setSkipLimit(final int skipLimit) { 
    this.skipLimit = skipLimit; 
} 

public boolean shouldSkip(final Throwable t, final int skipCount) throws SkipLimitExceededException { 

    if (skipCount < this.skipLimit) { 
     return true; 
    } 
    return false; 
} 
} 

因此,对于在达到跳转限制之前发生的任何错误,跳过策略将忽略错误(返回true)。在达到跳过限制后,作业将失败并出现任何错误。

的mySkipListener类是如下:

public class mySkipListener implements SkipListener<MyItem, MyItem> { 

public void onSkipInProcess(final MyItem item, final Throwable t) { 
    // TODO Auto-generated method stub 
    System.out.println("Skipped details during PROCESS is: " + t.getMessage()); 
} 

public void onSkipInRead(final Throwable t) { 

    System.out.println("Skipped details during READ is: " + t.getMessage()); 
} 

public void onSkipInWrite(final MyItem item, final Throwable t) { 
    // TODO Auto-generated method stub 
    System.out.println("Skipped details during WRITE is: " + t.getMessage()); 
} 
} 
在myItemProcessor

现在我有下面的代码块:

if (item.getTheNumber().charAt(4) == '-') { 
     item.setProductNumber(item.getTheNumber().substring(0, 3)); 
    } else { 
     item.setProductNumber("55"); 
    } 

对于一些项目数量写字段为空的,因此上面的代码块抛出“ StringIndexOutofBounds“异常。

但我看到一个奇怪的行为,我不明白它为什么会发生。

总共有6个项目有错误,即Number字段为空。

如果跳过限制大于错误数量(即> 6),则跳过监听器类中的系统输出将被调用,并且将报告跳过的错误。

然而,如果跳过上限不(比如说5在我的例子),在跳跃监听器类的SYS出局没有得到所谓的一切,我直接让控制台上的以下异常转储:

org.springframework.batch.retry.RetryException: Non-skippable exception in recoverer while processing; nested exception is java.lang.StringIndexOutOfBoundsException 
at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor$2.recover(FaultTolerantChunkProcessor.java:282) 
at org.springframework.batch.retry.support.RetryTemplate.handleRetryExhausted(RetryTemplate.java:416) 
at org.springframework.batch.retry.support.RetryTemplate.doExecute(RetryTemplate.java:285) 
at org.springframework.batch.retry.support.RetryTemplate.execute(RetryTemplate.java:187) 

这种行为背后的原因是什么?我该怎么做才能解决这个问题?

感谢您的阅读!

回答

2

如果包含它的任务小程序正常完成,SkipListener仅用于块的末尾。当出现比跳过限制更多的错误时,通过您看到的异常报告该错误,并且中止该任务小程序。

如果错误数小于skip-limit,那么tasklet会正常结束,并且SkipListener会针对每个跳过的行或项目调用一次 - Spring Batch会在其内部建立一个内部列表,但只会报告最后。

这个想法是,如果任务失败,您可能会重试它,因此了解在不完整运行期间跳过的内容没有用,每次重试时都会得到相同的通知。只有在其他一切成功的情况下,你才能看到跳过的内容。您正在记录被跳过的项目的成像,您不希望它们被一次又一次地跳过记录。

正如你所看到的,简单的解决方案是使skip-limit足够大。同样的想法是,如果你不得不跳过很多物品,那么可能会有更严重的问题。