The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

アプリケーションの初期化と終了

アプリケーションの起動時にカスタムアクションを実行し、アプリケーションの停止時にすべてをクリーンアップする必要があることがよくあります。このガイドでは、以下の方法を説明します:

  • メインメソッドでQuarkusアプリケーションを書く

  • タスクを実行して終了するコマンドモードのアプリケーションを書く

  • アプリケーションの開始時に通知される

  • アプリケーションが停止したときに通知される

前提条件

このガイドを完成させるには、以下が必要です:

  • 約15分

  • IDE

  • JDK 11+ がインストールされ、 JAVA_HOME が適切に設定されていること

  • Apache Maven 3.8.1+

  • 使用したい場合、 Quarkus CLI

  • ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること

ソリューション

次のセクションで紹介する手順に沿って、ステップを踏んでアプリを作成することをお勧めします。ただし、完成した例にそのまま進んでも構いません。

Gitレポジトリをクローンするか git clone https://github.com/quarkusio/quarkus-quickstarts.gitアーカイブ をダウンロードします。

ソリューションは lifecycle-quickstart ディレクトリ にあります。

Mavenプロジェクトの作成

まず、新しいプロジェクトが必要です。以下のコマンドで新規プロジェクトを作成します。

CLI
quarkus create app org.acme:lifecycle-quickstart \
    --no-code
cd lifecycle-quickstart

Gradleプロジェクトを作成するには、 --gradle または --gradle-kotlin-dsl オプションを追加します。

Quarkus CLIのインストール方法については、Quarkus CLIガイドをご参照ください。

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:2.11.1.Final:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=lifecycle-quickstart \
    -DnoCode
cd lifecycle-quickstart

Gradleプロジェクトを作成するには、 -DbuildTool=gradle または -DbuildTool=gradle-kotlin-dsl オプションを追加します。

以下が生成されます:

  • Mavenの構造

  • nativejvm の両方のモードに対応した Dockerfile ファイルの例

  • アプリケーション設定ファイル

メインメソッド

By default, Quarkus will automatically generate a main method, that will bootstrap Quarkus and then just wait for shutdown to be initiated. Let’s provide our own main method:

package com.acme;

import io.quarkus.runtime.annotations.QuarkusMain;
import io.quarkus.runtime.Quarkus;

@QuarkusMain  (1)
public class Main {

    public static void main(String ... args) {
        System.out.println("Running main method");
        Quarkus.run(args); (2)
    }
}
1 このアノテーションは、設定でオーバーライドされない限り、これをメインのメソッドとして使用するようQuarkusに指示します。
2 これによりQuarkusが起動します。

このメインクラスはQuarkusを起動し、停止するまで実行します。これは自動生成されたメインクラスと変わりませんが、MavenやGradleのコマンドを実行する必要がなく、IDEから直接起動するだけで済むという利点があります。

まだQuarkusが設定されておらず、Quarkusは別のClassLoaderで動作する可能性があるため、このメインメソッドでビジネスロジックを行うことは推奨されていません。起動時にロジックを実行したい場合は、以下のように io.quarkus.runtime.QuarkusApplication を使用してください。

起動時に実際にビジネスロジックを実行したい場合(またはタスクを完了してから終了するアプリケーションを書きたい場合)、runメソッドに io.quarkus.runtime.QuarkusApplication クラスを指定する必要があります。Quarkusが起動すると、アプリケーションの run メソッドが呼び出されます。このメソッドが返されると、Quarkusアプリケーションは終了します。

起動時にロジックを実行したい場合は、 Quarkus.waitForExit() を呼び出す必要があります。このメソッドは、シャットダウンが要求されるまで待機します( Ctrl+C を押したときのような外部シグナルや、スレッドが Quarkus.asyncExit() を呼び出したときのような外部シグナルのいずれか)。

その一例が以下のようなものです:

package com.acme;

import io.quarkus.runtime.Quarkus;
import io.quarkus.runtime.QuarkusApplication;
import io.quarkus.runtime.annotations.QuarkusMain;

@QuarkusMain
public class Main {
    public static void main(String... args) {
        Quarkus.run(MyApp.class, args);
    }

    public static class MyApp implements QuarkusApplication {

        @Override
        public int run(String... args) throws Exception {
            System.out.println("Do startup logic here");
            Quarkus.waitForExit();
            return 0;
        }
    }
}

コマンドライン引数の注入

コマンドラインで渡された引数を注入することができます:

@Inject
@CommandLineArguments
String[] args;

コマンドライン引数は、プロパティ quarkus.args-D フラグを介してアプリケーションに渡すことができます。

  • Quarkus開発モードの場合:

    CLI
    quarkus dev -Dquarkus.args=cmd-args
    Maven
    ./mvnw quarkus:dev -Dquarkus.args=cmd-args
    Gradle
    ./gradlew --console=plain quarkusDev -Dquarkus.args=cmd-args
  • runner jarの場合: java -Dquarkus.args=<cmd-args> -jar target/quarkus-app/quarkus-run.jar

  • ネイティブ実行可能ファイルの場合: ./target/lifecycle-quickstart-1.0-SNAPSHOT-runner -Dquarkus.args=<cmd-args>

