繰り返し

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 つあります。

表 1: RepeatStatus のプロパティ

説明

CONTINUABLE

まだやるべきことがあります。

FINISHED

これ以上の繰り返しは行わないでください。

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 コールバックは、反復全体の前後に発生します。beforeafteronError は、個々の RepeatCallback 呼び出しに適用されます。

複数のリスナーが存在する場合、リストに含まれるため、順序があることに注意してください。この場合、open と before は同じ順序で呼び出され、afteronErrorclose は逆の順序で呼び出されます。

並列処理

RepeatOperations の実装は、コールバックを順番に実行することに制限されません。一部の実装では、コールバックを並行して実行できることが非常に重要です。このために、Spring Batch は TaskExecutorRepeatTemplate を提供し、TaskExecutorRepeatTemplate は Spring TaskExecutor 戦略を使用して RepeatCallback を実行します。デフォルトでは、SynchronousTaskExecutor を使用します。これは、同じスレッドで反復全体を実行する効果があります(通常の RepeatTemplate と同じ)。

宣言的な反復

場合によっては、発生するたびに繰り返したいとわかっているビジネス処理があります。この典型的な例は、メッセージパイプラインの最適化です。メッセージのバッチが頻繁に到着する場合は、メッセージごとに個別のトランザクションのコストを負担するよりも、処理する方が効率的です。Spring Batch は、この目的のためにメソッド呼び出しを RepeatOperations オブジェクトにラップする AOP インターセプターを提供します。RepeatOperationsInterceptor はインターセプトされたメソッドを実行し、提供された RepeatTemplate の CompletionPolicy に従って繰り返します。

  • Java

  • XML

次の例では、Java 構成を使用して、processMessage というメソッドへのサービス呼び出しを繰り返します (AOP インターセプターの構成方法の詳細については、<< docs.spring.io/spring-framework/docs/current/reference/html/core.html#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 インターセプターの構成方法の詳細については、<< docs.spring.io/spring-framework/docs/current/reference/html/core.html#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 によって再スローされる例外をスローすることによって、これ以上行うべき作業がないことを通知できます。