1. 概要

このチュートリアルでは、必要なビジネスケースに対して、スケジュールされたSpringバッチジョブトリガーおよび停止するさまざまな方法を調査および比較します。

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

2. スケジュールされたSpringBatchジョブをトリガーする

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

さらに、スケジュールされたSpringバッチジョブを最も直感的な方法でトリガーするために、フラグが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. スケジュールされたSpringBatchジョブを停止します

上記の条件付きフラグを使用すると、スケジュールされたタスクが有効な状態で、スケジュールされたSpringバッチジョブをトリガーできます。

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

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

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

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

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. 結論

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

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

いつものように、この記事で使用されているすべてのコードサンプルは、GitHubから入手できます。