Skip to content

Commit 5560de4

Browse files
authored
Merge pull request #53140 from dmlloyd/modular
Extension-based modularity
2 parents 9371911 + c194c85 commit 5560de4

62 files changed

Lines changed: 5558 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/dependabot.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ updates:
6363
- dependency-name: io.smallrye.beanbag:*
6464
- dependency-name: io.smallrye.common:*
6565
- dependency-name: io.smallrye.config:*
66+
- dependency-name: io.smallrye.modules:*
6667
- dependency-name: io.smallrye.reactive:*
6768
# RX Java 2
6869
- dependency-name: io.reactivex.rxjava2:rxjava

bom/application/pom.xml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
<smallrye-common.version>2.18.1</smallrye-common.version>
4949
<smallrye-config.version>3.17.2</smallrye-config.version>
5050
<smallrye-health.version>4.3.0</smallrye-health.version>
51+
<smallrye-modules.version>1.0.beta1</smallrye-modules.version>
5152
<smallrye-open-api.version>4.3.3</smallrye-open-api.version>
5253
<smallrye-graphql.version>2.18.1</smallrye-graphql.version>
5354
<smallrye-fault-tolerance.version>6.11.1</smallrye-fault-tolerance.version>
@@ -1753,6 +1754,41 @@
17531754
<artifactId>quarkus-jdbc-oracle-deployment</artifactId>
17541755
<version>${project.version}</version>
17551756
</dependency>
1757+
<dependency>
1758+
<groupId>io.quarkus</groupId>
1759+
<artifactId>quarkus-modular</artifactId>
1760+
<version>${project.version}</version>
1761+
</dependency>
1762+
<dependency>
1763+
<groupId>io.quarkus</groupId>
1764+
<artifactId>quarkus-modular-deployment</artifactId>
1765+
<version>${project.version}</version>
1766+
</dependency>
1767+
<dependency>
1768+
<groupId>io.quarkus</groupId>
1769+
<artifactId>quarkus-modular-spi</artifactId>
1770+
<version>${project.version}</version>
1771+
</dependency>
1772+
<dependency>
1773+
<groupId>io.quarkus</groupId>
1774+
<artifactId>quarkus-jlink</artifactId>
1775+
<version>${project.version}</version>
1776+
</dependency>
1777+
<dependency>
1778+
<groupId>io.quarkus</groupId>
1779+
<artifactId>quarkus-jlink-deployment</artifactId>
1780+
<version>${project.version}</version>
1781+
</dependency>
1782+
<dependency>
1783+
<groupId>io.quarkus</groupId>
1784+
<artifactId>quarkus-jlink-launcher</artifactId>
1785+
<version>${project.version}</version>
1786+
</dependency>
1787+
<dependency>
1788+
<groupId>io.quarkus</groupId>
1789+
<artifactId>quarkus-jlink-spi</artifactId>
1790+
<version>${project.version}</version>
1791+
</dependency>
17561792
<dependency>
17571793
<groupId>io.quarkus</groupId>
17581794
<artifactId>quarkus-jms-spi-deployment</artifactId>
@@ -4275,6 +4311,11 @@
42754311
<artifactId>smallrye-health-provided-checks</artifactId>
42764312
<version>${smallrye-health.version}</version>
42774313
</dependency>
4314+
<dependency>
4315+
<groupId>io.smallrye.modules</groupId>
4316+
<artifactId>smallrye-modules</artifactId>
4317+
<version>${smallrye-modules.version}</version>
4318+
</dependency>
42784319
<dependency>
42794320
<groupId>io.smallrye</groupId>
42804321
<artifactId>smallrye-open-api-core</artifactId>

