スケジュール設定されたSpring Batchジョブを起動および停止する方法

スケジュールされたSpringバッチジョブをトリガーおよび停止する方法

1. 概要

このチュートリアルでは、必要なビジネスケースについて、さまざまな方法を調査してtrigger and stop a scheduled Spring Batch job と比較します。

Spring BatchとSchedulerの紹介が必要な場合は、Spring-BatchSpring-Schedulerの記事を参照してください。

2. スケジュールされたSpringバッチジョブをトリガーする

まず、スケジューリングとバッチジョブを構成するためのクラスSpringBatchSchedulerがあります。 メソッドlaunchJob()がスケジュールされたタスクとして登録されます。

さらに、スケジュールされたSpring Batchジョブを最も直感的な方法でトリガーするために、条件付きフラグを追加して、フラグがtrueに設定されている場合にのみジョブを起動します。

private AtomicBoolean enabled = new AtomicBoolean(true);

private AtomicInteger batchRunCounter = new AtomicInteger(0);

@Scheduled(fixedRate = 2000)
public void launchJob() throws Exception {
    if (enabled.get()) {
        Date date = new Date();
        JobExecution jobExecution = jobLauncher()
          .run(job(), new JobParametersBuilder()
            .addDate("launchDate", date)
            .toJobParameters());
        batchRunCounter.incrementAndGet();
    }
}

// stop, start functions (changing the flag of enabled)

変数batchRunCounterは、バッチジョブが停止したかどうかを確認するための統合テストで使用されます。

3. スケジュールされたSpringバッチジョブを停止する

上記の条件付きフラグを使用すると、スケジュールされたタスクを有効にして、スケジュールされたSpringBatchジョブをトリガーできます。

ジョブを再開する必要がない場合は、スケジュールされたタスクを実際に停止してリソースを節約できます。

次の2つのサブセクションで2つのオプションを見てみましょう。

3.1. スケジューラポストプロセッサの使用

@Scheduledアノテーションを使用してメソッドをスケジュールしているため、BeanポストプロセッサScheduledAnnotationBeanPostProcessorが最初に登録されます。

postProcessBeforeDestruction()を明示的に呼び出して、指定されたスケジュール済みBeanを破棄できます。

@Test
public void stopJobSchedulerWhenSchedulerDestroyed() throws Exception {
    ScheduledAnnotationBeanPostProcessor bean = context
      .getBean(ScheduledAnnotationBeanPostProcessor.class);
    SpringBatchScheduler schedulerBean = context
      .getBean(SpringBatchScheduler.class);
    await().untilAsserted(() -> Assert.assertEquals(
      2,
      schedulerBean.getBatchRunCounter().get()));
    bean.postProcessBeforeDestruction(
      schedulerBean, "SpringBatchScheduler");
    await().atLeast(3, SECONDS);

    Assert.assertEquals(
      2,
      schedulerBean.getBatchRunCounter().get());
}

複数のスケジューラーを検討する場合、必要に応じて特定のスケジューラーを停止できるように、1つのスケジューラーを独自のクラスに保持することをお勧めします。

3.2. スケジュールされたFutureのキャンセル

スケジューラを停止する別の方法は、そのFutureを手動でキャンセルすることです。

Futureマップをキャプチャするためのカスタムタスクスケジューラは次のとおりです。

@Bean
public TaskScheduler poolScheduler() {
    return new CustomTaskScheduler();
}

private class CustomTaskScheduler
  extends ThreadPoolTaskScheduler {

    //

    @Override
    public ScheduledFuture scheduleAtFixedRate(
      Runnable task, long period) {
        ScheduledFuture future = super
          .scheduleAtFixedRate(task, period);

        ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) task;
        scheduledTasks.put(runnable.getTarget(), future);

        return future;
    }
}

次に、Futureマップを繰り返し、バッチジョブスケジューラのFutureをキャンセルします。

public void cancelFutureSchedulerTasks() {
    scheduledTasks.forEach((k, v) -> {
        if (k instanceof SpringBatchScheduler) {
            v.cancel(false);
        }
    });
}

複数のスケジューラタスクがある場合は、カスタムスケジューラプール内でFutureマップを維持できますが、スケジューラクラスに基づいて対応するスケジュールされたFutureをキャンセルできます。

4. 結論

この簡単な記事では、スケジュールされたSpring Batchジョブをトリガーまたは停止する3つの異なる方法を試しました。

バッチジョブを再起動する必要がある場合、条件付きフラグを使用してジョブの実行を管理するのが柔軟なソリューションです。 それ以外の場合は、他の2つのオプションに従って、スケジューラを完全に停止できます。

いつものように、記事で使用されているすべてのコードサンプルは利用可能なover on GitHubです。