The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.
このページを編集

Picocli を使ったコマンドモード

Picocli は、リッチなコマンドラインアプリケーションを作成するためのオープンソースツールです。

Quarkus では、Picocli を使用するためのサポートを提供しています。このガイドには、 picocli エクステンションの使用例が記載されています。

Quarkus のコマンドモードに詳しくない場合は、まず コマンドモードのリファレンスガイド を読むことを検討してください。

エクステンション

Quarkus プロジェクトを設定すると、プロジェクトのベースディレクトリーで次のコマンドを実行することで、 picocli エクステンションをプロジェクトに追加できます。

コマンドラインインタフェース
quarkus extension add picocli
Maven
./mvnw quarkus:add-extension -Dextensions='picocli'
Gradle
./gradlew addExtension --extensions='picocli'

これにより、pom.xml に以下が追加されます:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-picocli</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-picocli")

コマンドラインアプリケーションの構築

シンプルなアプリケーション

1 つの Command のみを含むシンプルな Picocli アプリケーションは、次のように作成できます。

package com.acme.picocli;

import picocli.CommandLine;

import jakarta.enterprise.context.Dependent;
import jakarta.inject.Inject;

@CommandLine.Command (1)
public class HelloCommand implements Runnable {

    @CommandLine.Option(names = {"-n", "--name"}, description = "Who will we greet?", defaultValue = "World")
    String name;

    private final GreetingService greetingService;

    public HelloCommand(GreetingService greetingService) { (2)
        this.greetingService = greetingService;
    }

    @Override
    public void run() {
        greetingService.sayHello(name);
    }
}

@Dependent
class GreetingService {
    void sayHello(String name) {
        System.out.println("Hello " + name + "!");
    }
}
1 picocli.CommandLine.Command でアノテーションが付けられたクラスが 1 つだけの場合、それがコマンドラインアプリケーションのエントリーポイントとして自動的に使用されます。
2 picocli.CommandLine.Command でアノテーションされたクラスはすべて CDI Bean として登録されています。
@CommandLine.Command でアノテーションが付けられた Bean では、プロキシーされるスコープ (例: @ApplicationScoped) を使用しないでください 。 Picocli はそのような Bean にフィールド値を設定できないためです。 デフォルトでは、この Picocli エクステンションは @CommandLine.Command でアノテーションが付けられたクラスを @Dependent スコープを使用して登録します。プロキシーされるスコープを使用する必要がある場合は、次の例のように、フィールドではなくセッターにアノテーションを付けてください。
@CommandLine.Command
@ApplicationScoped
public class EntryCommand {
    private String name;

    @CommandLine.Option(names = "-n")
    public void setName(String name) {
        this.name = name;
    }
}

複数のコマンドを使用したコマンドラインアプリケーション

複数のクラスが picocli.CommandLine.Command アノテーションを持つ場合、そのうちの 1 つに io.quarkus.picocli.runtime.annotations.TopCommand アノテーションを付ける必要があります。これは quarkus.picocli.top-command プロパティーで上書きすることができます。

package com.acme.picocli;

import io.quarkus.picocli.runtime.annotations.TopCommand;
import picocli.CommandLine;

@TopCommand
@CommandLine.Command(mixinStandardHelpOptions = true, subcommands = {HelloCommand.class, GoodByeCommand.class})
public class EntryCommand {
}

@CommandLine.Command(name = "hello", description = "Greet World!")
class HelloCommand implements Runnable {

    @Override
    public void run() {
        System.out.println("Hello World!");
    }
}

@CommandLine.Command(name = "goodbye", description = "Say goodbye to World!")
class GoodByeCommand implements Runnable {

    @Override
    public void run() {
        System.out.println("Goodbye World!");
    }
}

Picocli CommandLine インスタンスのカスタマイズ

独自の Bean インスタンスを生成することで、 picocli エクステンションで使用される CommandLine クラスをカスタマイズすることができます。

package com.acme.picocli;

import io.quarkus.picocli.runtime.PicocliCommandLineFactory;
import io.quarkus.picocli.runtime.annotations.TopCommand;
import picocli.CommandLine;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;

@TopCommand
@CommandLine.Command
public class EntryCommand implements Runnable {
    @CommandLine.Spec
    CommandLine.Model.CommandSpec spec;

    @Override
    public void run() {
        System.out.println("My name is: " + spec.name());
    }
}