devtools/bom-descriptor-json/pom.xml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,6 +1311,19 @@
13111311
</exclusion>
13121312
</exclusions>
13131313
</dependency>
1314+
<dependency>
1315+
<groupId>io.quarkus</groupId>
1316+
<artifactId>quarkus-jlink</artifactId>
1317+
<version>${project.version}</version>
1318+
<type>pom</type>
1319+
<scope>test</scope>
1320+
<exclusions>
1321+
<exclusion>
1322+
<groupId>*</groupId>
1323+
<artifactId>*</artifactId>
1324+
</exclusion>
1325+
</exclusions>
1326+
</dependency>
13141327
<dependency>
13151328
<groupId>io.quarkus</groupId>
13161329
<artifactId>quarkus-jsonb</artifactId>
@@ -1714,6 +1727,19 @@
17141727
</exclusion>
17151728
</exclusions>
17161729
</dependency>
1730+
<dependency>
1731+
<groupId>io.quarkus</groupId>
1732+
<artifactId>quarkus-modular</artifactId>
1733+
<version>${project.version}</version>
1734+
<type>pom</type>
1735+
<scope>test</scope>
1736+
<exclusions>
1737+
<exclusion>
1738+
<groupId>*</groupId>
1739+
<artifactId>*</artifactId>
1740+
</exclusion>
1741+
</exclusions>
1742+
</dependency>
17171743
<dependency>
17181744
<groupId>io.quarkus</groupId>
17191745
<artifactId>quarkus-mongodb-client</artifactId>

