Quarkus 1.4 で追加されたコマンドラインモード

f:id:Naotsugu:20191119224111p:plain


はじめに

Quarkus 1.4 で Web アプリケーションではなく、コマンドラインアプリケーションの作成がサポートされました。

簡単に使い方を見てみましょう。


プロジェクトの作成

Gradle でプロジェクトを作成します。

$ mkdir example-quarkus-cl
$ cd example-quarkus-cl
$ gradle init

Java アプリケーションとして生成し、build.gradle を以下のように編集します。

plugins {
    id 'java'
    id 'io.quarkus' version '1.4.2.Final'
}

repositories {
    jcenter()
}

dependencies {
    implementation enforcedPlatform("io.quarkus:quarkus-universe-bom:1.4.2.Final")
    implementation 'io.quarkus:quarkus-core'
    implementation 'io.quarkus:quarkus-arc'
}

compileJava {
    options.encoding = 'UTF-8'
    options.compilerArgs << '-parameters'
}

compileTestJava {
    options.encoding = 'UTF-8'
}

java {
    sourceCompatibility = JavaVersion.VERSION_11
    targetCompatibility = JavaVersion.VERSION_11
}

ランタイムとCDIプロバイダが必要なので、io.quarkus:quarkus-coreio.quarkus:quarkus-arc を依存に追加します。


メインクラスの作成

メインクラスは以下のように作成します。

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

@QuarkusMain
public class HelloWorldMain implements QuarkusApplication {
    @Override
    public int run(String... args) throws Exception {
        System.out.println("Hello World");
        return 10;
    }
}

@QuarkusMain アノテーションにてエントリポイントとなるクラスを指定し、QuarkusApplicationrun メソッドを実装します。

QuarkusApplication は以下のようなインターフェースです。

public interface QuarkusApplication {
    int run(String... args) throws Exception;
}

準備はこれだけです。


実行

devモードで実行してみましょう。

$ ./gradlew quarkusDev

> Task :quarkusDev
Port 5005 in use, not starting in debug mode
OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
__  ____  __  _____   ___  __ ____  ______ 
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \   
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/   
2000-00-00 00:00:00,094 INFO  [io.quarkus] (Quarkus Main Thread) Quarkus 1.4.2.Final started in 0.546s. 
2000-00-00 00:00:00,106 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2000-00-00 00:00:00,106 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi]
Hello World
2000-00-00 00:00:00,118 INFO  [io.quarkus] (Quarkus Main Thread) Quarkus stopped in 0.012s
Quarkus application exited with code 10
Press Enter to restart or Ctrl + C to quit

Hello World が出力されました(devモード 起動している場合、Enter キーを押すとアプリケーションが再起動されます)。

devモードでコマンドライン引数を渡すには以下のようにします。

$ ./gradlew quarkusDev --quarkus-args='foo'


Uber Jar から実行するには以下のようにします。

$ ./gradlew quarkusBuild --uber-jar

build 配下に jar が作成されるので、以下のコマンドで実行できます。

$ java -jar ./build/*-runner.jar


QuarkusMain アノテーション

QuarkusMain は Quarkus にアプリケーションのエントリポイントを伝えます。

エントリポイントは QuarkusMain アノテーションの name パラメータで名前を定義することができます。

先程の HelloWorldMain とは別に HelloWorldMain2 を以下のように作成します。

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

@QuarkusMain(name = "secondary")
public class HelloWorldMain2 implements QuarkusApplication {
    @Override
    public int run(String... args) throws Exception {
        System.out.println("Hello World - 2");
        return 10;
    }
}

src/main/resources/application.properties を作成して以下のように指定します。

quarkus.package.main-class=secondary

これにより HelloWorldMain2 を選択的に実行することができます。

quarkus.package.main-class を指定しない場合はデフォルトの名前なしのメインクラスが実行されます(quarkus.package.main-class にはメインクラスの完全修飾名で指定することもできます)。


main メソッドからの実行

通常の Java のメインメソッドから実行するには以下のようにすることができます。

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

@QuarkusMain
public class App {
    public static void main(String[] args) {
        Quarkus.run(HelloWorldMain.class, args);
    }
}

HelloWorldMain 側は QuarkusApplicationrun メソッドを実装するだけです。

import io.quarkus.runtime.QuarkusApplication;

public class HelloWorldMain implements QuarkusApplication {
    @Override
    public int run(String... args) throws Exception {
        System.out.println("Hello World");
        return 10;
    }
}


メインスレッドでの待機

QuarkusApplication からのリターンで Quarkus がシャットダウンして JVM が終了します。

非同期で別スレッドを利用するアプリケーションを扱う場合は以下のようにメインスレッドで終了を待機します。

@QuarkusMain
public class HelloWorldMain implements QuarkusApplication {
    @Override
    public int run(String... args) throws Exception {
        // run async process
        Quarkus.waitForExit();
        return 10;
    }
}

メインスレッド外からアプリケーションをシャットダウンする場合は、Quarkus.asyncExit() を呼び出します。