https://docs.spring.io/spring-batch/4.1.x/reference/html/repeat.html#repeat
https://qiita.com/kagamihoge/items/12fbbc2eac5b8a5ac1e0 俺の訳一覧リスト
1. Repeat
1.1. RepeatTemplate
バッチ処理とは繰り返し処理であり、simple optimizationとなるかjobの一部となるか、のどちらかです。strategyパターン化・繰り返しの汎用化・iterator相当の機能、を提供するために、Spring BatchにはRepeatOperations
があります。RepeatOperations
は以下の定義となります。
public interface RepeatOperations { RepeatStatus iterate(RepeatCallback callback) throws RepeatException; }
引数のcallbackはインタフェースで以下の定義となっており、繰り返し処理のビジネスロジックを記述します。
public interface RepeatCallback { RepeatStatus doInIteration(RepeatContext context) throws Exception; }
コールバックがイテレーションを終了するまで、コールバックを繰り返し実行します。上記インタフェースの戻り値はenumでRepeatStatus.CONTINUABLE
かRepeatStatus.FINISHED
のどちらかになります。RepeatStatus
enumは呼び出し元に繰り返し処理を続行するかどうかを示します。基本的には、RepeatOperations
の実装はRepeatStatus
をチェックしてイテレーションの終了判断の一つに使用します。コールバックでこれ以上の処理が無い事を呼び出し元に知らせるにはRepeatStatus.FINISHED
を返します。
RepeatOperations
の最もシンプルで汎用な実装はRepeatTemplate
で、以下のように使います。
RepeatTemplate template = new RepeatTemplate(); template.setCompletionPolicy(new SimpleCompletionPolicy(2)); template.iterate(new RepeatCallback() { public RepeatStatus doInIteration(RepeatContext context) { // Do stuff in batch... return RepeatStatus.CONTINUABLE; } });
上の例では、RepeatStatus.CONTINUABLE
で、処理続行を示しています。また、コールバックは処理終了を呼び出し元に伝えるためにRepeatStatus.FINISHED
を返すことも出来ます。コールバック処理に内在する考慮事項によって、強制終了するイテレーションがありえます。上のsetCompletionPolicyのように終了条件を外部にデリゲートするコールバック以外は無限ループです。
1.1.1. RepeatContext
RepeatCallback
の引数はRepeatContext
です。基本的にはコールバックで使うことは稀です。ただし、必要に応じて、イテレーション中の一時データを格納する場所として使えます。iterate
が返ると、コンテキストは無くなります。
イテレーションがネストする場合、RepeatContext
は親コンテキストを持ちます。親コンテキストは複数のiterate
間でデータ共有したいときに便利です。たとえば、複数のサブシーケンス呼び出し後もイテレーションでのイベント発生数を保持し続けたい場合、などです。
1.1.2. RepeatStatus
Spring Batchで処理を終了するかどうかを指示するのにはRepeatStatus
を使います。以下表のように、RepeatStatus
には2種類の値があります。
Table 1. RepeatStatus Properties
Value | Description |
---|---|
CONTINUABLE | 未処理アイテムが存在 |
FINISHED | ループ処理終了 |
また、RepeatStatus
のand()``でANDを取れます。これはcontinuableフラグとのANDです。つまり、両方とも
CONTINUABLEでなければ、
FINISHED```になります。
※以下コードは筆者補足
System.out.println(RepeatStatus.CONTINUABLE.and(true)); //CONTINUABLE System.out.println(RepeatStatus.CONTINUABLE.and(false)); //FINISHED System.out.println(RepeatStatus.FINISHED.and(true)); //FINISHED System.out.println(RepeatStatus.FINISHED.and(false)); //FINISHED
1.2. Completion Policies
RepeatTemplate
では、iterate
ループの終了はCompletionPolicy
が決定します。また、RepeatContext
のファクトリも行います。RepeatTemplate
はRepeatContext
の生成に設定されているポリシーを使用し、それをイテレーションでRepeatCallback
に毎回渡します。コールバックがdoInIteration
を完了すると、RepeatTemplate
は状態(RepeatContext
に保存)を更新するようCompletionPolicy
を呼び出します。それから、イテレーションを完了するかどうかをポリシーで決定します。
Spring BatchはCompletionPolicy
はシンプルで汎用の実装を用意しています。SimpleCompletionPolicy
は固定回数まで実行します(RepeatStatus.FINISHED
で任意のタイミングで強制終了も可能)。
より複雑な終了判定を行う自前のポリシーを実装することも可能です。たとえば、オンラインシステムで使用中であればバッチジョブを起動しないようにするバッチ処理ウィンドウに対しては、カスタムのポリシーを作成します。
1.3. Exception Handling
RepeatCallback
内で例外スローする場合、RepeatTemplate
は例外再スローかどうかを判断するExceptionHandler
を参照します。
以下はExceptionHandler
の定義です。
public interface ExceptionHandler { void handleException(RepeatContext context, Throwable throwable) throws Throwable; }
良くある使い方としては指定する例外スローの回数をカウントしてリミットに達したら失敗させます。Spring BatchはSimpleLimitExceptionHandler
と、これをもう少し柔軟にしたRethrowOnThresholdExceptionHandler
を用意しています。SimpleLimitExceptionHandler
はリミットのプロパティとチェック対象の例外の型を指定します。対象の例外の型のサブクラスはすべてカウント対象です。リミットに達するまでそれらの例外は無視し、達すると再スローします。それ以外の例外は常に再スローします。
SimpleLimitExceptionHandler
のオプションのプロパティuseParent
は重要です。デフォルトではfalse
で、リミットは現在のRepeatContext
に対してのみ適用します。true
にすると、ネストしたイテレーションの兄弟コンテキスト間でリミットは保持されます。
1.4. Listeners
異なるイテレーションの横断的関心事を扱うコールバックがあると便利な場合があります。Spring BatchにはRepeatListener
があります。RepeatTemplate
にRepeatListener
の実装を登録すると、イテレーション中にRepeatContext
とRepeatStatus
のしかるべきポイントでコールバックが呼ばれます。
RepeatListener
は以下のような定義です。
public interface RepeatListener { void before(RepeatContext context); void after(RepeatContext context, RepeatStatus result); void open(RepeatContext context); void onError(RepeatContext context, Throwable e); void close(RepeatContext context); }
open
とclose
はイテレーション全体の開始前後のコールバックです。before
, after
, onError
はRepeatCallback
の呼び出しに適用されます。
なお、1つ以上のリスナーがある場合、そのリストで順序が発生します。この場合、open
とbefore
は同一順序で呼ばれ、after
, onError
, close
は逆順で呼ばれます。
1.5. Parallel Processing
RepeatOperations
の実装でコールバックをシーケンシャルに実行するという制限はありません。コールバックをパラレル実行する実装が可能な点は重要です。Spring BatchにはTaskExecutorRepeatTemplate
があり、RepeatCallback
の実行にSpringのTaskExecutor
を使います。デフォルトではSynchronousTaskExecutor
を使用し、これは同一スレッドでイテレーション全体を実行します(つまりRepeatTemplate
と基本的に同じ)。
1.6. Declarative Iteration
ビジネスロジック実行をリピートしたい場合があります。これの古典的なサンプルはメッセージパイプラインの最適化です。もし頻繁にメッセージが到着する場合、メッセージごとに別々のトランザクションを張るよりも、メッセージをバッチ処理するのが効果的です。Spring BatchはRepeatOperations
にメソッド呼び出しをラップするAOPインターセプターを用意しています。RepeatOperationsInterceptor
はインターセプト対象メソッドを実行するとCompletionPolicy
に従いRepeatTemplate
で繰り返し実行します。
以下の例はjava configurationでprocessMessage
のサービスメソッド呼び出しを繰り返し実行する設定です(AOPインターセプターの詳細な設定例はSpring User Guideを参照してください)。
@Bean public MyService myService() { ProxyFactory factory = new ProxyFactory(RepeatOperations.class.getClassLoader()); factory.setInterfaces(MyService.class); factory.setTarget(new MyService()); MyService service = (MyService) factory.getProxy(); JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut(); pointcut.setPatterns(".*processMessage.*"); RepeatOperationsInterceptor interceptor = new RepeatOperationsInterceptor(); ((Advised) service).addAdvisor(new DefaultPointcutAdvisor(pointcut, interceptor)); return service; }
上のサンプルはインターセプターにデフォルトのRepeatTemplate
を使用します。ポリシー・リスナー・などを変更するには、インターセプターに```RepeatTemplate````を設定してください。
インターセプトメソッドがvoid
を返す場合、インターセプターは常にRepeatStatus.CONTINUABLE
を返します(CompletionPolicy
で何らかの終了条件を指定しない場合無限ループの危険性がある)。もしくは、インターセプトメソッドの戻り値がnull
になるまでRepeatStatus.CONTINUABLE
を返し、null
の時点でRepeatStatus.FINISHED
を返します。よって、ターゲットメソッドのビジネスロジックは、null
を返すかRepeatTemplate
のExceptionHandler
が再スローする例外のスローにより、処理終了を伝えることが出来ます。