Extension Capabilities
Quarkus 扩展可能会提供某些功能,并要求应用程序中的其他扩展提供某些功能才能正常运行。
Quarkus extensions may provide certain capabilities and require certain capabilities to be provided by other extensions in an application to function properly.
功能代表技术方面,例如,它可能是某个功能、合同或规范的实现。每个功能都有一个名称,该名称应遵循 Java 包命名约定,例如 io.quarkus.rest
。
A capability represents a technical aspect, for example, it could be an implementation of some functionality, a contract or a specification. Each capability has a name which should follow the Java package naming convention, e.g. io.quarkus.rest
.
在 Quarkus 扩展描述符中描述了功能承诺和要求,它们是运行时扩展 JAR 工件的 `META-INF/quarkus-extension.properties`条目。
Capability promises and requirements are described in Quarkus extension descriptors - META-INF/quarkus-extension.properties
entries of the runtime extension JAR artifacts.
应用程序中只允许任何给定功能的一个提供程序。如果检测到某个功能的提供程序多于一个,则应用程序构建将失败,并显示相应的错误消息。
Only a single provider of any given capability is allowed in an application. If more than one provider of a capability is detected, the application build will fail with the corresponding error message.
如果某个扩展需要特定功能,那么应用程序依赖项中必定有另一个扩展可以提供该功能,否则构建将失败并显示相应的错误消息。
If one extension requires a certain capability, there must be another one among the application dependencies that provides that capability, otherwise the build will fail with the corresponding error message.
在构建时,应用程序中找到的所有功能都将汇总到 io.quarkus.deployment.Capabilities
构建项的一个实例中,扩展构建步骤可以注入该实例以检查给定的功能是否可用。
At build time all the capabilities found in the application will be aggregated in an instance of the io.quarkus.deployment.Capabilities
build item that extension build steps can inject to check whether a given capability is available or not.
Declaring capabilities
用于生成扩展描述符的 quarkus-extension-maven-plugin:extension-descriptor
Maven 目标和 extensionDescriptor
Gradle 任务允许通过以下方式配置提供的和必需的功能:
The quarkus-extension-maven-plugin:extension-descriptor
Maven goal and the extensionDescriptor
Gradle task, that generate extension descriptors, allow configuring provided and required capabilities in the following way:
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-maven-plugin</artifactId>
<configuration>
<capabilities>
<provides>io.quarkus.hibernate.orm</provides> 1
<requires>io.quarkus.agroal</requires> 2
</capabilities>
</configuration>
</plugin>
1 | the extension provides the io.quarkus.hibernate.orm capability (multiple provides elements are allowed) |
2 | the extension requires the io.quarkus.agroal capability to be provided to function properly (multiple requires elements are allowed) |
quarkusExtension {
capabilities {
provides 'io.quarkus.rest' 1
requires 'io.quarkus.resteasy' 2
}
}
1 | the extension provides the io.quarkus.hibernate.orm capability (multiple provides elements are allowed) |
2 | the extension requires the io.quarkus.agroal capability to be provided to function properly (multiple requires elements are allowed) |
Gradle 扩展插件仍处于试验阶段,未来可能会发生变化。 |
The Gradle extension plugin is still experimental and may change in the future. |
quarkusExtension {
capabilities {
provides("io.quarkus.rest") 1
requires("io.quarkus.resteasy") 2
}
}
1 | the extension provides the io.quarkus.hibernate.orm capability (multiple provides elements are allowed) |
2 | the extension requires the io.quarkus.agroal capability to be provided to function properly (multiple requires elements are allowed) |
Gradle 扩展插件仍处于试验阶段,未来可能会发生变化。 |
The Gradle extension plugin is still experimental and may change in the future. |
Conditional capability promises and requirements
仅当满足某个条件时才能提供或要求某个功能,例如,某个配置选项已启用或基于其他某些条件。以下是如何配置条件功能承诺:
A capability may be provided or required only if a certain condition is satisfied, for example, if a certain configuration option is enabled or based on some other condition. Here is how a conditional capability promise can be configured:
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-maven-plugin</artifactId>
<configuration>
<capabilities>
<providesIf> 1
<positive>io.quarkus.container.image.openshift.deployment.OpenshiftBuild</positive> 2
<name>io.quarkus.container.image.openshift</name> 3
</providesIf>
</capabilities>
</configuration>
</plugin>
1 | declaration of a conditional capability |
2 | condition that must be resolved to true by a class implementing java.util.function.BooleanSupplier |
3 | provided capability name |
|
|
还支持相应的 requiresIf
元素。
The corresponding requiresIf
element is also supported.
quarkusExtension {
capabilities {
provides 'io.quarkus.container.image.openshift' onlyIf ['io.quarkus.container.image.openshift.deployment.OpenshiftBuild'] 1
}
}
1 | condition that must be resolved to true by a class implementing java.util.function.BooleanSupplier |
也可以指定 |
It is possible to specify |
quarkusExtension {
capabilities {
provides("io.quarkus.container.image.openshift").onlyIf(["io.quarkus.container.image.openshift.deployment.OpenshiftBuild"]) 1
}
}
1 | condition that must be resolved to true by a class implementing java.util.function.BooleanSupplier |
也可以指定 |
It is possible to specify |
在这种情况下,应将 io.quarkus.container.image.openshift.deployment.OpenshiftBuild
包含在扩展部署依赖项之一中并实现 java.util.function.BooleanSupplier
。在构建时,Quarkus 引导程序将创建一个该类的实例,并且仅在 getAsBoolean()
方法返回真时才注册 io.quarkus.container.image.openshift
功能。
In this case, io.quarkus.container.image.openshift.deployment.OpenshiftBuild
should be included in one of the extension deployment dependencies and implement java.util.function.BooleanSupplier
. At build time, the Quarkus bootstrap will create an instance of it and register io.quarkus.container.image.openshift
capability only if its getAsBoolean()
method returns true.
OpenshiftBuild
的实现可能如下所示:
An implementation of the OpenshiftBuild
could look like this:
import java.util.function.BooleanSupplier;
import io.quarkus.container.image.deployment.ContainerImageConfig;
public class OpenshiftBuild implements BooleanSupplier {
private ContainerImageConfig containerImageConfig;
OpenshiftBuild(ContainerImageConfig containerImageConfig) {
this.containerImageConfig = containerImageConfig;
}
@Override
public boolean getAsBoolean() {
return containerImageConfig.builder.map(b -> b.equals(OpenshiftProcessor.OPENSHIFT)).orElse(true);
}
}
CapabilityBuildItem
每个提供的功能都将在构建时用 io.quarkus.deployment.builditem.CapabilityBuildItem
的实例表示。从理论上讲,扩展构建步骤可以直接生成 `CapabilityBuildItem',绕过扩展描述符中的相应声明。但是,除非有非常充分的理由不声明描述符中的功能,否则应避免这种提供功能的方法。
Each provided capability will be represented with an instance of io.quarkus.deployment.builditem.CapabilityBuildItem
at build time. Theoretically, `CapabilityBuildItem’s could be produced by extension build steps directly, bypassing the corresponding declaration in the extension descriptors. However, this way of providing capabilities should be avoided, unless there is a very good reason not to declare a capability in the descriptor.
来自扩展构建步骤的功能对于 Quarkus 开发工具不可用。因此,在项目创建期间分析扩展兼容性或将新扩展添加到项目时,无法考虑此类功能。
Capabilities produced from extension build steps aren’t available for the Quarkus dev tools. As a consequences, such capabilities can not be taken into account when analyzing extension compatibility during project creation or when adding new extensions to a project.
Querying capabilities
在构建期间,应用程序中找到的所有功能都将汇总到 io.quarkus.deployment.Capabilities
构建项的实例中,扩展构建步骤可以注入该实例以检查某个功能是否存在。例如
All the capabilities found in an application will be aggregated during the build in an instance of io.quarkus.deployment.Capabilities
build item, which can be injected by extension build steps to check whether a certain capability is present or not. E.g.
@BuildStep
HealthBuildItem addHealthCheck(Capabilities capabilities, DataSourcesBuildTimeConfig dataSourcesBuildTimeConfig) {
if (capabilities.isPresent(Capability.SMALLRYE_HEALTH)) {
return new HealthBuildItem("io.quarkus.agroal.runtime.health.DataSourceHealthCheck",
dataSourcesBuildTimeConfig.healthEnabled);
} else {
return null;
}
}
Capability prefixes
像功能名称一样,功能前缀是一个点分隔的字符串,它由第一个功能名称元素或从第一个功能名称元素开始的点分隔功能名称元素序列组成。例如,对于功能 io.quarkus.resteasy.json.jackson
,将注册以下前缀:
Like a capability name, a capability prefix is a dot-separated string that is composed of either the first capability name element or a dot-separated sequence of the capability name elements starting from the first one. E.g. for capability io.quarkus.resteasy.json.jackson
the following prefixes will be registered:
-
io
-
io.quarkus
-
io.quarkus.resteasy
-
io.quarkus.resteasy.json
Capabilities.isCapabilityWithPrefixPresent(prefix)
可以用来检查是否存在带有给定前缀的功能。
Capabilities.isCapabilityWithPrefixPresent(prefix)
could be used to check whether a capability with a given prefix is present.
鉴于应用程序中只允许一个给定功能的提供者,功能前缀允许表达不同但某些相关的功能中特定的通用方面。例如,可能有一些扩展提供了以下功能:
Given that only a single provider of a given capability is allowed in an application, capability prefixes allow expressing a certain common aspect among different but somewhat related capabilities. E.g. there could be extensions providing the following capabilities:
-
io.quarkus.resteasy.json.jackson
-
io.quarkus.resteasy.json.jackson.client
-
io.quarkus.resteasy.json.jsonb
-
io.quarkus.resteasy.json.jsonb.client
在应用程序中包含任何一个扩展将启用 RESTEasy JSON 序列化器。如果构建步骤需要检查是否已在应用程序中启用了 RESTEasy JSON 序列化器,而不是检查是否存在这些功能中的任何一个,它可以简单地检查是否存在带有前缀 io.quarkus.resteasy.json
的扩展。
Including any one of those extensions in an application will enable the RESTEasy JSON serializer. In case a build step needs to check whether the RESTEasy JSON serializer is already enabled in an application, instead of checking whether any of those capabilities is present, it could simply check whether an extension with prefix io.quarkus.resteasy.json
is present.