JavaのQuartzライブラリのJobListenerで定義したジョブを監視する方法

JavaのQuartzライブラリのJobListenerで定義したジョブを監視する方法

org.quartz.JobListenerインタフェースをimplementsしたリスナークラスを作成してSchedulerのgetListenerManager().addJobListener()メソッドにリスナーのインスタンスを指定すると、ジョブを監視することができます。

オーバーライドするメソッドが4つあります。

メソッド 処理
getName 名前を返す
jobToBeExecuted job実行前処理
jobExecutionVetoed 不明
jobWasExecuted job実行後処理

以下、Jobを監視するリスナークラスです。

package jp.co.confrage;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class AListener implements org.quartz.JobListener {

  @Override
  public String getName() {
    return "default";
  }
  @Override
  public void jobToBeExecuted(final JobExecutionContext context) {
    System.out.println("処理前に呼ばれる");
  }
  @Override
  public void jobExecutionVetoed(final JobExecutionContext context) {
    System.out.println("ジョブ実行拒否されたら呼ばれる");
  }
  @Override
  public void jobWasExecuted(
  final JobExecutionContext context, final JobExecutionException jobException) {
    System.out.println("処理後に呼ばれる");
  }
}

とりあえずジョブの実行前後で標準出力するだけのリスナーを作成しました。リスナーAとします。

スケジューラにリスナーを登録する

2つのジョブAとジョブBを作成して、適当なトリガーでジョブBをスケジューリングします。

SchedulerクラスのgetListenerManager().addJobListener()メソッドにリスナーAのインスタンスを渡してリスナーを登録します。

第一引数
JobListenerのインスタンス

以下のようにリスナーを登録します。

Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.getListenerManager().addJobListener(new AListener());

全ソースは以下です。

package jp.co.confrage;

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

public class Library {
  public static void main(final String[] args) {
    JobKey keyA = new JobKey("job1", "group1");
    JobKey keyB = new JobKey("job2", "group2");
    JobDetail jobA = JobBuilder.newJob(AJob.class).withIdentity(keyA).build(); // 未使用
    JobDetail jobB = JobBuilder.newJob(BJob.class).withIdentity(keyB).build();

    Trigger trigger =
    TriggerBuilder.newTrigger()
      .withIdentity("trigger1", "group2")
      .startNow()
      .withSchedule(
      SimpleScheduleBuilder.simpleSchedule()
        .withIntervalInMilliseconds(1000) // 1秒間隔
        .repeatForever()) // 処理をずっと繰り返す
        .build();

    try {
      Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
      scheduler.getListenerManager().addJobListener(new AListener()); // AListenerを登録
      scheduler.scheduleJob(jobB, trigger); // job Bをスケジューリング

      scheduler.start(); // スタート
      Thread.sleep(10000); // 10秒スリープ
      scheduler.shutdown(); // エンド
    } catch (SchedulerException | InterruptedException e) {
      throw new RuntimeException(e);
    }
  }
}

この時、ジョブBに対してリスナーAが動作します。実行結果です。

処理前に呼ばれる
BJob execute.
処理後に呼ばれる
処理前に呼ばれる
BJob execute.
処理後に呼ばれる

...省略

ジョブAをスケジューリングしてもリスナーAが動作します。

org.quartz.impl.matchers.KeyMatcherクラスで識別子が一致する場合に監視する

リスナーAはジョブAだけを監視したい、ジョブBは監視させたくないといった場合、getListenerManager().addJobListener()メソッドの第二引数を追加します。

第一引数にリスナーAのインスタンスを指定します。

第二引数にMatcher<JobKey>を指定します。

第一引数 第二引数
JobListenerのインスタンス Matcher<JobKey>

具体的には以下のような感じです。

JobKey keyA = new JobKey("job1", "group1");
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler
  .getListenerManager()
  .addJobListener(new AListener(), KeyMatcher.keyEquals(keyA)); // AListenerを登録

全ソースは以下です。

package jp.co.confrage;

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.KeyMatcher;

public class Library {
  public static void main(final String[] args) {
    JobKey keyA = new JobKey("job1", "group1");
    JobKey keyB = new JobKey("job2", "group2");
    JobDetail jobA = JobBuilder.newJob(AJob.class).withIdentity(keyA).build(); // 未使用
    JobDetail jobB = JobBuilder.newJob(BJob.class).withIdentity(keyB).build();

    Trigger trigger =
    TriggerBuilder.newTrigger()
      .withIdentity("trigger1", "group2")
      .startNow()
      .withSchedule(
        SimpleScheduleBuilder.simpleSchedule()
          .withIntervalInMilliseconds(1000) // 1秒間隔
          .repeatForever()) // 処理をずっと繰り返す
      .build();

    try {
      Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
      scheduler.getListenerManager().addJobListener(new AListener(), KeyMatcher.keyEquals(keyA));
      // AListenerを登録,keyAのジョブを監視

      scheduler.scheduleJob(jobB, trigger); // job Bをスケジューリング

      scheduler.start(); // スタート
      Thread.sleep(10000); // 10秒スリープ
      scheduler.shutdown(); // エンド
    } catch (SchedulerException | InterruptedException e) {
      throw new RuntimeException(e);
    }
  }
}

ジョブBは実行されますが、監視しているのはジョブAなのでリスナーで監視できていないのがわかります。

次回、意図的にジョブの実行を拒否してjobExecutionVetoed()メソッドが実行されることを確認します。

コメント

タイトルとURLをコピーしました