@ApplicationScoped
class CustomConfiguration {

    @Produces
    CommandLine customCommandLine(PicocliCommandLineFactory factory) { (1)
        return factory.create().setCommandName("CustomizedName");
    }
}
1 PicocliCommandLineFactory は、 TopCommandCommandLine.IFactory を注入した CommandLine のインスタンスを作成します。

プロファイルごとに異なるエントリーコマンド

@IfBuildProfile を使用して、プロファイルごとに異なるエントリーコマンドを作成することができます。

@ApplicationScoped
public class Config {

    @Produces
    @TopCommand
    @IfBuildProfile("dev")
    public Object devCommand() {
        return DevCommand.class; (1)
    }

    @Produces
    @TopCommand
    @IfBuildProfile("prod")
    public Object prodCommand() {
        return new ProdCommand("Configured by me!");
    }

}
1 ここでは java.lang.Class のインスタンスを返すことができます。この場合、 CommandLineCommandLine.IFactory を使ってこのクラスのインスタンスを作成しようとします。

解析された引数での CDI Beans の設定

Picocli によって解析された引数に基づいて CDI Bean を設定するために、 Event<CommandLine.ParseResult> 、または単に CommandLine.ParseResult を使用することができます。このイベントは、このエクステンションによって作成された QuarkusApplication クラスで生成されます。独自の @QuarkusMain を提供している場合、このイベントは発生しません。 CommandLine.ParseResult はデフォルトの CommandLine Bean から作成されます。

@CommandLine.Command
public class EntryCommand implements Runnable {

    @CommandLine.Option(names = "-c", description = "JDBC connection string")
    String connectionString;

    @Inject
    DataSource dataSource;

    @Override
    public void run() {
        try (Connection c = dataSource.getConnection()) {
            // Do something
        } catch (SQLException throwables) {
            // Handle error
        }
    }
}

@ApplicationScoped
class DatasourceConfiguration {

    @Produces
    @ApplicationScoped (1)
    DataSource dataSource(CommandLine.ParseResult parseResult) {
        PGSimpleDataSource ds = new PGSimpleDataSource();
        ds.setURL(parseResult.matchedOption("c").getValue().toString());
        return ds;
    }
}
1 @ApplicationScoped 遅延初期化に使用

独自の QuarkusMain の提供

また、 QuarkusMain でアノテーションされた独自のアプリケーションのエントリーポイントを提供することもできます (コマンドモードのリファレンスガイド に記載されています)。

package com.acme.picocli;

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

import jakarta.inject.Inject;

@QuarkusMain
@CommandLine.Command(name = "demo", mixinStandardHelpOptions = true)
public class ExampleApp implements Runnable, QuarkusApplication {
    @Inject
    CommandLine.IFactory factory; (1)

    @Override
    public void run() {
        // business logic
    }

    @Override
    public int run(String... args) throws Exception {
        return new CommandLine(this, factory).execute(args);
    }
}
1 picocli のエクステンションで作成された Quarkus 互換の CommandLine.IFactory Bean。

開発モード

開発モード、つまり mvn quarkus:dev を実行している場合、アプリケーションは Space bar キーが押されるたびに実行され、再起動されます。また、コマンドラインアプリに引数を渡すには、 quarkus.args システムプロパティを使用します (例: mvn quarkus:dev -Dquarkus.args='--help'mvn quarkus:dev -Dquarkus.args='-c -w --val 1' )。 Gradle プロジェクトの場合、引数は --quarkus-args を使用して渡すことができます。

コマンドライン機能を含む一般的なQuarkusアプリケーション(HTTPベースのサービスなど)を作成する場合は、アプリケーションのライフサイクルを異なる方法で処理する必要があります。 コマンドの Runnable.run() メソッドでは、必ず Quarkus.waitForExit() または Quarkus.asyncExit() を使用してください。これにより、アプリケーションが早期にシャットダウンされるのを防ぎ、適切なシャットダウン処理を行うことができます。

アプリケーションのパッケージ化

Picocli コマンドラインアプリケーションは、複数のフォーマット (JAR、ネイティブ実行可能ファイルなど) でパッケージ化でき、さまざまなリポジトリー (Homebrew、Chocolatey、SDKMAN など) に公開できます。

jar として

Picocli コマンドラインアプリケーションは標準の Quarkus アプリケーションであるため、さまざまなパッケージフォーマット (fast-jar、uber-jar など) で JAR として公開できます。

