Konfigurieren der Überspringlogik in Spring Batch

1. Einleitung

Standardmäßig führen Fehler, die während einer Spring Batch-Jobverarbeitung auftreten, dazu, dass ein entsprechender Schritt fehlschlägt. Es gibt jedoch viele Situationen, in denen wir das aktuell verarbeitete Element für bestimmte Ausnahmen lieber überspringen möchten.

In diesem Tutorial werden zwei Ansätze zum Konfigurieren der Sprunglogik im Spring Batch-Framework untersucht.

2. Unser Anwendungsfall

Als Beispiel verwenden wir einen einfachen, klumpenorientierten Job, der bereits in unserem Einführungsartikel zu Spring Batch vorgestellt wurde.

Dieser Job konvertiert einige Finanzdaten von einer CSV in ein XML-Format.

2.1. Eingabedaten

Fügen wir zunächst der ursprünglichen CSV-Datei einige Zeilen hinzu:

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

Wie wir sehen können, enthalten die letzten drei Zeilen einige ungültige Daten - in den Zeilen 5 und 7 fehlt das Feld Benutzername, und der Transaktionsbetrag in Zeile 6 ist negativ.

In den späteren Abschnitten konfigurieren wir unseren Stapeljob so, dass diese beschädigten Datensätze übersprungen werden.

3. Konfigurieren des Überspringlimits und der überspringbaren Ausnahmen

3.1. Mit Sprung und skipLimit

Lassen Sie uns nun die erste von zwei Möglichkeiten diskutieren , unsere Arbeit zu konfigurieren Artikel im Falle eines Ausfalls überspringen - der Sprung und skipLimit Methoden:

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

Zunächst einmal aktivieren Sprung Funktionalität, müssen wir einen Anruf aufzunehmen hochverfügbare () während der Step-Bauprozess.

In skip () und skipLimit () definieren wir die Ausnahmen, die übersprungen werden sollen, und die maximale Anzahl übersprungener Elemente.

Wenn im obigen Beispiel während der Lese-, Prozess- oder Schreibphase entweder eine MissingUsernameException oder eine NegativeAmountException ausgelöst wird, wird das aktuell verarbeitete Element weggelassen und auf das Gesamtlimit von zwei angerechnet.

Folglich , wenn eine Ausnahme ein drittes Mal geworfen wird, dann ist der ganze Schritt wird fehlschlagen .

3.1. Verwenden von noSkip

Im vorherigen Beispiel schlägt jede andere Ausnahme außer MissingUsernameException und NegativeAmountException fehl.

In einigen Situationen kann es jedoch sinnvoller sein , Ausnahmen zu identifizieren, die dazu führen sollten, dass unser Schritt fehlschlägt, und andere zu überspringen.

Mal sehen , wie wir dies mit konfigurieren können überspringen , skipLimit und 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(); }

Mit der obigen Konfiguration weisen wir das Spring Batch-Framework an, alle Ausnahmen (innerhalb eines konfigurierten Grenzwerts) mit Ausnahme von SAXException zu überspringen . Dies bedeutet, dass SAXException immer einen Schrittfehler verursacht.

Die Reihenfolge der Sprung () und NOSKIP () Anrufe spielt keine Rolle.

4. Verwenden von Custom SkipPolicy

Manchmal benötigen wir einen ausgefeilteren Mechanismus zur Überprüfung von Übersprungen. Zu diesem Zweck bietet das Spring Batch-Framework die SkipPolicy- Schnittstelle.

Wir können dann unsere eigene Implementierung der Sprunglogik bereitstellen und sie in unsere Schrittdefinition einfügen.

Stellen Sie sich vor, wir möchten weiterhin das Überspringlimit von zwei Elementen definieren und nur MissingUsernameException und NegativeAmountException überspringen.

Eine zusätzliche Einschränkung besteht jedoch darin, dass wir NegativeAmountException überspringen können , jedoch nur, wenn der Betrag einen definierten Grenzwert nicht überschreitet .

Lassen Sie uns unsere benutzerdefinierte SkipPolicy implementieren :

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

Jetzt können wir unsere benutzerdefinierte Richtlinie in einer Schrittdefinition verwenden:

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

Und ähnlich wie in unserem vorherigen Beispiel müssen wir weiterhin errorTolerant () verwenden , um die Sprungfunktion zu aktivieren.

Dieses Mal jedoch, wissen wir nicht Anruf überspringen () oder NOSKIP () . Stattdessen verwenden wir die skipPolicy () -Methode, um unsere eigene Implementierung der SkipPolicy- Schnittstelle bereitzustellen .

Wie wir sehen können, bietet dieser Ansatz mehr Flexibilität, sodass er in bestimmten Anwendungsfällen eine gute Wahl sein kann .

5. Schlussfolgerung

In diesem Tutorial haben wir zwei Möglichkeiten vorgestellt, wie Sie einen Spring Batch-Job fehlertolerant machen können.

Obwohl die Verwendung von skipLimit () zusammen mit den Methoden skip () und noSkip () populärer zu sein scheint, ist die Implementierung einer benutzerdefinierten SkipPolicy in einigen Situationen möglicherweise bequemer.

Wie üblich sind alle Codebeispiele auf GitHub verfügbar.