Spring Batch 6 の新機能

依存関係のアップグレード

このメジャーリリースでは、Spring の依存関係が次のバージョンにアップグレードされます。

  • Spring Framework 7.0

  • Spring Integration 7.0

  • Spring Data 4.0

  • Spring LDAP 4.0

  • Spring AMQP 4.0

  • Spring Kafka 4.0

  • Micrometer 1.16

バッチインフラストラクチャ構成の改善

バッチインフラストラクチャ構成用の新しいアノテーションとクラス

v6 より前では、@EnableBatchProcessing アノテーションは JDBC ベースのインフラストラクチャに紐付けられていました。これはもはや当てはまりません。基盤となるジョブリポジトリを設定するための 2 つの新しいアノテーション、@EnableJdbcJobRepository と @EnableMongoJobRepository が導入されました。

v6 以降、@EnableBatchProcessing ではバッチインフラストラクチャの共通属性を構成できるようになり、新しい専用アノテーションを使用してストア固有の属性を指定できるようになりました。

これらのアノテーションの使用方法の例を次に示します。

@EnableBatchProcessing(taskExecutorRef = "batchTaskExecutor")
@EnableJdbcJobRepository(dataSourceRef = "batchDataSource", transactionManagerRef = "batchTransactionManager")
class MyJobConfiguration {

	@Bean
	public Job job(JobRepository jobRepository) {
		return new JobBuilder("job", jobRepository)
                    // job flow omitted
                    .build();
	}
}

同様に、DefaultBatchConfiguration に基づくプログラムモデルも更新され、ストア固有の属性を定義するための 2 つの新しい設定クラス(JdbcDefaultBatchConfiguration と MongoDefaultBatchConfiguration)が導入されました。これらのクラスを使用することで、各ジョブリポジトリやその他のバッチインフラストラクチャ Bean の特定の属性をプログラム的に設定できます。

デフォルトでリソースレスのバッチインフラストラクチャ

DefaultBatchConfiguration クラスが更新され、デフォルトで「リソースレス」なバッチインフラストラクチャ(v5.2 で導入された ResourcelessJobRepository 実装に基づく)が提供されるようになりました。これにより、以前はバッチメタデータの保存に必要だったジョブリポジトリ用のインメモリデータベース(H2 や HSQLDB など)が不要になりました。

さらに、ResourcelessJobRepository はデータベース接続やトランザクションを必要としないため、この変更により、メタデータが使用されていない場合のバッチアプリケーションのデフォルトのパフォーマンスが向上します。

最後に、この変更により、メタデータの保存にメモリ内データベースが不要になるため、バッチアプリケーションのメモリフットプリントを削減できます。

バッチインフラストラクチャ構成の簡素化

v6 より前では、複雑な Spring Batch アプリケーションの典型的な設定は非常に複雑で、JobRepositoryJobLauncherJobExplorerJobOperatorJobRegistryJobRegistrySmartInitializingSingleton など多くの Bean が必要でした。そのため、たとえば JobRepository と JobExplorer の両方で同じ実行コンテキストシリアライザーを設定するなど、多くの設定コードが必要でした。

このリリースでは、バッチインフラストラクチャの構成を簡素化するためにいくつかの変更が加えられました。

  • JobRepository は JobExplorer インターフェースを継承するため、別途 JobExplorer Bean を定義する必要はありません。

  • JobOperator は JobLauncher インターフェースを継承するため、別途 JobLauncher Bean を定義する必要はありません。

  • JobRegistry はオプションになり、ジョブを自動的に登録できるほどスマートになったため、別途 JobRegistrySmartInitializingSingleton Bean を定義する必要はありません。

  • トランザクションマネージャーはオプションになり、指定されていない場合はデフォルトの ResourcelessTransactionManager が使用されます。

これにより、一般的なバッチアプリケーションに必要な Bean の数が削減され、構成コードが簡素化されます。

チャンク指向処理モデルの新しい実装

これは新機能ではなく、チャンク指向処理モデルの新しい実装です。この新しい実装はバージョン 5.1 でテスト的な追加機能として導入され、バージョン 6.0 で安定版として利用可能になりました。

新しい実装は、ChunkOrientedTasklet / TaskletStep クラスの代わりとなる ChunkOrientedStep クラスで提供されます。

ビルダーを使用して ChunkOrientedStep を定義する方法の例を次に示します。

@Bean
public Step chunkOrientedStep(JobRepository jobRepository, ItemReader<Person> itemReader, ItemWriter<Person> itemWriter) {
    int chunkSize = 100;
    return new ChunkOrientedStepBuilder<Person, Person>("step", jobRepository, chunkSize)
            .reader(itemReader)
            .writer(itemWriter)
            .build();
}

さらに、フォールトトレランス機能は次のように採用されました。

  • 再試行機能は、以前の Spring Retry ライブラリではなく、Spring Framework 7 で導入された再試行機能に基づいています。

  • スキップ機能は、新しい実装に合わせて若干調整され、現在は完全に SkipPolicy インターフェースのみに基づいています。