devtools/bom-descriptor-json/src/main/resources/catalog-overrides.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@
139139
"name": "Alternative languages",
140140
"id": "alt-languages",
141141
"description": "Support for other JVM based languages"
142+
},
143+
{
144+
"name": "Packaging",
145+
"id": "packaging",
146+
"description": "Support for packaging a built application in various ways"
142147
}
143148
],
144149
"metadata":{

docs/pom.xml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,6 +1275,19 @@
12751275
</exclusion>
12761276
</exclusions>
12771277
</dependency>
1278+
<dependency>
1279+
<groupId>io.quarkus</groupId>
1280+
<artifactId>quarkus-jlink-deployment</artifactId>
1281+
<version>${project.version}</version>
1282+
<type>pom</type>
1283+
<scope>test</scope>
1284+
<exclusions>
1285+
<exclusion>
1286+
<groupId>*</groupId>
1287+
<artifactId>*</artifactId>
1288+
</exclusion>
1289+
</exclusions>
1290+
</dependency>
12781291
<dependency>
12791292
<groupId>io.quarkus</groupId>
12801293
<artifactId>quarkus-jsonb-deployment</artifactId>
@@ -1678,6 +1691,19 @@
16781691
</exclusion>
16791692
</exclusions>
16801693
</dependency>
1694+
<dependency>
1695+
<groupId>io.quarkus</groupId>
1696+
<artifactId>quarkus-modular-deployment</artifactId>
1697+
<version>${project.version}</version>
1698+
<type>pom</type>
1699+
<scope>test</scope>
1700+
<exclusions>
1701+
<exclusion>
1702+
<groupId>*</groupId>
1703+
<artifactId>*</artifactId>
1704+
</exclusion>
1705+
</exclusions>
1706+
</dependency>
16811707
<dependency>
16821708
<groupId>io.quarkus</groupId>
16831709
<artifactId>quarkus-mongodb-client-deployment</artifactId>

docs/src/main/asciidoc/jlink.adoc

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
////
2+
This guide is maintained in the main Quarkus repository
3+
and pull requests should be submitted there:
4+
https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
5+
////
6+
[id="jlink"]
7+
= JLink packaging
8+
include::_attributes.adoc[]
9+
:diataxis-type: reference
10+
:categories: packaging
11+
:extension-status: experimental
12+
:summary: The jlink extension produces a custom Java runtime image containing only the modules needed to run the application.
13+
:topics: jlink,packaging,modules,modularity
14+
:extensions: io.quarkus:quarkus-jlink
15+
16+
The `jlink` extension produces a custom Java runtime image for a Quarkus application.
17+
The image contains only the JDK modules and application modules that are needed to run the application, resulting in a smaller, faster, and more self-contained distribution.
18+
This extension depends on the xref:modularity.adoc[Quarkus modularity extension] to compute the application's module graph.
19+
20+
include::{includes}/extension-status.adoc[]
21+
22+
== Prerequisites
23+
24+
The `jlink` extension requires Java 25 or later.
25+
Earlier JDK versions have compatibility issues with the `jlink` tool that prevent reliable image generation.
26+
27+
== Usage
28+
29+
Add the `quarkus-jlink` extension to your project.
30+
When the extension is present, a `jlink` image is produced automatically as part of the normal Quarkus build.
31+
JAR packaging is disabled when `jlink` is active.
32+
33+
:add-extension-extensions: quarkus-jlink
34+
include::{includes}/devtools/extension-add.adoc[]
35+
36+
After adding the extension, build the project normally:
37+
38+
include::{includes}/devtools/build.adoc[]
39+
40+
The `jlink` image is written to the output directory (by default, `target/jlink-output/image`).
41+
42+
== Running the image
43+
44+
To run the application, execute the launcher script in the image's `bin` directory:
45+
46+
[source,bash]
47+
----
48+
./target/jlink-output/image/bin/<launcher-name>
49+
----
50+
51+
The launcher name defaults to the value of `quarkus.package.output-name`.
52+
53+
== Image layout
54+
55+
The output directory has the standard `jlink` image structure.
56+
The `bin/` directory contains the launcher script.
57+
The `lib/` directory contains the JDK runtime modules.
58+
Application modules that are not on the boot module path are placed in `lib/quarkus/` and are loaded dynamically on demand after startup by `smallrye-modules`.
59+
See the xref:modularity.adoc[modularity guide] for an explanation of boot modules and dynamic modules.
60+
61+
== Configuration reference
62+
63+
`quarkus.jlink.enabled`::
64+
Whether jlink image generation is enabled.
65+
Type: `boolean`.
66+
Default: `true`.
67+
68+
`quarkus.jlink.min-heap-size`::
69+
The minimum heap size to configure in the image's JVM options.
70+
If not set, no minimum heap size is specified.
71+
Type: `MemorySize` (optional).
72+
73+
`quarkus.jlink.max-heap-size`::
74+
The maximum heap size to configure in the image's JVM options.
75+
If not set, no maximum heap size is specified.
76+
Type: `MemorySize` (optional).
77+
78+
`quarkus.jlink.image-path`::
79+
The path of the image directory within the output directory.
80+
Type: `Path`.
81+
Default: `image`.
82+
83+
`quarkus.jlink.launcher-name`::
84+
The name of the launcher script generated in the image's `bin/` directory.
85+
Type: `String`.
86+
Default: derived from `quarkus.package.output-name`.
87+
88+
`quarkus.jlink.output-directory`::
89+
The base output directory for the jlink build.
90+
Type: `Path`.
91+
Default: derived from `quarkus.package.output-directory`.
92+
93+
`quarkus.jlink.staging-directory`::
94+
The path of the staging directory used during the jlink build process, relative to the output directory.
95+
Type: `Path`.
96+
Default: `staging`.
97+
98+
== CDS support
99+
100+
Support for Class Data Sharing (CDS) and AOT precompilation within jlink images is planned for a future release.
101+
102+
CDS currently only applies to modules on the boot module path.
103+
Dynamic modules loaded by `smallrye-modules` are not eligible for CDS precompilation at this time.
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
////
2+
This guide is maintained in the main Quarkus repository
3+
and pull requests should be submitted there:
4+
https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
5+
////
6+
[id="modularity-reference"]
7+
= Modularity SPI reference
8+
include::_attributes.adoc[]
9+
:diataxis-type: reference
10+
:categories: architecture
11+
:extension-status: experimental
12+
:summary: Reference for the build items that Quarkus extensions use to participate in Quarkus modularity.
13+
:topics: modularity,jpms,modules,extensions,spi
14+
15+
This document describes the build items that extension authors use to integrate with the xref:modularity.adoc[Quarkus modularity] system.
16+
Extensions can declare boot modules, add inter-module dependencies, and consume the completed module model.
17+
18+
include::{includes}/extension-status.adoc[]
19+
20+
== `BootModulePathBuildItem`
21+
22+
`BootModulePathBuildItem` is a `MultiBuildItem` produced by extensions.
23+
It declares that a named module must be placed on the boot module path.
24+
25+
An extension should produce this item when it provides a module that must be in the JDK's boot module layer.
26+
This is necessary when the module is required before the dynamic module loader (`smallrye-modules`) starts, or when the module must participate in the boot class loading chain.
27+
28+
The constructor takes a single `String` parameter: the module name.
29+
30+
[source,java]
31+
----
32+
@BuildStep
33+
BootModulePathBuildItem myBootModule() {
34+
return new BootModulePathBuildItem("com.example.my.boot.module");
35+
}
36+
----
37+
38+
The modularity extension computes the transitive closure of all declared boot modules.
39+
If a boot module depends on other modules (via `LINKED` dependencies), those modules are also included in the boot set automatically.
40+
Automatic modules are excluded from the boot set because they cannot be linked by `jlink`.
41+
42+
== `AddDependencyBuildItem`
43+
44+
`AddDependencyBuildItem` is a `MultiBuildItem` produced by extensions.
45+
It adds a dependency between two modules at build time.
46+
47+
An extension should produce this item when it needs to wire a module dependency that is not expressed in the Maven POM or in the module's `module-info.class` descriptor.
48+
This is common when Quarkus extensions generate code that references types from another module, or when service loading relationships must be declared explicitly.
49+
50+
The constructor takes three parameters: the source module name (`String`), the target module name (`String`), and a set of dependency modifiers (`Modifiers<Dependency.Modifier>`).
51+
52+
[source,java]
53+
----
54+
@BuildStep
55+
AddDependencyBuildItem extraDependency() {
56+
return new AddDependencyBuildItem(
57+
"com.example.source.module",
58+
"com.example.target.module",
59+
Dependency.Modifier.set(Dependency.Modifier.LINKED, Dependency.Modifier.READ));
60+
}
61+
----
62+
63+
When multiple items declare the same source/target pair, their modifier sets are merged.
64+
65+
== `ApplicationModuleInfoBuildItem`
66+
67+
`ApplicationModuleInfoBuildItem` is a `SimpleBuildItem` produced by the modularity extension.
68+
It contains the completed `AppModuleModel`, which includes the module descriptor for every module in the application, the set of boot modules, and the set of JDK modules in use.
69+
70+
This item is consumed by downstream packaging extensions such as the xref:jlink.adoc[jlink extension].
71+
Extension authors generally do not need to consume this item unless they are implementing a custom packaging step.
72+
73+
== Dependency modifiers
74+
75+
The `Dependency.Modifier` enum (from `io.smallrye.modules.desc`) defines the following values.
76+
These are used with `AddDependencyBuildItem` to control how the dependency is wired.
77+
78+
`LINKED`::
79+
The dependency is linked for class loading.
80+
Classes from the target module are visible to the source module's class loader.
81+
82+
`READ`::
83+
The dependency is readable from the source module.
84+
Exported packages from the target module are accessible to the source module.
85+
86+
`SERVICES`::
87+
Service implementations in the target module are available to the source module via `ServiceLoader`.
88+
89+
`OPTIONAL`::
90+
The dependency is optional.
91+
If the target module is not present at link time, the dependency is silently ignored rather than causing a failure.
92+
93+
`TRANSITIVE`::
94+
The dependency is transitive.
95+
Any module that depends on the source module also implicitly depends on the target module.
96+
97+
`SYNTHETIC`::
98+
The dependency was added by a framework rather than declared in the original module descriptor. _Note:_ because modifier sets are merged when a dependency is declared in two places, this modifier would take precedence over a non-synthetic dependency, which is a minor detail but possibly undesirable. Thus, this modifier may change to be "non-synthetic" or something along those lines in the final version, so that an explicit dependency will never be marked as being synthetic.
99+
100+
`MANDATED`::
101+
The dependency is mandated by specification (for example, the implicit dependency on `java.base`).
102+
103+
== Related core build items
104+
105+
The `quarkus-core-deployment` module provides two additional build items that affect the module graph.
106+
These are documented separately but are noted here for completeness.
107+
108+
`ModuleOpenBuildItem` declares that one module should open specified packages to another module (equivalent to the `--add-opens` JVM flag).
109+
`ModuleEnableNativeAccessBuildItem` declares that a module requires native access (equivalent to the `--enable-native-access` JVM flag).

0 commit comments

Comments
 (0)