2012-02-07 6 views
5

Ho un programma batch in primavera.strano comportamento nel batch di primavera sull'implementazione della politica di salto

Il limite di salto è impostato a 5 e la dimensione del blocco è 1000.

ho un lavoro con due fasi come sotto:

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

La politica salto è come qui sotto:

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

Lo SkipPolicy è la seguente:

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

Pertanto, per qualsiasi errore verificatosi prima del raggiungimento del limite di salto, il criterio di salto ignorerà l'errore (restituisce true). Il processo avrà esito negativo per qualsiasi errore dopo il raggiungimento del limite di salto.

La classe mySkipListener è come qui sotto:

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

Ora in myItemProcessor devo sotto blocco di codice:

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

Per alcuni degli elementi Thenumber campo è nullo e quindi sopra il codice di blocco tiri " StringIndexOutofBounds "eccezione.

Ma sto vedendo uno strano comportamento che non capisco perché sta accadendo.

In tutto ci sono 6 articoli che hanno errori, cioè il campo Numero è nullo.

Se il limite di salto è maggiore del numero di errori (ad esempio> 6), vengono richiamati i sistemi nella classe skip listener e vengono segnalati gli errori saltati.

Tuttavia, se il limite di salto è inferiore (per esempio 5, come nel mio esempio), le uscite sys in classe ascoltatore salto non sono sempre chiamati a tutti e io sono sempre direttamente la discarica eccezione di seguito su console:

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) 

Qual è la ragione di questo comportamento? Cosa dovrei fare per risolvere questo?

Grazie per la lettura!

risposta

2

SkipListener viene utilizzato solo alla fine del blocco, se il tasklet che lo contiene termina normalmente. Quando si verificano più errori rispetto al limite di salto, ciò viene segnalato, tramite l'eccezione che si vede, e l'attività viene interrotta.

Se il numero di errori è inferiore al limite di salto, il tasklet termina normalmente e lo SkipListener viene richiamato una volta per ogni riga o elemento saltato - Spring Batch crea un elenco di essi internamente mentre procede, ma solo i report alla fine.

L'idea se questo è che, se l'operazione non riesce che si sta, probabilmente, ha intenzione di riprovare, in modo da sapere cosa ma ho saltato durante una corsa incompleta non è utile, ogni volta che si riprovare si otterrà la stessa notifica. Solo se tutto il resto ha successo, puoi vedere cosa è stato saltato. Immaginando di registrare gli elementi saltati, non vuoi che vengano registrati come saltati più e più volte.

Come hai visto, la soluzione semplice è di rendere il limite di skip sufficientemente ampio. Di nuovo l'idea è che se devi saltare un sacco di elementi, probabilmente c'è un problema più serio.