新しい ChunkOrientedStep で再試行機能とスキップ機能を使用する方法の簡単な例を次に示します。

@Bean
public Step faulTolerantChunkOrientedStep(JobRepository jobRepository, ItemReader<Person> itemReader, ItemWriter<Person> itemWriter) {

    // retry policy configuration
    int maxRetries = 10;
    var retrybaleExceptions = Set.of(TransientException.class);
    RetryPolicy retryPolicy = RetryPolicy.builder()
        .maxRetries(maxRetries)
        .includes(retrybaleExceptions)
        .build();

    // skip policy configuration
    int skipLimit = 50;
    var skippableExceptions = Set.of(FlatFileParseException.class);
    SkipPolicy skipPolicy = new LimitCheckingExceptionHierarchySkipPolicy(skippableExceptions, skipLimit);

    // step configuration
    int chunkSize = 100;
    return new ChunkOrientedStepBuilder<Person, Person>("step", jobRepository, chunkSize)
        .reader(itemReader)
        .writer(itemWriter)
        .faultTolerant()
        .retryPolicy(retryPolicy)
        .skipPolicy(skipPolicy)
        .build();
}

以前の実装から新しい実装に移行する方法の詳細については、移行ガイド [GitHub] (英語) を参照してください。

新しい並行性モデル

このリリースより前は、「並列反復」の概念に基づく同時実行モデルでは、さまざまなレベルで多くの状態同期が必要であり、スロットリングとバックプレッシャーに関連するいくつかの制限があり、トランザクションのセマンティクスがわかりにくくなり、パフォーマンスが低下していました。

このリリースでは、このモデルを見直し、プロデューサーコンシューマーパターンに基づく、簡素化された新しい並行処理アプローチを採用しました。並行処理のチャンク指向ステップでは、プロデューサースレッドとコンシューマースレッドの間に、境界付き内部キューが使用されます。アイテムは処理準備が整うとすぐにキューに追加され、コンシューマースレッドは処理可能になるとすぐにキューからアイテムを取得します。チャンクの書き込み準備が完了すると、プロデューサースレッドはチャンクの書き込みが完了するまで一時停止し、その後アイテムの生成を再開します。

この新しいモデルはより効率的で理解しやすく、同時実行のパフォーマンスも向上します。

新しいコマンドライン演算子

Spring Batch はバージョン 1 から CommandLineJobRunner を提供していました。このランナーは長年にわたりその目的を十分に果たしてきましたが、拡張性とカスタマイズ性に関してはいくつかの限界が見え始めました。静的初期化、オプションとパラメーターの非標準的な処理方法、拡張性の欠如など、多くの課題が報告されています。

さらに、これらすべての課題により、そのランナーを Spring Boot で再利用することができなくなり、両方のプロジェクトでコードが重複し、動作の相違 (ジョブパラメーターのインクリメンタ動作の違いなど) が発生し、多くのユーザーを混乱させていました。

このリリースでは、CommandLineJobRunner の最新バージョンである CommandLineJobOperator が導入され、コマンドラインからバッチジョブを操作 (開始、停止、再起動など) できるようになりました。また、カスタマイズと拡張が可能で、Spring Batch 6 で導入された新しい変更に合わせて更新されています。

失敗したジョブ実行を回復する機能

このリリース以前は、ジョブ実行が突然失敗した場合、データベースを手動で更新しなければ復旧できませんでした。これはエラーが発生しやすく、異なるジョブリポジトリ間で一貫性がありませんでした(JDBC データベースの場合はいくつかの SQL 文、NoSQL ストアの場合はいくつかのカスタム文が必要だったため)。

このリリースでは、JobOperator インターフェースに recover という新しいメソッドが導入され、すべてのジョブリポジトリにわたって失敗したジョブ実行を一貫して回復できるようになりました。

あらゆるステップを停止する機能

v5.2 時点では、Tasklet ステップから JobOperator#stop ステップまで外部から停止することしかできません。カスタム Step 実装で外部停止シグナルを処理しようとしても、不可能です。

このリリースでは、Step を継承し、停止シグナルを処理できる任意のステップで実装できる、StoppableStep という新しいインターフェースが追加されました。

正常なシャットダウンのサポート

Spring Batch 6.0 では、バッチジョブの正常なシャットダウンのサポートが導入されました。この機能により、実行中のジョブを制御された方法で停止することができ、実行中のステップに中断シグナルが正しく送信されるようになります。

正常なシャットダウンが開始されると、ジョブ実行は現在アクティブなステップを停止し、ジョブリポジトリを一貫性のある状態に更新して再開を可能にします。実行中のステップが完了すると、ジョブ実行は停止状態としてマークされ、必要なクリーンアップ操作が実行されます。

Java フライトレコーダーによる可観測性 (JFR)

