英政府競争規制当局の競争・市場庁(CMA)は11月26日(現地時間)、1月から独禁法違反の可能性を調査中の米Googleの「プライバシーサンドボックス」の取り組みについて、Googleから改善したコミットメントを受理したと発表した。
Googleは今年の3月に、ChromeブラウザでのサードパーティーCookieの完全廃止とプライバシーサンドボックス採用に向けた計画を発表したが、6月にはCMAや欧州委員会による調査に協力するため、その実行を2023年後半まで延期すると発表した。
⇧ とあって、
“他のプロバイダーのように”サードパーティーCookieの代わりにユーザーを一意に識別するような識別子を使うことはしないとGoogleは強調する。Googleが採用するのは、プライバシーサンドボックスをベースとするFLoC(Federated Learning of Cohorts、群れの連合学習)と呼ぶAPI。FLoCは、大まかに言うと、同じ関心を持つ匿名ユーザーの集合体という意味で、名称のFLoCもflock(群れ)を意図しているようだ。このAPIにより、個々のユーザーを追跡せずに広告主とパブリッシャーに成果を提供することが可能という。
⇧「FLoC(Federate Learning of Cohorts)」が結構、評判が良くなかったような...
システム開発とかに影響してくるかが気になるところですかね...
今回は、「spring-boot-starter-〇〇」と、「spring-boot-starter-quartz」について調べてみました。
レッツトライ~。
「spring-boot-starter-〇〇」の有難みが実感しにくい...
「spring-boot-starter-quartz」って「依存関係」を利用した際に、結局のところ、
- 「spring framework」側ではどこまで面倒を見てくれるのか?
- 利用する側がどこまで面倒を見ないといけないか?
全くもってよく分からなかったので、「spring-boot-starter-〇〇」について確認してみました。
そして、「Qiita」で、「quartz spring」で検索したら、2件しかヒットせず、しかも「データベース」と連携してるものは、0件というね...
情報が少な過ぎて、辛い...
とりあえず、「spring-boot-starter-〇〇」の情報を確認すると、
Spring Boot Starters are a set of convenient dependency descriptors that you can include in your application. You get a one-stop-shop for all the Spring and related technology that you need without having to hunt through sample code and copy paste loads of dependency descriptors. For example, if you want to get started using Spring and JPA for database access include the spring-boot-starter-data-jpa
dependency in your project, and you are good to go.
https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-starters
⇧ ってあるところを見ると、「Spring」関連の技術が洩れなく利用できる状態になるってことらしい。
つまり「spring framework」で「依存性の注入(DI:Dependency Injection)」を実現してくれる仕組みなんかも含まれてるんかな?と思ったら、
What is in a name
All official starters follow a similar naming pattern; spring-boot-starter-*
, where *
is a particular type of application. This naming structure is intended to help when you need to find a starter. The Maven integration in many IDEs lets you search dependencies by name. For example, with the appropriate Eclipse or Spring Tools plugin installed, you can press ctrl-space
in the POM editor and type “spring-boot-starter” for a complete list.
https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-starters
⇧ っていう説明で、
一応、「spring-boot-starter-*」の一覧も掲載してくれてるっぽいんですが、
Name | Description |
---|---|
Core starter, including auto-configuration support, logging and YAML |
|
Starter for using Spring AMQP and Rabbit MQ |
|
Starter for aspect-oriented programming with Spring AOP and AspectJ |
|
Starter for JMS messaging using Apache Artemis |
|
Starter for using Spring Batch |
|
Starter for using Spring Framework’s caching support |
|
Starter for using Cassandra distributed database and Spring Data Cassandra |
|
Starter for using Cassandra distributed database and Spring Data Cassandra Reactive |
|
Starter for using Couchbase document-oriented database and Spring Data Couchbase |
|
Starter for using Couchbase document-oriented database and Spring Data Couchbase Reactive |
|
Starter for using Elasticsearch search and analytics engine and Spring Data Elasticsearch |
|
Starter for using Spring Data JDBC |
|
Starter for using Spring Data LDAP |
|
Starter for using MongoDB document-oriented database and Spring Data MongoDB |
|
Starter for using MongoDB document-oriented database and Spring Data MongoDB Reactive |
|
Starter for using Neo4j graph database and Spring Data Neo4j |
|
Starter for using Spring Data R2DBC |
|
Starter for using Redis key-value data store with Spring Data Redis and the Lettuce client |
|
Starter for using Redis key-value data store with Spring Data Redis reactive and the Lettuce client |
|
Starter for exposing Spring Data repositories over REST using Spring Data REST |
|
Starter for building MVC web applications using FreeMarker views |
|
Starter for building MVC web applications using Groovy Templates views |
|
Starter for building hypermedia-based RESTful web application with Spring MVC and Spring HATEOAS |
|
Starter for using Spring Integration |
|
Starter for using JDBC with the HikariCP connection pool |
|
Starter for building RESTful web applications using JAX-RS and Jersey. An alternative to |
|
Starter for using jOOQ to access SQL databases with JDBC. An alternative to |
|
Starter for reading and writing json |
|
Starter for JTA transactions using Atomikos |
|
Starter for using Java Mail and Spring Framework’s email sending support |
|
Starter for building web applications using Mustache views |
|
Starter for using Spring Security’s OAuth2/OpenID Connect client features |
|
Starter for using Spring Security’s OAuth2 resource server features |
|
Starter for using the Quartz scheduler |
|
Starter for building RSocket clients and servers |
|
Starter for using Spring Security |
|
Starter for testing Spring Boot applications with libraries including JUnit Jupiter, Hamcrest and Mockito |
|
Starter for building MVC web applications using Thymeleaf views |
|
Starter for using Java Bean Validation with Hibernate Validator |
|
Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container |
|
Starter for using Spring Web Services |
|
Starter for building WebFlux applications using Spring Framework’s Reactive Web support |
|
Starter for building WebSocket applications using Spring Framework’s WebSocket support |
⇧「spring-boot-starter」の扱いがよく分かりませんと。
「spring-boot-starter」と「spring-boot-starter-*」の関係がいまいちよう分からんのですよ。
つまり、「spring-boot-starter-*」は「spring-boot-starter」の機能を受け継いでるのか、それとも、「spring-boot-starter-*」を読み込んだだけでは「spring-boot-starter」の機能は使えないのか、って説明が無いので解釈が難しいところですが、特に「spring-boot-starter-*」に「spring-boot-starter」の機能が含まれるとは記載されていないのでモヤモヤ感が半端ない...。
というわけで、試しに「依存関係」を見比べてみた。
plugins { id "org.springframework.boot.starter" } description = "Core starter, including auto-configuration support, logging and YAML" dependencies { api(project(":spring-boot-project:spring-boot")) api(project(":spring-boot-project:spring-boot-autoconfigure")) api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-logging")) api("jakarta.annotation:jakarta.annotation-api") api("org.springframework:spring-core") api("org.yaml:snakeyaml") }
plugins { id "org.springframework.boot.starter" } description = "Starter for using the Quartz scheduler" dependencies { api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter")) api("org.springframework:spring-context-support") api("org.springframework:spring-tx") api("org.quartz-scheduler:quartz") }
⇧ どうやら、「spring-boot-starter-*」は「spring-boot-starter」の「依存関係」を引き継いでるっぽい雰囲気なんだけど、「build.gradle」の8行目の書きっぷりがどういうことをしてくれてるのかがよく分からんけども...
spring-boot-starter-quartzを試してみる
Eclipseを起動して、「ファイル(F)」>「新規(N)」>「その他(O)...」を選択。
「Spring Boot」>「Spring スターター・プロジェクト」を選択し、「次へ(N)>」を押下。
「名前」を適当に入力し、「型:」は「Gradle」にしてます。「次へ(N)>」を押下。
追加した「依存関係」は、以下のキャプチャ画像の通り。「次へ(N)>」を押下。
「完了(F)>」を押下。
「ビルドツール」が「Gradle」の「Spring Boot」のプロジェクトが作成されました。
「build.gradle」を確認してみる。
plugins { id 'org.springframework.boot' version '2.6.0' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-quartz' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'org.postgresql:postgresql' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' } test { useJUnitPlatform() }
⇧ ってな感じです。(「Spring Boot」の実行でエラーが出てしまったので、後で、「依存関係」追加してます。追加した「依存関係」を含めた「build.gradle」は後述で掲載。)
で、「quartz」でデータベース」を使う場合は、「quartz」用のテーブルを作成する必要があるらしく、
⇧ 上記で公開されてる「table-〇〇.sql」の中から自分の環境で利用してる「データベース」のものを探して、ダウンロードして実施すれば良いらしい。
自分のローカル環境の「PostgreSQL」で試した限りでは、「qrtz_〇〇」って「テーブル」が作成される感じ。
「qrtz_〇〇」って「テーブル」が何に使われるかと言うと、
The RAMJobStore is the default JobStore which utilizes RAM as its storage device. The ramification of this is that access is extremely fast, but the data is completely volatile – therefore this JobStore should not be used if true persistence between program shutdowns is required. The JobStoreSupport contains base functionality for JDBC-based JobStore implementations.
https://examples.javacodegeeks.com/enterprise-java/quartz/java-quartz-architecture-example/
⇧上記サイト様によりますと、「Job」を保存しておくために「Job Store」が利用されるらしいのですが、「RAM」だと仮に「アプリケーション」が稼働してる「マシン」が停止してしまうと「データ」が消えてしまうので、「データ」を「永続化」するためには「JDBC」を使えば良い、ってことで「データベース」を利用して「Job」を保存するために「qrtz_〇〇」って「テーブル」が必要になるってことらしい。
実際には、
⇧ 上図のようなクラスが必要になってくるみたいね。
実装に入る前に、「qrtz_〇〇」テーブル用の設定が必要になってくるらしく、「quartz.properties」もしくは、「application.properties」に設定を書く必要があるそうな。「application.properties」のほうには、
⇧「spring.quartz.〇〇」な設定で必要そうなものを書けば良いらしいとは思うんだけど、ネットのexampleでほとんど設定してる人が見当たらない気がする...
そして、「quartz.properties」のほうはと言うと、「Quartz」のドキュメントによると、
Configuration of Quartz is typically done through the use of a properties file, in conjunction with the use of StdSchedulerFactory
(which consumes the configuration file and instantiates a scheduler).
https://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html
By default, StdSchedulerFactory
load a properties file named quartz.properties
from the "current working directory". If that fails, then the quartz.properties
file located (as a resource) in the org/quartz
package is loaded. If you wish to use a file other than these defaults, you must define the system property org.quartz.properties
to point to the file you want.
https://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html
⇧ デフォルトだと「StdSchedulerFactory」が「properties file」を読み込むらしいんだけど、そもそも、「StdSchedulerFactory」が何なのか不明なんですけどね...
An implementation of
that does all of its work of creating a SchedulerFactory
QuartzScheduler
instance based on the contents of a Properties
file.
https://www.quartz-scheduler.org/api/2.1.7/org/quartz/impl/StdSchedulerFactory.html
⇧ ってあって、「SchedulerFactory」って「インターフェイス」を継承してるってことなんだけど、
A singleton implementation of
.SchedulerFactory
https://www.quartz-scheduler.org/api/2.1.7/org/quartz/impl/DirectSchedulerFactory.html
⇧「SchedulerFactory」って「インターフェイス」を継承してるクラスとして「DirectSchedulerFactory」ってものも存在するそうな。
じゃあ「SchedulerFactory」って「インターフェイス」ってのはというと、
Provides a mechanism for obtaining client-usable handles to Scheduler
instances.
https://www.quartz-scheduler.org/api/2.1.7/org/quartz/impl/DirectSchedulerFactory.html
⇧ ってあることから、この「インターフェイス」が無いと「Quartz」が始まらないということらしい。
まぁ、基本的には「SchedulerFactory」を使っていけば良いってことですかね。
で、「Quartz」側の準備ができたら、「Spring Boot」側で「Quartz」が認識されるようにしてあげないといけないらしい。
Quartz Scheduler
を作成および構成し、そのライフサイクルを Spring アプリケーションコンテキストの一部として管理し、依存性注入のための Bean 参照としてスケジューラを公開する FactoryBean
。
https://spring.pleiades.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/quartz/SchedulerFactoryBean.html
⇧ っていうか、「spring-boot-starter-quartz」を「依存関係」に追加したら、すぐ動くんじゃなかったんか...
なので、「Spring Boot」で「Quartz」を使う場合は、
最低、赤枠のクラスは最低限必要になってくるんかな、ネット上のexampleを見た感じだと。あと、上図の赤枠で追加できてないけど、実行クラスが必要ですかね。
で、肝心の実行クラスについては、「@Controller」や「@RestController」の付いたクラス経由ってexampleが多いんですが、
⇧ 上記サイト様が「org.springframework.boot.ApplicationRunner」という「インターフェイス」を利用して、実行してたので、「オフライン」でも試せそうです。
そもそも、「バッチ処理」って「オフライン」が一般的だと思いますし(勝手なイメージ)。
で、何やかんやで、エラーとかも出て、「build.gradle」に「c3p0」ってのを追加したりもしてますが、ファイルの構成は以下のようになりました。
使用した「テーブル」は、「PostgreSQL」に「learning」って「スキーマ」を作って、そこに作成してた「user」テーブルを利用してます。
■テーブルの構造
■制約
というわけで、設定は以下のような感じに。
■/quartz-boot/build.gradle
plugins { id 'org.springframework.boot' version '2.6.0' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-quartz' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'org.postgresql:postgresql' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' // https://mvnrepository.com/artifact/com.mchange/c3p0 implementation group: 'com.mchange', name: 'c3p0', version: '0.9.5.5' } test { useJUnitPlatform() }
■/quartz-boot/src/main/resources/application.properties
# PsogreSQLを利用するための設定 spring.datasource.driver-class-name=org.postgresql.Driver spring.datasource.url=jdbc:postgresql://localhost:5434/postgres spring.datasource.username=postgres spring.datasource.password=postgres # SQL文とかのデバッグログの表示とか spring.jpa.hibernate.ddl-auto=validate spring.jpa.properties.hibernate.format_sql=true spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect #hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect logging.level.org.hibernate.SQL=DEBUG logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE #hibernate.globally_quoted_identifiers_skip_column_definitions=true ## QuartzProperties spring.quartz.job-store-type = jdbc spring.quartz.properties.org.quartz.threadPool.threadCount = 5 #Quartz Log level logging.level.org.springframework.scheduling.quartz=DEBUG logging.level.org.quartz=DEBUG
■/quartz-boot/src/main/resources/quartz.properties
#============================================================================ # Configure Main Scheduler Properties #============================================================================ org.quartz.scheduler.instanceName: TestScheduler org.quartz.scheduler.instanceId: instance_one org.quartz.scheduler.skipUpdateCheck: true #============================================================================ # Configure ThreadPool #============================================================================ org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount: 5 org.quartz.threadPool.threadPriority: 5 #============================================================================ # Configure JobStore #============================================================================ org.quartz.jobStore.misfireThreshold: 60000 org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate org.quartz.jobStore.useProperties=false org.quartz.jobStore.dataSource=myDS org.quartz.jobStore.tablePrefix=QRTZ_ org.quartz.jobStore.isClustered=true #============================================================================ # Other Example Delegates #============================================================================ #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DB2v6Delegate #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DB2v7Delegate #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DriverDelegate #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.HSQLDBDelegate #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.MSSQLDelegate #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PointbaseDelegate org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.WebLogicDelegate #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.WebLogicOracleDelegate #============================================================================ # Configure Datasources #============================================================================ org.quartz.dataSource.myDS.driver: org.postgresql.Driver org.quartz.dataSource.myDS.URL: jdbc:postgresql://localhost:5434/postgres org.quartz.dataSource.myDS.user: postgres org.quartz.dataSource.myDS.password: postgres org.quartz.dataSource.myDS.maxConnections: 5 org.quartz.dataSource.myDS.validationQuery: select 0 #============================================================================ # Configure Plugins #============================================================================ #org.quartz.plugin.shutdownHook.class: org.quartz.plugins.management.ShutdownHookPlugin #org.quartz.plugin.shutdownHook.cleanShutdown: true #org.quartz.plugin.triggHistory.class: org.quartz.plugins.history.LoggingJobHistoryPlugin
そんで、ソースコードは以下のような感じに。
■/quartz-boot/src/main/java/com/example/demo/batch/config/AutowiringSpringBeanJobFactory.java
package com.example.demo.batch.config; import org.quartz.spi.TriggerFiredBundle; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.scheduling.quartz.SpringBeanJobFactory; public class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware{ AutowireCapableBeanFactory beanFactory; @Override public void setApplicationContext(final ApplicationContext context) { beanFactory = context.getAutowireCapableBeanFactory(); } @Override protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception { final Object job = super.createJobInstance(bundle); beanFactory.autowireBean(job); return job; } }
■/quartz-boot/src/main/java/com/example/demo/batch/config/QuartzConfig.java
package com.example.demo.batch.config; import java.io.IOException; import java.util.Properties; import org.quartz.spi.JobFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.PropertiesFactoryBean; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.scheduling.quartz.SchedulerFactoryBean; @Configuration public class QuartzConfig { @Autowired ApplicationContext applicationContext; @Bean public JobFactory jobFactory() { AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory(); jobFactory.setApplicationContext(applicationContext); return jobFactory; } @Bean public SchedulerFactoryBean schedulerFactoryBean() throws IOException { SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean(); schedulerFactory.setQuartzProperties(quartzProperties()); schedulerFactory.setWaitForJobsToCompleteOnShutdown(true); schedulerFactory.setAutoStartup(true); schedulerFactory.setJobFactory(jobFactory()); return schedulerFactory; } public Properties quartzProperties() throws IOException { PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean(); propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties")); propertiesFactoryBean.afterPropertiesSet(); return propertiesFactoryBean.getObject(); } }
■/quartz-boot/src/main/java/com/example/demo/entity/UserEntity.java
package com.example.demo.entity; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; import lombok.Data; @Data @Entity @Table(name = "user", schema="learning") public class UserEntity { @Id private Integer id; private String name; }
■/quartz-boot/src/main/java/com/example/demo/repository/UserRepository.java
package com.example.demo.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import com.example.demo.entity.UserEntity; @Repository public interface UserRepository extends JpaRepository<UserEntity, Integer> { }
■/quartz-boot/src/main/java/com/example/demo/batch/service/SchedulerService.java
package com.example.demo.batch.service; import org.springframework.stereotype.Service; @Service public interface SchedulerService { void startAllSchedulers(); }
■/quartz-boot/src/main/java/com/example/demo/batch/service/impl/SchedulersServiceImpl.java
package com.example.demo.batch.service.impl; import java.util.TimeZone; import org.quartz.CronScheduleBuilder; import org.quartz.CronTrigger; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.TriggerBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.quartz.SchedulerFactoryBean; import org.springframework.stereotype.Service; import com.example.demo.batch.job.UserJob; import com.example.demo.batch.service.SchedulerService; @Service public class SchedulersServiceImpl implements SchedulerService { @Autowired private SchedulerFactoryBean schedulerFactoryBean; @Override public void startAllSchedulers() { // Scheduler scheduler = schedulerFactoryBean.getScheduler(); JobDetail jobDetail = JobBuilder.newJob(UserJob.class) .withIdentity("userJob", "jobGroup1") .storeDurably(true) .build(); CronTrigger trigger = TriggerBuilder .newTrigger() .withIdentity("cronTrigger1", "triggerGroup1") .withSchedule( CronScheduleBuilder.cronSchedule("*/1 * * * * ?") .inTimeZone(TimeZone.getTimeZone("Asia/Tokyo"))) .startNow().build(); try { // org.quartz.ObjectAlreadyExistsExceptionの例外を回避する if (scheduler.checkExists(jobDetail.getKey())){ scheduler.deleteJob(jobDetail.getKey()); } scheduler.scheduleJob(jobDetail, trigger); } catch (SchedulerException e) { // TODO 自動生成された catch ブロック e.printStackTrace(); } } }
■/quartz-boot/src/main/java/com/example/demo/batch/job/UserJob.java
package com.example.demo.batch.job; import java.util.List; import java.util.Objects; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.beans.factory.annotation.Autowired; import com.example.demo.entity.UserEntity; import com.example.demo.repository.UserRepository; public class UserJob implements Job { @Autowired private UserRepository userRepository; @Override public void execute(JobExecutionContext context) throws JobExecutionException { // TODO 自動生成されたメソッド・スタブ List<UserEntity> userEntityList = userRepository.findAll(); if(Objects.nonNull(userEntityList)) { userEntityList.stream() .forEach(userEntity -> { if ("鈴木".contains(userEntity.getName())) { userEntity.setName("ミスターX"); userRepository.save(userEntity); } }); } } }
■/quartz-boot/src/main/java/com/example/demo/batch/SchedulerStartUpHundler.java
package com.example.demo.batch; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; import com.example.demo.batch.service.SchedulerService; import lombok.extern.slf4j.Slf4j; @Slf4j @Component public class SchedulerStartUpHundler implements ApplicationRunner { @Autowired private SchedulerService schedulerService; @Override public void run(ApplicationArguments args) throws Exception { // log.info("Schedule all new scheduler jobs at app startup - starting"); schedulerService.startAllSchedulers(); log.info("Schedule all new scheduler jobs at app startup - complete"); } }
■/quartz-boot/src/main/java/com/example/demo/QuartzBootApplication.java
package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class QuartzBootApplication { public static void main(String[] args) { SpringApplication.run(QuartzBootApplication.class, args); } }
⇧ ってな感じで、「バッチ処理」の「Job」としては、「learning.user」テーブルの「name」カラムの値が「鈴木」ってレコードがあったら、「鈴木」を「ミスターX」に更新するという、全く実用的ではないサンプルなので、このあたりは、ご自分の用途に合わせていただければと。
「learning.user」テーブルのデータに「鈴木」を含めて、
Eclipseのほうで、実行してみます。
起動して、しばらくしたら、「コンソール」タブの右のほうにある を押下で停止します。
「テーブル」を更新してみると、
「鈴木」から「ミスターX」に更新されたので、上手くいったようです。
ただ、「Spring Boot」の「ApplicationRunner」なのか「Quartz」なのか分からんけど、「プロセス」が終了してないっぽいので、「タスクマネージャー」から「java.exe」の「タスク終了(E)」して、一度Eclipseも閉じました。(「Java仮想マシン(JVM:Java Virtual Machine)」が停止すれば、「Java」の「プロセス」も終了するかなと思い)
というわけで、「Spring Boot」の「ApplicationRunner」を利用するって方法に辿り着くまでに時間がかかって、肝心の「Quartz」の「JobDetail」とか「Tigger」のコーディングがいろいろ試せなかったというね...
しかも、「Spring Boot」の「ApplicationRunner」の「プロセス」の制御方法が分からんし...
あと、「qrtz_〇〇」テーブルに登録される「Trigger」とかが、前回登録されてたのが消されちゃってるので、「application.properties」か「quartz.properties」かのどっちかに何かしら設定をする必要があるんかな?
2022年2月13日(日)追記:↓ ここから
「spring-boot-autoconfigure」の依存関係を追加すれば、「SchedulerFactoryBean」クラスを継承したクラスを作成しなくてもQuartzの機能を使えました。
⇧ 手前味噌で恐縮ですが、上記の記事でまとめております。
それにしても、「spring-boot-autoconfigure」を依存関係に追加してQuartzを使ってる情報がネットで皆無だったのが気になりますな...
2022年2月13日(日)追記:↑ ここまで
今回もモヤモヤ感が半端ない...
今回はこのへんで。