2012-02-07 11 views
5

Mam program wiosennej partii.dziwne zachowanie w wiosennej partii o implementacji polityki pomijania

Limit kontenerowego jest ustawiony na 5, a rozmiar fragmencie jest 1000.

mam pracę w dwóch etapach jak poniżej:

<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> 

Polityka kontenerowego jest jak poniżej:

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

SkipPolicy jest jak poniżej:

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; 
} 
} 

Dlatego dla każdego błędu występującego przed osiągnięciem limitu przeskoku, polityka pomijania zignoruje błąd (return true). Zadanie nie powiedzie się dla żadnego błędu po osiągnięciu limitu przeskoku.

Klasa mySkipListener jest jak poniżej:

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()); 
} 
} 

Teraz w myItemProcessor mam poniżej bloku kodu:

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

Dla niektórych przedmiotów Thenumber pole jest nieważne i tak powyżej kodu blok rzuca " Wyjątek "StringIndexOutofBounds".

Ale widzę dziwne zachowanie, którego nie rozumiem, dlaczego tak się dzieje.

We wszystkich znajduje się 6 elementów, które zawierają błąd, tzn. Pole Liczba jest puste.

Jeśli limit pominięcia jest większy niż liczba błędów (tj.> 6), wywoływane są klasy sys out w klasie pominięcia w pomijaniu i pomijane są błędy pomijane.

Jednakże, jeśli limit kontenerowego jest mniej (powiedzmy 5 jak w moim przykładzie), że osoba, sys w pominąć klasy słuchacza są nie uzyskiwanie nazywa w ogóle, a ja wprost coraz poniższego wyjątku zrzutu na konsoli:

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) 

Jaka jest przyczyna tego zachowania? Co powinienem zrobić, aby rozwiązać ten problem?

Dzięki za przeczytanie!

Odpowiedz

2

SkipListener jest używany tylko na końcu fragmentu, jeśli zawierający go plik kończy się normalnie. Jeśli masz więcej błędów niż limit pominięcia, który jest zgłaszany, przez wyjątek, który zobaczysz, a zadanie zostanie przerwane.

Jeśli liczba błędów jest mniejsza niż limit pominięcia, zadanie kończy się normalnie, a funkcja SkipListener jest wywoływana jeden raz dla każdego pominiętego wiersza lub elementu - Spring Batch tworzy listę wewnętrznie w miarę jej przesyłania, ale tylko raporty na końcu.

Pomysł, jeśli jest tak, że jeśli zadanie się nie powiedzie, prawdopodobnie spróbujesz go ponownie, więc wiedząc, co zostało pominięte podczas niekompletnego uruchomienia, nie jest przydatne, za każdym razem, gdy spróbujesz ponownie, otrzymasz to samo powiadomienie. Tylko jeśli wszystko inne się powiedzie, zobaczysz, co zostało pominięte. Imaging logujesz pominięte elementy, nie chcesz, aby były one logowane jako pomijane w kółko.

Jak można zauważyć, prostym rozwiązaniem jest ustawienie wystarczająco dużego limitu. Ponownie chodzi o to, że jeśli pominąć wiele elementów, prawdopodobnie istnieje poważniejszy problem.