繰り返し
RepeatTemplate
バッチ処理とは、単純な最適化として、またはジョブの一部としての繰り返しアクションに関するものです。反復を戦略化および一般化し、イテレータフレームワークに相当するものを提供するために、Spring Batch には RepeatOperations
インターフェースがあります。RepeatOperations
インターフェースには次の定義があります。
public interface RepeatOperations {
RepeatStatus iterate(RepeatCallback callback) throws RepeatException;
}
コールバックは、次の定義に示されているインターフェースであり、繰り返すビジネスロジックを挿入できます。
public interface RepeatCallback {
RepeatStatus doInIteration(RepeatContext context) throws Exception;
}
反復を終了する必要があると実装が判断するまで、コールバックは繰り返し実行されます。これらのインターフェースの戻り値は列挙値で、RepeatStatus.CONTINUABLE
または RepeatStatus.FINISHED
のいずれかになります。RepeatStatus
列挙は、作業が残っているかどうかに関する情報を繰り返し操作の呼び出し元に伝えます。一般的に言えば、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
を返すこともでき、呼び出し元に作業が残っていないことを知らせます。一部の反復は、コールバックで行われている作業に固有の考慮事項によって終了する可能性があります。他のものは実質的に無限ループ (コールバックに関する限り) であり、前の例で示した場合のように、完了の決定は外部ポリシーに委譲されます。
RepeatContext
RepeatCallback
のメソッドパラメーターは RepeatContext
です。多くのコールバックはコンテキストを無視します。ただし、必要に応じて、反復中に一時データを格納するための属性バッグとして使用できます。iterate
メソッドが戻った後、コンテキストは存在しなくなります。
進行中のネストされた反復がある場合、RepeatContext
には親コンテキストがあります。親コンテキストは、iterate
の呼び出し間で共有する必要があるデータを保存するのに役立つことがあります。これは、たとえば、反復でのイベントの発生回数をカウントし、後続の呼び出しでそれを記憶したい場合です。
RepeatStatus
RepeatStatus
は、処理が終了したかどうかを示すために Spring Batch によって使用される列挙です。可能な RepeatStatus
値は 2 つあります。
値 | 説明 |
| まだやるべきことがあります。 |
| これ以上の繰り返しは行わないでください。 |
RepeatStatus
で and()
メソッドを使用して、RepeatStatus
値を論理 AND 演算と組み合わせることができます。これの効果は、継続可能フラグで論理 AND を実行することです。つまり、いずれかのステータスが FINISHED
の場合、結果は FINISHED
になります。
完了ポリシー
RepeatTemplate
の内部では、iterate
メソッドのループの終了は、RepeatContext
のファクトリでもある CompletionPolicy
によって決定されます。RepeatTemplate
には、現在のポリシーを使用して RepeatContext
を作成し、反復の各段階で RepeatCallback
に渡す責任があります。コールバックが doInIteration
を完了すると、RepeatTemplate
は CompletionPolicy
を呼び出して、その状態(RepeatContext
に保存されます)を更新するように要求する必要があります。次に、反復が完了したかどうかをポリシーに確認します。
Spring Batch は、CompletionPolicy
のいくつかの単純な汎用実装を提供します。SimpleCompletionPolicy
では、固定回数まで実行できます(RepeatStatus.FINISHED
では、いつでも早期完了が強制されます)。
ユーザーは、より複雑な決定のために独自の完了ポリシーを実装する必要がある場合があります。例: オンラインシステムの使用後にバッチジョブが実行されないようにするバッチ処理ウィンドウには、カスタムポリシーが必要です。
例外処理
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
に設定すると、ネストされた反復(ステップ内のチャンクのセットなど)の兄弟コンテキスト全体で制限が維持されます。
リスナー
多くの場合、多くの異なる反復にわたる横断的関心事のために追加のコールバックを受信できると便利です。このために、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
呼び出しに適用されます。
複数のリスナーが存在する場合、リストに含まれるため、順序があることに注意してください。この場合、open
と before
は同じ順序で呼び出され、after
、onError
、close
は逆の順序で呼び出されます。
並列処理
RepeatOperations
の実装は、コールバックを順番に実行することに制限されません。一部の実装では、コールバックを並行して実行できることが非常に重要です。このために、Spring Batch は TaskExecutorRepeatTemplate
を提供し、TaskExecutorRepeatTemplate
は Spring TaskExecutor
戦略を使用して RepeatCallback
を実行します。デフォルトでは、SynchronousTaskExecutor
を使用します。これは、同じスレッドで反復全体を実行する効果があります(通常の RepeatTemplate
と同じ)。
宣言的な反復
場合によっては、発生するたびに繰り返したいとわかっているビジネス処理があります。この典型的な例は、メッセージパイプラインの最適化です。メッセージのバッチが頻繁に到着する場合は、メッセージごとに個別のトランザクションのコストを負担するよりも、処理する方が効率的です。Spring Batch は、この目的のためにメソッド呼び出しを RepeatOperations
オブジェクトにラップする AOP インターセプターを提供します。RepeatOperationsInterceptor
はインターセプトされたメソッドを実行し、提供された RepeatTemplate
の CompletionPolicy
に従って繰り返します。
Java
XML
次の例では、Java 構成を使用して、processMessage
というメソッドへのサービス呼び出しを繰り返します (AOP インターセプターを構成する方法の詳細については、Spring ユーザーガイドを参照してください)。
@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;
}
次の例は、Spring AOP 名前空間を使用して processMessage
というメソッドへのサービス呼び出しを繰り返す宣言的反復を示しています (AOP インターセプターを構成する方法の詳細については、Spring ユーザーガイドを参照してください)。
<aop:config>
<aop:pointcut id="transactional"
expression="execution(* com..*Service.processMessage(..))" />
<aop:advisor pointcut-ref="transactional"
advice-ref="retryAdvice" order="-1"/>
</aop:config>
<bean id="retryAdvice" class="org.spr...RepeatOperationsInterceptor"/>
上記の例では、インターセプター内でデフォルトの RepeatTemplate
を使用しています。ポリシー、リスナー、その他の詳細を変更するために、RepeatTemplate
のインスタンスをインターセプターに注入できます。
インターセプトされたメソッドが void
を返す場合、インターセプターは常に RepeatStatus.CONTINUABLE
を返します (したがって、CompletionPolicy
に有限のエンドポイントがない場合、無限ループの危険があります)。それ以外の場合、インターセプトされたメソッドからの戻り値が null
になるまで RepeatStatus.CONTINUABLE
を返します。その時点で、RepeatStatus.FINISHED
を返します。ターゲットメソッド内のビジネスロジックは、null
を返すか、提供された RepeatTemplate
で ExceptionHandler
によって再スローされる例外をスローすることによって、これ以上行うべき作業がないことを通知できます。