コマンドラインアプリケーションのコンテキストでは、JAR をそのまま公開する予定の場合は、uber-jar をビルドする方が実用的です。

uber-jar のビルド方法の詳細は、次のドキュメントを参照してください。

その後、標準の java -jar your-application.jar コマンドを使用してアプリケーションを実行できます。

really-executable-jar-maven-plugin などのプラグインを使用すると、コマンドラインアプリケーションの実行を簡素化できます。

ネイティブ実行可能ファイルとして

ネイティブ実行可能ファイル をビルドすることもできますが、ネイティブ実行可能ファイルは移植可能ではなく、サポートされているプラットフォームごとに 1 つのバイナリーが必要であることに注意してください。

アプリケーションの公開

コマンドラインアプリケーションをリポジトリーに公開すると、使用がはるかに簡単になります。 要件に応じて、https://sdkman.io/[SDKMAN!]、macOS の場合は Homebrew、Windows の場合は Chocolatey など、さまざまなアプリケーションリポジトリーを利用できます。

これらのリポジトリーに公開する際には、https://jreleaser.org/[JReleaser] の使用を推奨します。

JReleaser は、アプリケーションを簡単に実行できるように、JAR に実行可能なラッパーを追加します。

詳細情報

Picocli アプリケーションをパッケージ化する方法に関するより一般的な情報については、https://picocli.info/#_packaging_your_application[Picocli 公式ドキュメント] を参照してください。

Kubernetesサポート

コマンドラインアプリケーションを作成したら、 kubernetes エクステンションを追加することで、このアプリケーションを Kubernetes にインストールして使用するために必要なリソースを生成することもできます。 kubernetes エクステンションをインストールするには、プロジェクトのベースディレクトリで以下のコマンドを実行します。

コマンドラインインタフェース
quarkus extension add kubernetes
Maven
./mvnw quarkus:add-extension -Dextensions='kubernetes'
Gradle
./gradlew addExtension --extensions='kubernetes'

これにより、 pom.xml に以下が追加されます。

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-kubernetes</artifactId>
</dependency>

そして次に、アプリケーションをビルドします:

コマンドラインインタフェース
quarkus build
Maven
./mvnw install
Gradle
./gradlew build

Kubernetes エクステンションは Picocli エクステンションの存在を検出し、 target/kubernetes/ ディレクトリに Deployment リソースの代わりに Job リソースを生成します。

Jobリソースを生成しない場合は、プロパティ quarkus.kubernetes.deployment-kind を使用して生成したいリソースを指定します。たとえば、Deployment リソースを生成したい場合は、 quarkus.kubernetes.deployment-kind=Deployment を使用します。

さらに、Kubernetes Jobが使用する引数を、プロパティ quarkus.kubernetes.arguments を介して提供することができます。例えば、 quarkus.kubernetes.arguments=A,B というプロパティを追加し、プロジェクトをビルドすると、以下のようなJobリソースが生成されます。

apiVersion: batch/v1
kind: Job
metadata:
  labels:
    app.kubernetes.io/name: app
    app.kubernetes.io/version: 0.1-SNAPSHOT
  name: app
spec:
  completionMode: NonIndexed
  suspend: false
  template:
    metadata:
      labels:
        app.kubernetes.io/name: app
        app.kubernetes.io/version: 0.1-SNAPSHOT
    spec:
      containers:
        - args:
            - A
            - B
          env:
            - name: KUBERNETES_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          image: docker.io/user/app:0.1-SNAPSHOT
          imagePullPolicy: Always
          name: app
          ports:
            - containerPort: 8080
              name: http
              protocol: TCP
      restartPolicy: OnFailure
      terminationGracePeriodSeconds: 10

最後に、KubernetesにインストールされるたびにKubernetesジョブが起動されます。Kubernetesのジョブの実行方法については、こちらの ドキュメント で詳しく解説しています。

設定リファレンス

ビルド時に固定される設定プロパティ - 他のすべての設定プロパティは実行時にオーバーライド可能

Configuration property

デフォルト

Name of bean annotated with io.quarkus.picocli.runtime.annotations.TopCommand or FQCN of class which will be used as entry point for Picocli CommandLine instance. This class needs to be annotated with picocli.CommandLine.Command.

Environment variable: QUARKUS_PICOCLI_TOP_COMMAND

Show more

string

関連コンテンツ