Spring Scheduling APIのためのQuarkus Extension
ユーザーは 通常のQuarkusスケジューラを使用することが推奨されますが、Quarkusは spring-scheduled
エクステンションの形でSpring Scheduledの互換性レイヤーを提供しています。
このガイドでは、よく知られているSpring Scheduledアノテーションを利用して、Quarkusアプリケーションがどのようにタスクを設定、スケジュールするかを説明します。
前提条件
このガイドを完成させるには、以下が必要です:
-
約15分
-
IDE
-
JDK 17+がインストールされ、
JAVA_HOME
が適切に設定されていること -
Apache Maven 3.9.8
-
使用したい場合は、 Quarkus CLI
-
ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること
-
Spring Webエクステンションに精通していること
ソリューション
次の章で紹介する手順に沿って、ステップを踏んでアプリを作成することをお勧めします。ただし、完成した例にそのまま進んでも構いません。
Gitレポジトリをクローンするか git clone https://github.com/quarkusio/quarkus-quickstarts.git
、 アーカイブ をダウンロードします。
ソリューションは spring-scheduled-quickstart
ディレクトリ にあります。
Mavenプロジェクトの作成
まず、新しいプロジェクトが必要です。以下のコマンドで新規プロジェクトを作成します:
Windowsユーザーの場合:
-
cmdを使用する場合、(バックスラッシュ
\
を使用せず、すべてを同じ行に書かないでください)。 -
Powershellを使用する場合は、
-D
パラメータを二重引用符で囲んでください。例:"-DprojectArtifactId=spring-scheduler-quickstart"
このコマンドは、Maven プロジェクトを生成し、spring-scheduled
エクステンションをインポートします。
すでにQuarkusプロジェクトが設定されている場合は、プロジェクトのベースディレクトリで以下のコマンドを実行することで、 spring-scheduled
エクステンションをプロジェクトに追加することができます。
quarkus extension add spring-scheduled
./mvnw quarkus:add-extension -Dextensions='spring-scheduled'
./gradlew addExtension --extensions='spring-scheduled'
これにより、ビルドファイルに以下が追加されます:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-spring-scheduled</artifactId>
</dependency>
implementation("io.quarkus:quarkus-spring-scheduled")
スケジュールされたジョブの作成
org.acme.spring.scheduler
パッケージで、以下の内容で CounterBean
クラスを作成します:
package org.acme.spring.scheduler;
import org.springframework.scheduling.annotation.Scheduled;
import java.util.concurrent.atomic.AtomicInteger;
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped (1)
public class CounterBean {
private AtomicInteger counter = new AtomicInteger();
public int get() { (2)
return counter.get();
}
@Scheduled(cron="*/5 * * * * ?") (3)
void cronJob() {
counter.incrementAndGet(); (4)
System.out.println("Cron expression hardcoded");
}
@Scheduled(cron = "{cron.expr}") (5)
void cronJobWithExpressionInConfig() {
counter.incrementAndGet();
System.out.println("Cron expression configured in application.properties");
}
@Scheduled(fixedRate = 1000) (6)
void jobAtFixedRate() {
counter.incrementAndGet();
System.out.println("Fixed Rate expression");
}
@Scheduled(fixedRateString = "${fixedRate.expr}") (7)
void jobAtFixedRateInConfig() {
counter.incrementAndGet();
System.out.println("Fixed Rate expression configured in application.properties");
}
}
1 | application スコープでBeanを宣言します。SpringはBeanの @Scheduled アノテーションのみを検出します。 |
2 | get() メソッドでは、現在の値を取得することができます。 |
3 | Spring @Scheduled アノテーションをcronのような表現で使用し、Quarkusにこのメソッドの実行をスケジュールするよう指示します。この例では、毎日午前10時15分にタスクが実行されるようにスケジュールしています。 |
4 | コードはとても簡単です。毎日、午前10時15分になると、カウンターが増加します。 |
5 | application.properties で設定可能な`cron.expr` で cron のような式でジョブを定義します。 |
6 | 一定の時間間隔で実行されるメソッドを定義します。期間はミリ秒単位で指定します。 |
7 | 一定の時間間隔で実行されるジョブを定義します。application.properties 内で fixedRate.expr で設定可能です。 |
アプリケーション設定ファイルの更新
application.properties
ファイルを編集し、 cron.expr
と fixedRate.expr
の設定を追加します:
# The syntax used by Spring for cron expressions is the same as which is used by regular Quarkus scheduler.
cron.expr=*/5 * * * * ?
fixedRate.expr=1000
リソースとテストの作成
CountResource
クラスを作成して、内容を更新します。
package org.acme.spring.scheduler;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/count")
public class CountResource {
@Inject
CounterBean counter; (1)
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "count: " + counter.get(); (2)
}
}
1 | CounterBean の注入 |
2 | 現在のカウンターの値の返却 |
テストも更新する必要があります。CountResourceTest
クラスを一致するように編集します。
package org.acme.spring.scheduler;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.containsString;
import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;
@QuarkusTest
public class CountResourceTest {
@Test
public void testHelloEndpoint() {
given()
.when().get("/count")
.then()
.statusCode(200)
.body(containsString("count")); (1)
}
}
1 | レスポンスに count が含まれていることを確認 |
アプリケーションをパッケージ化して実行する
アプリケーションを次のように実行します:
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
別のターミナルで、curl localhost:8080/count
を実行し、カウンタの値を確認します。 数秒後、curl localhost:8080/count
を再実行し、カウンタが増分されたことを確認します。
コンソールを見て、以下のメッセージが表示されていることを確認してください:
- Cron expression hardcoded
- Cron expression configured in application.properties
- Fixed Rate expression
- Fixed Rate expression configured in application.properties
これらのメッセージは、 @Scheduled
でアノテーションされたメソッドの実行がトリガーされたことを示しています。
いつものように、アプリケーションは以下の方法でパッケージ化されます。
quarkus build
./mvnw install
./gradlew build
そして、 java -jar target/quarkus-app/quarkus-run.jar
を使って実行します。
次のようにネイティブ実行可能ファイルを生成することもできます。
quarkus build --native
./mvnw install -Dnative
./gradlew build -Dquarkus.native.enabled=true
プロパティー式の使用
Quarkusは、 application.properties
ファイルでのプロパティ式の使用をサポートしているため、タスクの設定を外部化するには、プロパティを application.properties
ファイルに保存し、それぞれ fixedRateString
、 initialDelayString
パラメータを使用する必要があります。
この設定はビルド時設定であり、プロパティ式はビルド時に解決されることに注意してください。
サポートされていないSpring Scheduledの機能
Quarkusは現在、Spring @Scheduledが提供する機能のサブセットのみをサポートしており、さらに多くの機能が計画されています。現在のところ、 fixedDelay
と fixedDelayString
のパラメータはサポートされていません。言い換えれば、 @Scheduled
のメソッドは常に独立して実行されるということです。
重要なテクニカルノート
Quarkus での Spring サポートは、Spring Application Context を開始せず、Spring インフラストラクチャークラスも実行しないことに注意してください。Spring クラスとアノテーションは、メタデータの読み取りにのみ使用されるか、ユーザーコードメソッドの戻り値の型またはパラメーター型として使用されます。エンドユーザーにとってそれが意味することは、任意の Spring ライブラリーを追加しても効果がないということです。さらに、Spring インフラストラクチャークラス (たとえば、org.springframework.beans.factory.config.BeanPostProcessor
など) は実行されません。