Picocli を使ったコマンドモード
Picocli は、リッチなコマンドラインアプリケーションを作成するためのオープンソースツールです。
Quarkus では、Picocli を使用するためのサポートを提供しています。このガイドには、 picocli
エクステンションの使用例が記載されています。
Quarkus のコマンドモードに詳しくない場合は、まず コマンドモードのリファレンスガイド を読むことを検討してください。 |
エクステンション
Quarkus プロジェクトを設定すると、プロジェクトのベースディレクトリーで次のコマンドを実行することで、 picocli
エクステンションをプロジェクトに追加できます。
quarkus extension add picocli
./mvnw quarkus:add-extension -Dextensions='picocli'
./gradlew addExtension --extensions='picocli'
これにより、pom.xml
に以下が追加されます:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-picocli</artifactId>
</dependency>
implementation("io.quarkus:quarkus-picocli")
シンプルなコマンドラインアプリケーション
Command
を 1 つだけ使ったシンプルな PicocliApplication は、以下のように作成できます。
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 つだけある場合、これは Picocli CommandLine のエントリーポイントとして使用されます。 |
2 | picocli.CommandLine.Command でアノテーションされたクラスはすべて CDI Bean として登録されています。 |
@CommandLine.Command を持つ Bean では、プロキシーされるスコープを使用してはいけません (例: @ApplicationScope は使用しないでください)。Picocli はそのような Bean でフィールド値を設定できないためです。このエクステンションは @CommandLine.Command アノテーションを持つクラスを @Depended スコープを使って登録します。プロキシーされるスコープを使用する必要がある場合は、フィールドではなくセッターを次の例のようにアノテーションしてください。
|
@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 は、 TopCommand と CommandLine.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 のインスタンスを返すことができます。この場合、 CommandLine は CommandLine.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。 |
ネイティブモードのサポート
このエクステンションでは、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'
開発モード
In the development mode, i.e. when running mvn quarkus:dev
, the application is executed and restarted every time the Space bar
key is pressed. You can also pass arguments to your command line app via the quarkus.args
system property, e.g. mvn quarkus:dev -Dquarkus.args='--help'
and mvn quarkus:dev -Dquarkus.args='-c -w --val 1'
.
For Gradle projects, arguments can be passed using --quarkus-args
.
If you’re creating a typical Quarkus application (e.g., HTTP-based services) that includes command-line functionality, you’ll need to handle the application’s lifecycle differently. In the |
Kubernetesサポート
コマンドラインアプリケーションを作成したら、 kubernetes
エクステンションを追加することで、このアプリケーションを Kubernetes にインストールして使用するために必要なリソースを生成することもできます。 kubernetes
エクステンションをインストールするには、プロジェクトのベースディレクトリで以下のコマンドを実行します。
quarkus extension add kubernetes
./mvnw quarkus:add-extension -Dextensions='kubernetes'
./gradlew addExtension --extensions='kubernetes'
これにより、 pom.xml
に以下が追加されます。
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-kubernetes</artifactId>
</dependency>
そして次に、アプリケーションをビルドします:
quarkus build
./mvnw install
./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 |
型 |
デフォルト |
||
---|---|---|---|---|
Set this to false to use the
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: Show more |
boolean |
|
||
Name of bean annotated with Environment variable: Show more |
string |