Configurazione della logica di salto in Spring Batch

1. Introduzione

Per impostazione predefinita, qualsiasi errore riscontrato durante l'elaborazione di un processo Spring Batch farà fallire un passaggio corrispondente. Tuttavia, ci sono molte situazioni in cui preferiremmo saltare l'elemento attualmente elaborato per alcune eccezioni.

In questo tutorial, esploreremo due approcci per configurare la logica di salto nel framework Spring Batch.

2. Il nostro caso d'uso

Ai fini degli esempi, riutilizzeremo un lavoro semplice e orientato ai blocchi presentato già nel nostro articolo introduttivo di Spring Batch.

Questo lavoro converte alcuni dati finanziari da un formato CSV a XML.

2.1. Dati in ingresso

Innanzitutto, aggiungiamo alcune righe al file CSV originale:

username, user_id, transaction_date, transaction_amount devendra, 1234, 31/10/2015, 10000 john, 2134, 3/12/2015, 12321 robin, 2134, 2/02/2015, 23411 , 2536, 3/10/2019, 100 mike, 9876, 5/11/2018, -500 , 3425, 10/10/2017, 9999

Come possiamo vedere, le ultime tre righe contengono dati non validi: nelle righe 5 e 7 manca il campo del nome utente e l'importo della transazione nella riga 6 è negativo.

Nelle sezioni successive, configureremo il nostro lavoro batch per saltare questi record danneggiati.

3. Configurazione del limite di salto e delle eccezioni ignorabili

3.1. Utilizzo di skip e skipLimit

Discutiamo ora il primo dei due modi per configurare il nostro lavoro per saltare gli elementi in caso di errore: i metodi skip e skipLimit :

@Bean public Step skippingStep( ItemProcessor processor, ItemWriter writer) throws ParseException { return stepBuilderFactory .get("skippingStep") .chunk(10) .reader(itemReader(invalidInputCsv)) .processor(processor) .writer(writer) .faultTolerant() .skipLimit(2) .skip(MissingUsernameException.class) .skip(NegativeAmountException.class) .build(); }

Prima di tutto, per abilitare la funzionalità di salto, dobbiamo includere una chiamata a faultTolerant () durante il processo di creazione dei passaggi.

All'interno di skip () e skipLimit () , definiamo le eccezioni che vogliamo ignorare e il numero massimo di elementi ignorati.

Nell'esempio precedente, se viene generata un'eccezione MissingUsernameException o NegativeAmountException durante la fase di lettura, elaborazione o scrittura, l'elemento attualmente elaborato verrà omesso e conteggiato rispetto al limite totale di due.

Di conseguenza, se un'eccezione viene lanciata una terza volta, l'intero passaggio fallirà .

3.1. Utilizzando noSkip

Nell'esempio precedente, qualsiasi altra eccezione oltre a MissingUsernameException e NegativeAmountException rende il nostro passaggio non riuscito.

In alcune situazioni, tuttavia, potrebbe essere più appropriato identificare le eccezioni che dovrebbero far fallire il nostro passaggio e saltare qualsiasi altro.

Vediamo come possiamo configurarlo usando skip , skipLimit e noSkip :

@Bean public Step skippingStep( ItemProcessor processor, ItemWriter writer) throws ParseException { return stepBuilderFactory .get("skippingStep") .chunk(10) .reader(itemReader(invalidInputCsv)) .processor(processor) .writer(writer) .faultTolerant() .skipLimit(2) .skip(Exception.class) .noSkip(SAXException.class) .build(); }

Con la configurazione precedente, istruiamo il framework Spring Batch a saltare qualsiasi eccezione (entro un limite configurato) eccetto SAXException . Ciò significa che SAXException causa sempre un errore di passaggio.

L'ordine delle chiamate skip () e noSkip () non ha importanza.

4. Utilizzo di SkipPolicy personalizzato

A volte potrebbe essere necessario un meccanismo di controllo dei salti più sofisticato. A tale scopo, il framework Spring Batch fornisce l' interfaccia SkipPolicy .

Possiamo quindi fornire la nostra implementazione della logica di salto e inserirla nella nostra definizione del passaggio.

Tenendo presente l'esempio precedente, immagina di voler ancora definire un limite di salto di due elementi e rendere ignorabili solo MissingUsernameException e NegativeAmountException .

Tuttavia, un ulteriore vincolo è che possiamo saltare NegativeAmountException, ma solo se l'importo non supera un limite definito .

Implementiamo la nostra SkipPolicy personalizzata :

public class CustomSkipPolicy implements SkipPolicy { private static final int MAX_SKIP_COUNT = 2; private static final int INVALID_TX_AMOUNT_LIMIT = -1000; @Override public boolean shouldSkip(Throwable throwable, int skipCount) throws SkipLimitExceededException { if (throwable instanceof MissingUsernameException && skipCount < MAX_SKIP_COUNT) { return true; } if (throwable instanceof NegativeAmountException && skipCount < MAX_SKIP_COUNT ) { NegativeAmountException ex = (NegativeAmountException) throwable; if(ex.getAmount() < INVALID_TX_AMOUNT_LIMIT) { return false; } else { return true; } } return false; } }

Ora possiamo utilizzare la nostra politica personalizzata in una definizione di passaggio:

 @Bean public Step skippingStep( ItemProcessor processor, ItemWriter writer) throws ParseException { return stepBuilderFactory .get("skippingStep") .chunk(10) .reader(itemReader(invalidInputCsv)) .processor(processor) .writer(writer) .faultTolerant() .skipPolicy(new CustomSkipPolicy()) .build(); }

E, analogamente al nostro esempio precedente, dobbiamo ancora usare faultTolerant () per abilitare la funzionalità di salto.

Questa volta, tuttavia, non chiamiamo skip () o noSkip () . Invece, utilizziamo il metodo skipPolicy () per fornire la nostra implementazione dell'interfaccia SkipPolicy .

Come possiamo vedere, questo approccio ci offre una maggiore flessibilità, quindi può essere una buona scelta in alcuni casi d'uso .

5. conclusione

In questo tutorial, abbiamo presentato due modi per rendere un lavoro Spring Batch tollerante ai guasti.

Anche se l'uso di uno skipLimit () insieme ai metodi skip () e noSkip () sembra essere più popolare, potremmo trovare più conveniente implementare uno SkipPolicy personalizzato in alcune situazioni.

Come al solito, tutti gli esempi di codice sono disponibili su GitHub.