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 エクステンションをプロジェクトに追加できます。

./mvnw quarkus:add-extension -Dextensions="picocli"

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

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

シンプルなコマンドラインアプリケーション

Command を 1 つだけ使ったシンプルな PicocliApplication は、以下のように作成できます。

package com.acme.picocli;

import picocli.CommandLine;

import javax.enterprise.context.Dependent;
import javax.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 つだけある場合、これは Picocli CommandLine のエントリーポイントとして使用されます。
2 picocli.CommandLine.Command でアノテーションされたクラスはすべて CDI Bean として登録されています。
Beans with @CommandLine.Command should not use proxied scopes (e.g. do not use @ApplicationScope) because Picocli will not be able to set field values in such beans. This extension will register classes with @CommandLine.Command annotation using @Depended scope. If you need to use proxied scope, then annotate setter and not field, for example:
@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 javax.enterprise.context.ApplicationScoped;
import javax.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 javax.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。

ネイティブモードのサポート

このエクステンションでは、Quarkus 標準のビルドステップメカニズムを使用して、GraalVM Nativeイメージをサポートしています。将来のpicocliリリースで互換性のない変更が問題を引き起こす例外的なケースでは、一時的な回避策として、以下の設定を使用してpicocliプロジェクトのアノテーションプロセッサーにフォールバックすることができます。

<dependency>
  <groupId>info.picocli</groupId>
  <artifactId>picocli-codegen</artifactId>
</dependency>

Gradle の場合は、 build.gradle ファイルの dependencies セクションに以下を追加する必要があります。

annotationProcessor enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")
annotationProcessor 'info.picocli:picocli-codegen'

開発モード

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

設定リファレンス

ビルド時に固定される設定プロパティ - それ以外の設定プロパティは実行時に上書き可能

Configuration property

タイプ

デフォルト

Set this to false to use the picocli-codegen annotation processor instead of build steps. CAUTION: this will have serious build-time performance impact since this is run on every restart in dev mode, use with care! This property is intended to be used only in cases where an incompatible change in the picocli library causes problems in the build steps used to support GraalVM Native images. In such cases this property allows users to make the trade-off between fast build cycles with the older version of picocli, and temporarily accept slower build cycles with the latest version of picocli until the updated extension is available.

Environment variable: QUARKUS_PICOCLI_NATIVE_IMAGE_PROCESSING_ENABLE

boolean

true

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

string