既存の Micrometer メトリクスに加えて、Spring Batch 6.0 では Java Flight Recorder (JFR) のサポートが導入され、強化された監視機能が提供されます。

JFR は、Java 仮想マシン(JVM)に組み込まれた強力なプロファイリングおよびイベント収集フレームワークです。パフォーマンスのオーバーヘッドを最小限に抑えながら、アプリケーションの実行時動作に関する詳細な情報を取得できます。

このリリースでは、ジョブとステップの実行、アイテムの読み取りと書き込み、トランザクション境界など、バッチジョブ実行の重要な側面を監視するための JFR イベントがいくつか導入されています。

JSpecify による null 安全性アノテーション

Spring Batch 6.0 API に JSpecify (英語) アノテーションが付けられるようになり、null 安全性の保証が強化され、コード品質が向上しました。

ローカルチャンクのサポート

リモートチャンクと同様に、ローカルチャンクは、複数のスレッドを使用して、同じ JVM 内でローカルにアイテムのチャンクを並列処理できる新機能です。これは、処理するアイテム数が多く、マルチコアプロセッサーを活用したい場合に特に便利です。ローカルチャンクを使用すると、チャンク指向のステップを構成し、複数のスレッドを使用してアイテムのチャンクを同時処理できます。各スレッドは、独自のアイテムのチャンクを独立して読み取り、処理、書き込みを行い、ステップは全体の実行を管理し、結果をコミットします。

Spring Integration メッセージチャネルを使用した SEDA スタイル

Spring Batch 5.2 では、BlockingQueueItemReader および BlockingQueueItemWriter コンポーネントを用いて、ローカルスレッドを用いた SEDA(ステージングイベントドリブンアーキテクチャ)スタイルの処理の概念を導入しました。その基盤を基に、Spring Batch 6.0 では Spring Integration メッセージングチャネルを用いた大規模な SEDA スタイルの処理をサポートします。これにより、バッチジョブの各ステージを分離し、メッセージチャネルを用いて非同期的に処理することが可能になります。Spring Integration を活用することで、メッセージングチャネルの設定と管理が容易になり、メッセージ変換、フィルタリング、ルーティングなどの機能も活用できます。

Jackson 3 サポート

Spring Batch 6.0 は、JSON 処理に Jackson 3.x をサポートするようにアップグレードされました。このアップグレードにより、Jackson ライブラリの最新機能および改善点との互換性が確保され、パフォーマンスとセキュリティも向上します。Spring Batch のすべての JSON 関連コンポーネント(JsonItemReaderJsonFileItemWriterJacksonExecutionContextStringSerializer など)は、デフォルトで Jackson 3.x を使用するように更新されました。

Jackson 2.x のサポートは非推奨となり、将来のリリースで削除される予定です。現在 Spring Batch アプリケーションで Jackson 2.x をご使用の場合は、最新の機能と改善点を活用するために、Jackson 3.x へのアップグレードをお勧めします。

リモートステップサポート

このリリースでは、リモートステップ実行のサポートが導入され、バッチジョブのステップをリモートマシンまたはクラスター上で実行できるようになりました。この機能は、パフォーマンスとスケーラビリティを向上させるためにワークロードを複数のノードに分散させたい大規模なバッチ処理シナリオで特に役立ちます。リモートステップ実行は、ローカルジョブ実行環境とリモートステップ実行プログラム間の通信を可能にする Spring Integration メッセージングチャネルを使用することで実現されます。

ラムダスタイルの設定

このリリースでは、バッチアーティファクトの設定にコンテキストラムダ式を使用できるようになりました。この新しい設定スタイルにより、アイテムのリーダーとライターをより簡潔かつ読みやすく定義できます。

たとえば、次のような従来のビルダーパターンを使用する代わりに:

var reader = new FlatFileItemReaderBuilder()
 .resource(...)
 .delimited()
 .delimiter(",")
 .quoteCharacter('"')
 ...
 .build();

次のようにラムダ式を使用して区切られたオプションを設定できるようになりました。

var reader = new FlatFileItemReaderBuilder()
 .resource(...)
 .delimited (config -> config.delimiter(',').quoteCharcter( '"' ))
 ...
 .build();

廃止と削減

他のメジャーリリースと同様に、Spring Batch 6.0 では一部の機能が廃止または削除されました。以下の変更点にご注意ください。

  • 以前のバージョンで非推奨となりた API と機能はすべて削除されました

  • @EnableBatchProcessing(modular = true) によるモジュラー構成は非推奨となりました

  • このバージョンでは、コア API を簡素化し、その範囲を縮小するために、いくつかの API が非推奨になりました。

  • spring-batch-test モジュールでの JUnit 4 サポートを廃止

  • Jackson 2 のサポートを廃止

  • batch:…​ 名前空間を介した XML 構成を廃止

詳細については、移行ガイド [GitHub] (英語) を参照してください。