LoginSignup
0
0

More than 1 year has passed since last update.

Spring BootでQuartzを利用する(1)

Last updated at Posted at 2022-10-14

Spring Bootにジョブスケジューラの『Quartz』を組込み
ジョブ登録と削除用エンドポイントを作成し実行します。

■完成イメージ

+----------+            +-------------+            +------------+
|          |            | Spring Boot |   JDBC     |   Job      |
| Browser |<---------->|     +       |<---------->| Persistent |
|          | port=8080  |   Quartz    | port=33060 |   data     |
|          |            |             |            |  (MySQL)   |
+----------+            +-------------+            +------------+

■構築環境

・Windows10 バージョン21H2
・IntelliJ IDEA 2022.1.4(Community Edition)
・OpenJDK Runtime Environment Zulu17.36+17-CA (build 17.0.4.1+1-LTS)
・Spring Boot 2.7.4
・Quartz
・Mysql 5.7.39

1. プロジェクトへQuartzを組込む

build.geadleを編集しJPA, JDBC Driver, Quartzの依存関係を追加。

build.gradle
dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-quartz'
	runtimeOnly 'mysql:mysql-connector-java'
}

2. Spring Bootアプリケーションのパラメータを設定

エンドポイントの受信ポート及びMysqlとの接続設定を追加。
spring.quartz.jdbc.initialize-schemaをalwaysにする事でQuartzに必要なテーブルを自動作成します。
ただし起動時に毎回初期化が走るため、不必要であればneverに変更してください。
またMySQLユーザにはテーブルを作成する適切なロールが紐づいている必要があります。

application.properties
server.port=8080
spring.datasource.platform=org.hibernate.dialect.MySQL5Dialect
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://***.***.***.***:33060/データベース名
spring.datasource.username=ユーザ名
spring.datasource.password=パスワード
spring.jpa.open-in-view=false
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true


#QUARTZ CONFIGS
spring.quartz.job-store-type=jdbc
spring.quartz.jdbc.initialize-schema=always

3. Quartzの起動とDIコンテナへの登録

Spring Bootの起動時にQuartzも同時に起動しDIコンテナにインスタンスを登録します。

SchedulerApplication.java
@SpringBootApplication
public class SchedulerApplication {

	public static void main(String[] args) {
		SpringApplication.run(SchedulerApplication.class, args);
	}

	@Bean
	public Scheduler scheduler(SchedulerFactoryBean factory) throws SchedulerException {
		Scheduler scheduler = factory.getScheduler();
		scheduler.start();
		return scheduler;
	}
}

4. パラメータクラス作成

ジョブの引数として渡すパラメータクラスを作成。
シリアライズ(直列化)できるようSerializableをimplementsします。

JobParameter.java
public class JobParameter implements Serializable {
    private static final long serialVersionUID = 1L;
    private final String uid;
    private final String name;
}

5. ジョブクラスを作成

パラメータとして受け取った名前を標準出力するジョブになります。

SimpleJob.java
public class SimpleJob implements Job {
    @Override
    public void execute(JobExecutionContext context) {
        JobDataMap parameter = context.getJobDetail().getJobDataMap();
        JobParameter jobParameter = (JobParameter)parameter.get("parameter");
        System.out.println(MessageFormat.format("JobName: {0}",jobParameter.getName()));
    }
}

6. エンドポイント作成

登録と削除用のエンドポイントを持つコントローラクラスになります。

SimpleController.java
@RestController
@RequestMapping("/")
public class SimpleController {

    private final Scheduler scheduler;

    @Autowired
    public SimpleController(Scheduler scheduler) {
        this.scheduler = scheduler;
    }

    @GetMapping("/create")
    public ResponseEntity create() throws Exception {
        // パラメータ作成
        JobParameter jobParameter = new JobParameter("0001", "shigemax");

        // ジョブ生成及びパラメータ付与
        JobDetail job = JobBuilder.newJob(SimpleJob.class)
                .withIdentity("sample_job").build();
        job.getJobDataMap().put("parameter", jobParameter);

        // トリガー設定(120秒後に発火)
        Date afterFiveSeconds = Date.from(LocalDateTime.now().plusSeconds(120)
                .atZone(ZoneId.systemDefault()).toInstant());
        Trigger trigger = TriggerBuilder.newTrigger()
                .startAt(afterFiveSeconds)
                .build();

        // ジョブ登録
        this.scheduler.scheduleJob(job, trigger);

        return ResponseEntity.ok().build();
    }

    @GetMapping("/delete")
    public ResponseEntity delete() throws Exception {
        // ジョブ名で削除
        this.scheduler.deleteJob(new JobKey("sample_job"));
        return ResponseEntity.ok().build();
    }
}

7. Spring Boot起動

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.7.4)

8. Quartz用テーブルの確認

mysql> SHOW TABLES;
+--------------------------+
| Tables_in_quartz         |
+--------------------------+
| QRTZ_BLOB_TRIGGERS       |
| QRTZ_CALENDARS           |
| QRTZ_CRON_TRIGGERS       |
| QRTZ_FIRED_TRIGGERS      |
| QRTZ_JOB_DETAILS         |
| QRTZ_LOCKS               |
| QRTZ_PAUSED_TRIGGER_GRPS |
| QRTZ_SCHEDULER_STATE     |
| QRTZ_SIMPLE_TRIGGERS     |
| QRTZ_SIMPROP_TRIGGERS    |
| QRTZ_TRIGGERS            |
+--------------------------+

9. ジョブの登録

HTTP GETにてhttp://localhost:8080/createにリクエスト。
120秒後に標準出力にてパラメータで引き渡された名前が表示される。
JobClass: class com.example.scheduler.job.SimpleJob
JobName: shigemax

10. MySQLコンテナにbashログイン

HTTP GETにてhttp://localhost:8080/createにリクエスト後、
HTTP GETにてhttp://localhost:8080/deleteにリクエスト。
ジョブが削除された為、ジョブが120秒たっても実行されないことを確認。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0