Configuration de la logique de saut dans Spring Batch

1. Introduction

Par défaut, toute erreur rencontrée lors du traitement d'un travail Spring Batch entraînera l'échec d'une étape correspondante. Cependant, il existe de nombreuses situations dans lesquelles nous préférerions ignorer l'élément actuellement traité pour certaines exceptions.

Dans ce didacticiel, nous explorerons deux approches pour configurer la logique de saut dans le framework Spring Batch.

2. Notre cas d'utilisation

À des fins d'exemples, nous réutiliserons un travail simple, orienté bloc, présenté déjà dans notre article d'introduction Spring Batch.

Ce travail convertit certaines données financières d'un format CSV au format XML.

2.1. Des données d'entrée

Tout d'abord, ajoutons quelques lignes au fichier CSV d'origine:

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

Comme nous pouvons le voir, les trois dernières lignes contiennent des données non valides - les lignes 5 et 7 ne contiennent pas le champ du nom d'utilisateur et le montant de la transaction à la ligne 6 est négatif.

Dans les sections suivantes, nous allons configurer notre travail par lots pour ignorer ces enregistrements corrompus.

3. Configuration de la limite de saut et des exceptions désactivables

3.1. Utilisation de skip et skipLimit

Discutons maintenant de la première des deux façons de configurer notre travail pour ignorer les éléments en cas d'échec - les méthodes skip et 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(); }

Tout d'abord, pour activer la fonctionnalité de saut, nous devons inclure un appel à faultTolerant () pendant le processus de construction de l'étape.

Dans skip () et skipLimit () , nous définissons les exceptions que nous voulons ignorer et le nombre maximum d'éléments ignorés.

Dans l'exemple ci-dessus, si une exception MissingUsernameException ou NegativeAmountException est lancée pendant la phase de lecture, de traitement ou d'écriture, l'élément actuellement traité sera omis et compté dans la limite totale de deux.

Par conséquent, si une exception est levée une troisième fois, l'étape entière échouera .

3.1. Utilisation de noSkip

Dans l'exemple précédent, toute autre exception en plus de MissingUsernameException et NegativeAmountException fait échouer notre étape.

Dans certaines situations, cependant, il peut être plus approprié d' identifier les exceptions qui devraient faire échouer notre étape et sauter sur toute autre.

Voyons comment nous pouvons configurer cela en utilisant skip , skipLimit et 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(); }

Avec la configuration ci-dessus, nous demandons au framework Spring Batch d'ignorer toute exception (dans une limite configurée) sauf SAXException . Cela signifie que SAXException provoque toujours un échec d'étape.

L'ordre des appels skip () et noSkip () n'a pas d'importance.

4. Utilisation de SkipPolicy personnalisée

Parfois, nous pouvons avoir besoin d'un mécanisme de contrôle des sauts plus sophistiqué. À cette fin, le framework Spring Batch fournit l' interface SkipPolicy .

Nous pouvons ensuite fournir notre propre implémentation de la logique de saut et la brancher dans notre définition d'étape.

En gardant l'exemple précédent à l'esprit, imaginez que nous souhaitons toujours définir une limite de saut de deux éléments et rendre uniquement MissingUsernameException et NegativeAmountException désactivables.

Cependant, une contrainte supplémentaire est que nous pouvons ignorer NegativeAmountException, mais uniquement si le montant ne dépasse pas une limite définie .

Implémentons notre SkipPolicy personnalisée :

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

Maintenant, nous pouvons utiliser notre stratégie personnalisée dans une définition d'étape:

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

Et, comme dans notre exemple précédent, nous devons toujours utiliser faultTolerant () pour activer la fonctionnalité de saut.

Cette fois, cependant, nous n'appelons pas skip () ou noSkip () . Au lieu de cela, nous utilisons la méthode skipPolicy () pour fournir notre propre implémentation de l' interface SkipPolicy .

Comme nous pouvons le voir, cette approche nous donne plus de flexibilité, elle peut donc être un bon choix dans certains cas d'utilisation .

5. Conclusion

Dans ce didacticiel, nous avons présenté deux façons de rendre un travail Spring Batch tolérant aux pannes.

Même si l'utilisation d'un skipLimit () avec les méthodes skip () et noSkip () semble être plus populaire, nous pouvons trouver l'implémentation d'une SkipPolicy personnalisée plus pratique dans certaines situations.

Comme d'habitude, tous les exemples de code sont disponibles à l'adresse over sur GitHub.