Platform
Quarkusエクステンションエコシステムは、Quarkusコア開発チームを含むコミュニティによって開発・保守されたQuarkusエクステンションで構成されています。Quarkusエコシステム("Quarkus universe"と呼ばれることもあります)には、これまでに開発されたすべてのQuarkusエクステンションが含まれていますが、Quarkusプラットフォームという概念もあります。
Quarkusプラットフォームとは
Quarkusプラットフォームは、QuarkusでJavaアプリケーションを構築、テスト、デプロイすることを容易にする、厳選されたエクステンション、ツール、設定のセットです。
Quarkusプラットフォームの基本的な約束事は、プラットフォームで構成されるQuarkusエクステンションを組み合わせて、お互いに競合することなく同じアプリケーションで使用することができるということです。Quarkusプラットフォームを作成する各組織は、プラットフォームに受け入れられるエクステンションについて独自の基準を設定し、受け入れられたエクステンション間の互換性を保証する手段を確立することができます。
Quarkusプラットフォームの利点
同じプロジェクトで複数のエクステンションを使用する場合、QuarkusプラットフォームのBOMは以下を保証します。
-
依存関係間のバージョン互換性;
-
依存関係管理の簡素化;
-
アップグレードの容易化。
QuarkusプラットフォームBOM
各Quarkusプラットフォームは、次のようなMaven BOMアーティファクトを提供することが期待されています:
-
io.quarkus:quarkus-bomの選択されたバージョンをインポートすること (プラットフォームの BOM は最後にフラット化されますが、io.quarkus:quarkus-bomの何らかのバージョンに基づいていなければなりません) -
プラットフォームを構成するすべてのQuarkusエクステンションアーティファクト(ランタイムとデプロイメントのもの)を含むこと
-
プラットフォームエクステンション間の互換性を保証するために、遷移的な依存関係のバージョンを整列させるために必要なすべてのサードパーティ製アーティファクトが含まれていること
-
プラットフォームJSONディスクリプタアーティファクトを含むこと
-
プラットフォーム設定プロパティ アーティファクトを含む場合があります
QuarkusプラットフォームからエクステンションをインクルードしたいQuarkusアプリケーションは、QuarkusプラットフォームのBOMをインポートします。
Quarkusプラットフォームディスクリプタ
Quarkusプラットフォームディスクリプタは、プラットフォームとそのエクステンションに関する情報をQuarkusツールに提供するJSONアーティファクトです。例: http://code.quarkus.io やQuarkusコマンドラインツールは、ユーザーの要求に応じて、このディスクリプタを参照して、プロジェクトへのエクステンションのリスト化、追加、削除を行います。このアーティファクトは、Quarkusプラットフォームディスクリプタとしても使用されます。Quarkusツールがプロジェクトで使用されているQuarkusプラットフォームを識別する必要がある場合、プロジェクトの依存関係バージョン制約(Maven用語では、 dependencyManagement セクションから管理されている依存関係の有効なリスト)を分析して、その中からプラットフォームディスクリプタのアーティファクトを探します。プラットフォームディスクリプタがQuarkusプラットフォームBOMに含まれていることを考えると、すべてのQuarkusアプリケーションは、インポートされたプラットフォームBOMからのプラットフォームディスクリプタアーティファクトを依存関係バージョン制約(Maven用語では管理された依存関係)として継承します。
プロジェクトの依存性制約の中でQuarkusプラットフォームディスクリプタを簡単に識別できるように、プラットフォームディスクリプタのMavenアーティファクト座標は、以下の命名規則に従う必要があります。
-
ディスクリプタアーティファクトの
groupIdは、対応するQuarkus Platform BOMのgroupIdと一致している必要があります。 -
ディスクリプタアーティファクトの
artifactIdは、対応するQuarkus Platform BOMのartifactIdで、サフィックスが-quarkus-platform-descriptorである必要があります。 -
ディスクリプタアーティファクトの
classifierは、対応するQuarkus Platform BOMのversionと一致している必要があります。 -
ディスクリプタアーティファクトの
typeはjsonである必要があります。 -
ディスクリプタアーティファクトの
versionは、対応するQuarkus Platform BOMのversionと一致している必要があります。
文字列としては次のようになります: <platform-bom-groupId>:<platform-bom-artifactId>-quarkus-platform-descriptor:<platform-version>:json:<platform-version>
例えば、Quarkus BOM io.quarkus:quarkus-bom::pom:1.2.3 の記述子の座標は io.quarkus:quarkus-bom-quarkus-platform-descriptor:1.2.3:json:1.2.3 となります。また、BOM org.acme:acme-bom::pom:555 で定義されたカスタムQuarkusプラットフォームの場合は、 org.acme:acme-bom-quarkus-platform-descriptor:555:json:555 となります。
プラットフォームのバージョンにマッチする分類子は、最初は混乱するように見えるかもしれません。しかし、これは記述子をプラットフォームの真の「フィンガープリント」に変えるものです。MavenとGradleの両方で、依存バージョン制約(または管理された依存関係)の効果的なセットは、現在のプロジェクトとその親(複数可)で個別に指定されたすべてのインポートされたBOMとバージョン制約をマージすることによって得られます。アーティファクト classifier は、依存関係IDの一部であり、 groupId:artifactId:classifier:type と表すことができます。つまり、プロジェクトが2つのBOM、例えば org.apple:apple-bom::pom:1.0 と org.orange:orange-bom::pom:1.0 をインポートし、これら2つのBOMがそれぞれ異なるバージョン io.quarkus:quarkus-bom::pom をインポートする場合、Quarkusツールはこの事実を検出し、安全な組み合わせではない 可能性がある ため、ユーザーに認識させることができます。もし、記述子アーティファクトにプラットフォームのバージョンを含む分類子が含まれていなければ、ツールは、同じプロジェクトに同じプラットフォームの異なるバージョンが混在している可能性を検出できないでしょう。
プラットフォームディスクリプタは通常、Mavenプラグインを使用して生成されます。
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-platform-descriptor-json-plugin</artifactId>
<version>${quarkus.version}</version> (1)
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>generate-extensions-json</goal> (2)
</goals>
</execution>
</executions>
<configuration>
<bomGroupId>${quarkus.platform.group-id}</bomGroupId> (3)
<bomArtifactId>${quarkus.platform.artifact-id}</bomArtifactId> (4)
<bomVersion>${quarkus.platform.version}</bomVersion> (5)
<overridesFile>${overridesfile}</overridesFile> (6)
<resolveDependencyManagement>true</resolveDependencyManagement> (7)
</configuration>
</plugin>
| 1 | quarkus-platform-descriptor-json-plugin のバージョン |
| 2 | generate-extensions-json は、プラットフォームディスクリプタを生成するゴールです。 |
| 3 | プラットフォーム BOM の groupId |
| 4 | プラットフォーム BOM の artifactId |
| 5 | プラットフォーム BOM の version |
| 6 | このパラメータはオプションで、プラットフォームディスクリプタが生成されるすべてのランタイムエクステンションアーティファクトに含まれるQuarkusエクステンションディスクリプタのメタデータの一部をオーバーライドすることができます。 |
| 7 | このパラメータもオプションで、デフォルトは false です。プラットフォームBOMが 生成されず 、フラット化 されていない 場合はtrueに設定しなければなりません。たとえば、 io.quarkus:quarkus-bom となります。 |
Quarkusプラットフォームプロパティ
Quarkusプラットフォームでは、幾つかの設定オプションに対して独自のデフォルト値を提供している場合があります。
Quarkusは、アプリケーション設定の接続に SmallRye Configを使用しています。Quarkusプラットフォームは、アプリケーションの application.properties によって支配されている構成ソースの階層の別の構成ソースとして使用することができます。
プ ラ ッ ト フ ォーム固有のデフ ォル ト を提供す る には、 プ ラ ッ ト フ ォームは、 座標が下記の命名規則に従っ てい る プ ロ パテ ィ アーテ ィ フ ァ ク ト に対 し て、 その BOM 内に依存バージ ョ ン制約を含める必要があ り ます。
-
プロパティアーティファクトの
groupIdは、対応するQuarkus Platform BOMのgroupIdと一致している必要があります。 -
プロパティアーティファクトの
artifactIdは、対応するQuarkus Platform BOMのartifactIdで、サフィックスが-quarkus-platform-propertiesである必要があります。 -
ディスクリプタアーティファクトの
classifierは空/NULL のままの必要があります。 -
ディスクリプタアーティファクトの
typeはpropertiesである必要があります。 -
ディスクリプタアーティファクトの
versionは、対応するQuarkus Platform BOMのversionと一致している必要があります。
プロパティ・アーティファクト自体は、 java.util.Properties クラスのインスタンスにロードされる伝統的な properties ファイルであることが期待されます。
At this point, platform properties are only allowed to provide the default values for a restricted set of configuration options. The property names in the platform properties file must be prefixed with the platform. suffix.
|
設定オプションをプラットフォーム固有のものにしたいエクステンションの開発者は、デフォルト値を platform. で始まるプロパティに設定しなければなりません。以下に例を示します。
package io.quarkus.deployment.pkg;
@ConfigRoot(phase = ConfigPhase.BUILD_TIME)
@ConfigMapping(prefix = "quarkus")
public interface NativeConfig {
/**
* The docker image to use to do the image build
*/
@WithDefault("${platform.quarkus.native.builder-image}")
String builderImage();
}
この場合、 quarkus.native.builder-image のデフォルト値はプラットフォームによって提供されます。もちろん、ユーザーは application.properties で quarkus.native.builder-image に希望の値を設定することができます。しかし、ユーザーがカスタマイズしていない場合は、デフォルト値はプラットフォームのプロパティから提供されます。上記の例のプラットフォームのプロパティファイルには、以下のようなものが含まれています(実際の値は例として提供されています)。
platform.quarkus.native.builder-image=quay.io/quarkus/ubi10-quarkus-mandrel-builder-image:jdk-21
|
The builder image used to build the native executable is based on UBI 10.
It means that the native executable produced by the container build will be based on UBI 10 as well.
So, if you plan to build a container, make sure that the base image in your For example to switch back to an UBI 9 builder image you can use:
You can see the available tags for UBI 8 here (UBI 8), for UBI 9 here (UBI 9), and for UBI 10 here (UBI 10)) |
また、プラットフォームプロパティのコンテンツとそのアーティファクトの座標を検証し、プラットフォームプロパティのアーティファクトがプラットフォームのBOMに存在するかどうかをチェックするMavenプラグインのゴールもあります。ここでは、プラグインの構成例を示します。
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-platform-descriptor-json-plugin</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>platform-properties</goal>
</goals>
</execution>
</executions>
</plugin>
Quarkusプラットフォームプロパティのマージ
アプリケーションが複数のQuarkusプラットフォームをインポートしており、それらのプラットフォームが独自のプラットフォームプロパティアーティファクトを含んでいる場合、それらのプラットフォームプロパティアーティファクトのコンテンツは、アプリケーションのビルドに使用される単一のプロパティセットを形成するためにマージされます。プロパティアーティファクトがマージされる順番は、アプリケーションの依存関係バージョン制約のリストに表示される順番に対応します(Maven用語では、アプリケーションの管理された依存関係の実際のリスト、すなわちフラット化された managedDependencies POMセクションに対応します)。
| The content of the properties artifacts found earlier will dominate over those found later among the application’s dependency constraints! |
つまり、あるプラットフォームがベースとなるプラットフォームで定義されている特定のプロパティ値をオーバーライドする必要がある場合は、ベースとなるプラットフォームをインポートする前に、そのプラットフォームのプロパティアーティファクトをBOMの managedDependencies セクションに含める必要があります。
例えば、 org.acme:acme-quarkus-bom プラットフォームは io.quarkus:quarkus-bom プラットフォームをベースにしています。 org.acme:acme-quarkus-bom プラットフォームが、 io.quarkus:quarkus-bom プラットフォームに含まれる io.quarkus:quarkus-bom-quarkus-platform-properties で定義された特定のプロパティを上書きする場合、 org.acme:acme-quarkus-bom は次のように構成されなければなりません。
<!-- skipped content -->
<artifactId>acme-quarkus-bom</artifactId>
<name>Acme - Quarkus - BOM</name>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<!-- Acme Quarkus platform properties -->
<dependency>
<groupId>org.acme</groupId>
<artifactId>acme-quarkus-bom-quarkus-platform-properties</artifactId>
<type>properties</type>
<version>${project.version}</version>
</dependency>
<!-- The base Quarkus BOM -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bom</artifactId>
<version>${quarkus.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- skipped content -->
こうすることで、 org.acme:acme-quarkus-bom のプラットフォーム・プロパティが io.quarkus:quarkus-bom のプラットフォーム・プロパティよりも先に現れる為、ビルドの際に優先されます。
Product attribution properties
A platform may declare that some of its members represent supported products (offerings). This information is consumed by CycloneDX SBOM generation to represent each product as a component and link the application artifacts that belong to it — see Product attribution in the CycloneDX guide.
The identity of a product is attached to an imported platform member BOM through platform properties whose names embed the member BOM’s coordinates:
platform.<member-bom-groupId>.<member-bom-artifactId>.cpe-
The CPE of the product represented by the platform member. When present, a product component is generated in the SBOM for this member. This property alone is sufficient to enable product attribution for the member.
platform.<member-bom-groupId>.<member-bom-artifactId>.cpe-artifacts-
An encoded map that, for each supported runtime extension artifact of the member, records the artifacts a consumer should attribute to the member’s CPE (the extension’s deployment artifact plus its resolved deployment dependency closure, aligned to the versions the platform ships). Keying the map by the runtime artifact lets a consumer look up the runtime artifacts it already has in its application model directly. The value is generated by the platform build tooling rather than written by hand, and is present only when the member declares both a CPE and an offering; when it is absent or empty, the product component is still emitted but without any attributed artifacts.
For example, for a platform member BOM org.acme:acme-camel-bom:
platform.org.acme.acme-camel-bom.cpe=cpe:2.3:a:acme:quarkus:3.40:*:*:*:*:*:*:*
platform.org.acme.acme-camel-bom.cpe-artifacts=<base64>
The generated product component can be further described with the following optional properties, using the same platform.<member-bom-groupId>.<member-bom-artifactId>. prefix: product-purl, product-name, product-version, product-description and product-type (defaults to framework). If product-purl is not set, the member BOM’s own pkg:maven PURL is used.
cpe-artifacts value format
The cpe-artifacts value is an encoding of a map that maps supported runtime extension artifacts to their corresponding original deployment dependencies.
The value is Base64 wrapping a DEFLATE-compressed UTF-8 rendering of the text format below:
-
Encode: build the text format → UTF-8 bytes →
java.util.zip.DeflaterwithBEST_COMPRESSION→java.util.Base64(standard alphabet, no line breaks). -
Decode:
Base64.getDecoder().decode(value)→java.util.zip.Inflater→ UTF-8 string → parse the text format.
The compressed stream is a standard zlib/DEFLATE stream; the compression level is not needed for decompression.
Coordinates recur heavily across entries (deployment closures overlap, and even distinct coordinates share groupIds, versions and artifactId prefixes). To remove this repetition, the text has two sections separated by a line containing exactly --: a dictionary of every distinct coordinate (grouped so shared parts are written once) followed by the entries, which reference the dictionary by index.
@org.apache.camel.quarkus ← groupId; the NEXT line is this group's common artifactId prefix
camel-quarkus- ← positional prefix line (empty when there is no shared prefix)
=3.33.0 ← version sub-block
core ← artifactId minus prefix → camel-quarkus-core (classifier "", type jar)
support:linux-x86_64 ← camel-quarkus-support, classifier linux-x86_64, type jar
=3.20.0 ← further versions reuse the same groupId + prefix
legacy ← camel-quarkus-legacy
@io.quarkus
quarkus-core ← prefix equals the only artifactId (singleton group)
=3.15.0
← empty artifact line ⇒ artifactId equals the prefix exactly
--
1a[0,3,5] ← entry: runtime-key index, then delta-encoded dependency indices
In the dictionary section each line is self-identifying by its first character. Maven groupIds, artifactIds and versions never start with @ or =, so the dispatch is unambiguous:
| Line | 意味 |
|---|---|
|
Starts a group. The very next line is this group’s common artifactId prefix. |
(line after |
The group’s common artifactId prefix — positional, always present, and empty when the group has no shared prefix. |
|
Starts a version sub-block within the current group. |
(anything else) |
An artifact line (see below). |
An artifact line is the artifactId with the group prefix stripped, optionally followed by :classifier and/or :type. Trailing default parts (empty classifier, jar type) are omitted. With prefix P, group G and version V:
| Artifact line | Reconstructed coordinate |
|---|---|
|
|
|
classifier |
|
empty classifier, type |
|
classifier |
(empty line) |
artifactId equals the prefix exactly ( |
|
artifactId equals the prefix, classifier |
Artifact lines take dictionary indices sequentially in the order they appear, starting at 0; the @, prefix and = lines consume no index.
In the entries section there is one line per runtime extension, of the form <key-index>[<Δ0>,<Δ1>,…,<Δn>]:
-
<key-index>is the base-36 dictionary index of the runtime extension artifact (absolute). -
Inside the brackets is the extension’s deployment-rooted dependency closure, as base-36 dictionary indices sorted ascending and delta-encoded: the first value is absolute, each subsequent value is the gap from the previous one (reconstruct by a running sum). An empty closure is
<key-index>[].
For example, 1a[0,3,5] means: key = dictionary entry Integer.parseInt("1a", 36); dependencies = dictionary entries at absolute indices 0, 0+3=3, 3+5=8.
The output is reproducible: the dictionary is sorted by (groupId, version, artifactId, classifier, type), entries are ordered by their runtime key’s dictionary index, and dependency indices are ascending. Byte-identical output across builds additionally assumes a consistent JDK/zlib, as with any DEFLATE-based artifact.