スタートアップとシャットダウンのイベントをリッスンする

org.acme.lifecycle パッケージ内に AppLifecycleBean という名前の新しいクラスを作成し(または別の名前を選び)、以下の内容をコピーします。

package org.acme.lifecycle;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;

import io.quarkus.runtime.ShutdownEvent;
import io.quarkus.runtime.StartupEvent;
import org.jboss.logging.Logger;

@ApplicationScoped
public class AppLifecycleBean {

    private static final Logger LOGGER = Logger.getLogger("ListenerBean");

    void onStart(@Observes StartupEvent ev) {               (1)
        LOGGER.info("The application is starting...");
    }

    void onStop(@Observes ShutdownEvent ev) {               (2)
        LOGGER.info("The application is stopping...");
    }

}
1 アプリケーションの起動時に呼び出されるメソッド
2 アプリケーションの終了時に呼び出されるメソッド
また、各再配置の間に 開発モード でイベントが呼び出されます。
メソッドは注入されたBeanにアクセスすることができます。詳細は AppLifecycleBean.java クラスを確認してください。

@Initialized(ApplicationScoped.class) との違いは? @Destroyed(ApplicationScoped.class)

JVMモードでは、 StartupEvent が常に @Initialized(ApplicationScoped.class)後に 起動され、 ShutdownEvent@Destroyed(ApplicationScoped.class)前に 起動されることを除けば、実質的な違いはありません。しかし、ネイティブの実行形式のビルドでは、 @Initialized(ApplicationScoped.class)ネイティブのビルドプロセスの一部 として起動され、 StartupEvent はネイティブイメージが実行されるときに起動されます。詳細は、Bootstrapの3つのフェーズとQuarkus Philosophy を参照してください。

CDIアプリケーションでは、アプリケーションコンテキストが初期化されたときに、Qualifier @Initialized(ApplicationScoped.class) のイベントが発生します。詳しくは 仕様書をご覧ください。

@Startup を使用して、アプリケーション起動時に CDI Bean を初期化する

@Startup でアノテーションされたクラス、プロデューサメソッド、フィールドで表現されたBeanは、アプリケーションの起動時に初期化されます。

package org.acme.lifecycle;

import javax.enterprise.context.ApplicationScoped;

@Startup (1)
@ApplicationScoped
public class EagerAppBean {

   private final String name;

   EagerAppBean(NameGenerator generator) { (2)
     this.name = generator.createName();
   }
}
1 @Startup でアノテーションされた各Beanに対して、 StartupEvent の合成オブザーバが生成されます。デフォルトの優先度が使用されます。
2 Beanのコンストラクタは、アプリケーションの起動時に呼び出され、結果として得られるコンテキストインスタンスがアプリケーションのコンテキストに格納されます。
@Dependent Beanは、 @Dependent Beanに宣言されたオブザーバーの行動に従うために、その後すぐに破壊されます。
クラスが @Startup でアノテーションされていて、スコープのアノテーションがない場合は、 @ApplicationScoped が自動的に追加されます。

アプリケーションをパッケージ化して実行する

アプリケーションを次のように実行します:

CLI
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

ログメッセージが表示されます。アプリケーションが停止すると、2つ目のログメッセージが印刷されます。

いつものように、アプリケーションは以下の方法でパッケージ化できます:

CLI
quarkus build
Maven
./mvnw clean package
Gradle
./gradlew build

そして次のように実行します java -jar target/quarkus-app/quarkus-run.jar

次のようにネイティブ実行可能ファイルを生成することもできます:

CLI
quarkus build --native
Maven
./mvnw package -Dnative
Gradle
./gradlew build -Dquarkus.package.type=native

起動モード

Quarkusには3種類の起動モードがあります。 NORMAL (つまりプロダクション)、 DEVELOPMENTTEST です。 quarkus:dev を実行している場合は DEVELOPMENT 、JUnit テストを実行している場合は TEST 、それ以外の場合は NORMAL となります。

アプリケーションは、 io.quarkus.runtime.LaunchMode enum を CDI Beanに注入するか、静的メソッド io.quarkus.runtime.LaunchMode.current() を呼び出すことで起動モードを取得できます。

グレースフルシャットダウン

Quarkus includes support for graceful shutdown, this allows Quarkus to wait for running requests to finish, up till a set timeout. By default, this is disabled, however you can configure this by setting the quarkus.shutdown.timeout config property. When this is set shutdown will not happen until all running requests have completed, or until this timeout has elapsed. This config property is a duration, and can be set using the standard java.time.Duration format, if only a number is specified it is interpreted as seconds.

リクエストを受け付けるエクステンションは、個別にサポートを追加する必要があります。現時点では HTTP エクステンションだけがこれをサポートしているので、メッセージングリクエストがアクティブなときにシャットダウンが発生する可能性があります。