2012-02-07 80 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足夠大。同樣的想法是,如果你不得不跳過很多物品,那麼可能會有更嚴重的問題。