1. 序章

デフォルトでは、 Spring Batch ジョブの処理中にエラーが発生すると、対応するステップが失敗します。 ただし、特定の例外のために、現在処理されているアイテムをスキップしたい場合が多くあります。

このチュートリアルでは、SpringBatchフレームワークでスキップロジックを構成するための2つのアプローチを検討します。

2. 私たちのユースケース

例として、SpringBatchの紹介記事ですでに紹介したシンプルなチャンク指向のジョブを再利用します。

このジョブは、一部の財務データをCSV形式からXML形式に変換します。

2.1. 入力データ

まず、元のCSVファイルにいくつかの行を追加しましょう。

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

ご覧のとおり、最後の3行には無効なデータが含まれています。行5と7にはユーザー名フィールドがなく、行6のトランザクション量は負です。

後のセクションでは、これらの破損したレコードをスキップするようにバッチジョブを構成します。

3. スキップ制限とスキップ可能な例外の構成

3.1. skipおよびskipLimitを使用する

次に、失敗した場合にアイテムをスキップするようにジョブを構成する2つの方法の最初の方法について説明します。skipメソッドとskipLimitメソッドです。

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

まず、スキップ機能を有効にするには、ステップ構築プロセス中にfaultTolerant()の呼び出しを含める必要があります。

skip()および skipLimit()内で、スキップする例外とスキップされるアイテムの最大数を定義します。

上記の例では、読み取り、処理、または書き込みフェーズ中にMissingUsernameExceptionまたはNegativeAmountExceptionがスローされた場合、現在処理されているアイテムは省略され、合計2つの制限に対してカウントされます。 。

したがって、 3回目の例外がスローされると、ステップ全体が失敗します

3.1. noSkipを使用する

前の例では、MissingUsernameExceptionNegativeAmountException以外の例外があると、ステップが失敗します。

ただし、状況によっては、例外を特定して、ステップを失敗させ、他のステップをスキップする方が適切な場合があります。

skip skipLimit 、およびnoSkipを使用してこれを構成する方法を見てみましょう。

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

上記の構成では、 SAXExceptionを除くすべてのException (構成された制限内)をスキップするようにSpringBatchフレームワークに指示します。 これは、SAXExceptionが常にステップ障害を引き起こすことを意味します。

skip()および noSkip()呼び出しの順序は重要ではありません。

4. カスタムSkipPolicyの使用

より高度なスキップチェックメカニズムが必要になる場合があります。 そのために、SpringBatchフレームワークはSkipPolicyインターフェースを提供します。

次に、スキップロジックの独自の実装を提供し、それをステップ定義にプラグインできます。

前の例を念頭に置いて、2つのアイテムのスキップ制限を定義し、MissingUsernameExceptionNegativeAmountExceptionのみをスキップ可能にしたいとします。

ただし、追加の制約は、量が定義された制限を超えない場合に限り、NegativeAmountExceptionをスキップできることです。

カスタムSkipPolicyを実装しましょう。

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

これで、ステップ定義でカスタムポリシーを使用できます。

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

また、前の例と同様に、スキップ機能を有効にするには、 faultTolerant()を使用する必要があります。

ただし、今回は skip()または noSkip()は呼び出しません。 代わりに、 skipPolicy() メソッドを使用して、SkipPolicyインターフェイスの独自の実装を提供します。

ご覧のとおり、このアプローチは柔軟性が高いため、特定のユースケースに適しています。

5. 結論

このチュートリアルでは、SpringBatchジョブをフォールトトレラントにする2つの方法を紹介しました。

skipLimit() skip()および noSkip()メソッドと一緒に使用する方が一般的であるように見えますが、カスタムの実装が見つかる場合があります。 SkipPolicy は、状況によってはより便利になります。

いつものように、すべてのコード例はGitHubから入手できます。