コマンドモードアプリケーション
このリファレンスでは、実行して終了するアプリケーションの書き方について説明しています。
ソリューション
次の章で紹介する手順に沿って、ステップを踏んでアプリを作成することをお勧めします。ただし、完成した例にそのまま進んでも構いません。
Gitリポジトリをクローンする: git clone https://github.com/quarkusio/quarkus-quickstarts.git
、または アーカイブ をダウンロードする。
ソリューションは getting-started-command-mode
ディレクトリ にあります。
Mavenプロジェクトの作成
まず、以下のコマンドで新しいQuarkusプロジェクトを作成します。
Windowsユーザーの場合:
-
cmdを使用する場合、(バックスラッシュ
\
を使用せず、すべてを同じ行に書かないでください)。 -
Powershellを使用する場合は、
-D
パラメータを二重引用符で囲んでください。例:"-DprojectArtifactId=command-mode-quickstart"
推奨のプロジェクト作成コマンドでは、RESTサーバーを含めないようにするため、codestartsを無効にします。 同様に、code.quarkus.ioを使用してプロジェクトを生成する場合は、 MORE OPTIONS → Starter Code で No を選択して、Quarkus REST(旧RESTEasy Reactive)エクステンションを追加しないようにする必要があります。 |
QuarkusのRESTエクステンションは、codestartsでエクステンションを指定しなかった場合にのみ、自動的に追加されます。
コマンドモードアプリケーションの作成
終了するアプリケーションを実装するためには、2つの異なるアプローチがあります。
-
QuarkusApplication
を実装し、Quarkusがこのメソッドを自動的に実行するようにします -
QuarkusApplication
とJava mainメソッドを実装し、Java mainメソッドを使用してQuarkusを起動します
このドキュメントでは、 QuarkusApplication
インスタンスをアプリケーション mainと呼び、Java mainメソッドを持つクラスを Java mainと呼びます。
QuarkusのAPIにアクセスできる最もシンプルなコマンドモードのアプリケーションは、以下のようになります:
import io.quarkus.runtime.QuarkusApplication;
import io.quarkus.runtime.annotations.QuarkusMain;
@QuarkusMain (1)
public class HelloWorldMain implements QuarkusApplication {
@Override
public int run(String... args) throws Exception { (2)
System.out.println("Hello " + args[0]);
return 0;
}
}
1 | @QuarkusMain のアノテーションは、Quarkusにここがメインエントリポイントであることを伝えます。 |
2 | Quarkus が起動すると run メソッドが呼び出され、アプリケーションが終了すると停止します。 |
Main method
Java mainでアプリケーション mainを実行したい場合は以下のようになります:
import io.quarkus.runtime.Quarkus;
import io.quarkus.runtime.annotations.QuarkusMain;
@QuarkusMain
public class JavaMain {
public static void main(String... args) {
Quarkus.run(HelloWorldMain.class, args);
}
}
これは HelloWorldMain
アプリケーション mainを直接実行するのと実質的には同じですが、IDE から実行できるという利点があります。
QuarkusApplication を実装したクラスで Java main がある場合は Java main が実行されます。
|
Java mainはほとんどロジックを実行せず、アプリケーション mainを起動するだけにすることをお勧めします。開発モードでは、Java mainはアプリケーション mainとは異なるClassLoaderで実行されるので、期待通りの動作をしないかもしれません。 |
複数のmainメソッド
アプリケーション内に複数のmainメソッドを持ち、ビルド時にそれらの間で選択することが可能です。 @QuarkusMain
アノテーションはオプションの 'name' パラメーターを取り、 quarkus.package.main-class
ビルド時設定オプションを使用して実行するmainを選択するために使用できます。アノテーションを使用したくない場合は、メインクラスの完全修飾名を指定するために使用することもできます。
デフォルトでは、名前のない(つまり空の文字列) @QuarkusMain
が使用されます。もしこれが存在せず、 quarkus.package.main-class
も指定されていなければ、Quarkusは自動的にアプリケーションを動かすだけのメインクラスを生成します。
@QuarkusMain の name は一意である必要があります(デフォルトの空文字列を含む)。アプリケーション内に複数の @QuarkusMain アノテーションがある場合、名前が一意でないとビルドに失敗します。
|
コマンドモードのライフサイクル
コマンドモードのアプリケーションを実行する場合、基本的なライフサイクルは以下の通りです:
-
Quarkusの起動
-
QuarkusApplication
mainメソッドの実行 -
mainメソッドが返った後にQuarkusをシャットダウンし、JVMを終了します
シャットダウンは常にアプリケーションのメインスレッドがreturnされることで開始されます。起動時に何らかのロジックを実行して、通常のアプリケーションのように実行したい場合 (つまり終了しない) は、メインスレッドから Quarkus.waitForExit
を呼び出す必要があります (非コマンドモードのアプリケーションは、基本的に waitForExit
を呼び出すだけのアプリケーションを実行しているだけです)。
実行中のアプリケーションをシャットダウンしたいが、メインスレッドにいない場合、メインスレッドのブロックを解除してシャットダウン処理を開始するために Quarkus.asyncExit
を呼び出す必要があります。
アプリケーションの実行
To run the command mode application on the JVM, first build it using mvnw package
or equivalent.
Then launch it:
java -jar target/quarkus-app/quarkus-run.jar
You can also build a native application with mvnw package -Dnative
, and launch it with something like:
./target/getting-started-command-mode-1.0-SNAPSHOT-runner
開発モード
また、コマンドモードのアプリケーションについては、開発モードがサポートされています。 開発モードでアプリケーションを起動すると、コマンドモードアプリケーションが実行されます:
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
コマンドモードのアプリケーションでは、コマンドラインで引数を渡す必要があることが多く、これは開発モードでも可能です:
quarkus dev '--help'
./mvnw quarkus:dev -Dquarkus.args='--help'
./gradlew quarkusDev --quarkus-args='--help'
アプリケーションが停止した後、画面の下に以下のように表示されます:
--
Press [space] to restart, [e] to edit command line args (currently '-w --tags 1.0.1.Final'), [r] to resume testing, [o] Toggle test output, [h] for more options>
スペースバー
キーを押せば、アプリケーションが再び起動します。また、 e
ホットキーを使って、コマンドライン引数を編集し、アプリケーションを再起動することもできます。
コマンドモードアプリケーションのテスト
コマンドモード・アプリケーションは、 @QuarkusMainTest
および @QuarkusMainIntegrationTest
のアノテーションを使用してテストすることができます。これらは、 @QuarkusTest
および @QuarkusIntegrationTest
と同様の方法で動作します。 @QuarkusMainTest
は現在のJVM内でCLIテストを実行し、 QuarkusIntegrationTest
は生成された実行ファイル(ジャーおよびネイティブの両方)を実行するために使用されます。
上記のCLIアプリケーションの簡単なテストを以下のように書くことができます:
import io.quarkus.test.junit.main.Launch;
import io.quarkus.test.junit.main.LaunchResult;
import io.quarkus.test.junit.main.QuarkusMainLauncher;
import io.quarkus.test.junit.main.QuarkusMainTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@QuarkusMainTest
public class HelloTest {
@Test
@Launch("World")
public void testLaunchCommand(LaunchResult result) {
Assertions.assertTrue(result.getOutput().contains("Hello World"));
}
@Test
@Launch(value = {}, exitCode = 1)
public void testLaunchCommandFailed() {
}
@Test
public void testManualLaunch(QuarkusMainLauncher launcher) {
LaunchResult result = launcher.launch("Everyone");
Assertions.assertEquals(0, result.exitCode());
Assertions.assertTrue(result.getOutput().contains("Hello Everyone"));
}
}
各テストメソッドは、アプリケーションを自動的に起動するために @Launch
のアノテーションを付けるか、手動で起動するために QuarkusMainLauncher
のパラメータを持つ必要があります。
これを統合テストで拡張し、ネイティブ実行可能ファイルや実行可能jarをテストするために使用することができます:
import io.quarkus.test.junit.main.QuarkusMainIntegrationTest;
@QuarkusMainIntegrationTest
public class HelloIT extends HelloTest {
}
モック
CDI インジェクションは @QuarkusMainTest
テストではサポートされていません。 そのため、QuarkusMock
や @InjectMock
を使用して CDI Bean をモックすることもサポートされていません。
テストプロファイル を活用することで、CDI Beanのモックを作成することが可能です。
例えば、次のテストでは、シングルトン CdiBean1
は MockedCdiBean1
によってモック化されます:
package org.acme.commandmode.test;
import java.util.Set;
import jakarta.enterprise.inject.Alternative;
import jakarta.inject.Singleton;
import org.junit.jupiter.api.Test;
import org.acme.commandmode.test.MyCommandModeTest.MyTestProfile;
import io.quarkus.test.junit.QuarkusTestProfile;
import io.quarkus.test.junit.TestProfile;
import io.quarkus.test.junit.main.Launch;
import io.quarkus.test.junit.main.LaunchResult;
import io.quarkus.test.junit.main.QuarkusMainTest;
@QuarkusMainTest
@TestProfile(MyTestProfile.class)
public class MyCommandModeTest {
@Test
@Launch(value = {})
public void testLaunchCommand(LaunchResult result) {
// ... assertions ...
}
public static class MyTestProfile implements QuarkusTestProfile {
@Override
public Set<Class<?>> getEnabledAlternatives() {
return Set.of(MockedCdiBean1.class); (1)
}
}
@Alternative (2)
@Singleton (3)
public static class MockedCdiBean1 implements CdiBean1 {
@Override
public String myMethod() {
return "mocked value";
}
}
}
1 | 代替モックビーンを有効にしたい CDI ビーンをすべて列挙します。 |
2 | Alternative を @Priority なしで使用します。@Mock を使用しないことを確認してください。 |
3 | モックされたビーンのスコープは、元のビーンと一致する必要があります。 |
このパターンを使用すると、任意のテストに対して特定の選択肢を有効にすることができます。