副标题:手动维护 Feature 版本太痛苦?这一招教你实现 server.xml 的”自动驾驶”。
⚠️ 常见错误提示(报错码速查)
如果你在启动 Open Liberty 时遇到以下错误,说明你掉入了”版本依赖地狱”:
CWWKF0033E: The singleton features mpHealth-3.0 and mpHealth-4.0 are colliding.
CWWKF0032E: An incompatible feature combination was detected: jaxrs-3.0 with jaxrs-4.0.
如果你正在面对这些报错,本文将带你用 Versionless 方式彻底根治! 🛠️
Read more: 告别 CWWKF0033E 冲突:Open Liberty Versionless 详解,终结 Jakarta EE 依赖地狱引言:Java 开发者的”依赖地狱”
如果你曾经开发过 Java EE / Jakarta EE 应用,你一定遇到过这样的场景:
场景 1:版本冲突
<!-- 你配置了这些 features -->
<feature>servlet-5.0</feature>
<feature>jpa-3.0</feature>
<feature>jaxrs-3.0</feature>
<feature>mpHealth-3.0</feature>
然后启动服务器,看到这样的错误:
CWWKF0033E: The singleton features mpHealth-3.0 and mpHealth-4.0 are coliding.
CWWKF0032E: An incompatible fature combination was detected:
jaxrs-3.0 with jaxrs-4.0.
为什么会冲突?
因为 jpa-3.0 依赖 mpHealth-3.0,而 jaxrs-3.1 依赖 mpHealth-4.0。你需要手动查找所有依赖关系,然后选择合适的版本组合。
场景 2:升级噩梦
你正在使用 Jakarta EE 9.1,现在想升级到 10.0。你需要:
- 手动修改 所有 feature 版本号:
servlet-5.0→servlet-6.0jpa-3.0→jpa-3.1jaxrs-3.0→jaxrs-3.1- … (可能有 20+ features)
- 祈祷没有版本冲突
- 如果冲突了,回到场景 1
开发体验极差! 😫
Open Liberty 的解决方案:Versionless Features
核心理念:开发者只需要关心 “我需要什么功能”,而不是 “这个功能用什么版本”。
传统方式 vs Versionless 方式
❌ 传统方式(指定版本)
<featureManager>
<feature>servlet-6.0</feature>
<feature>jpa-3.1</feature>
<feature>jaxrs-3.1</feature>
<feature>jsonp-2.1</feature>
<feature>jsonb-3.0</feature>
<feature>mpHealth-5.0</feature>
<feature>mpMetrics-6.0</feature>
</featureManager>
问题:
- ❌ 需要记住每个 feature 的版本号
- ❌ 需要手动解决版本冲突
- ❌ 升级平台时,需要修改 每一个 feature 版本
✅ Versionless 方式(不指定版本)
<featureManager>
<!-- 声明平台 -->
<platform>jakartaee-10.0</platform>
<platform>microProfile-7.0</platform>
<!-- 只声明功能,不声明版本 -->
<feature>servlet</feature>
<feature>jpa</feature>
<feature>jaxrs</feature>
<feature>jsonp</feature>
<feature>jsonb</feature>
<feature>mpHealth</feature>
<feature>mpMetrics</feature>
</featureManager>
优势:
- ✅ 不需要记住版本号 – Open Liberty 自动选择合适的版本
- ✅ 自动解决版本冲突 – 平台保证了所有 feature 版本兼容
- ✅ 升级简单 – 只需要修改
<platform>版本号,所有 features 自动升级
工作原理:Platform是核心
什么是平台(Platform)?
平台是一个 预测试、预验证的 feature 版本组合,保证所有 features 之间 100% 兼容。
Open Liberty 支持 3 类平台:
| 平台类型 | 版本示例 | 包含的 Features |
|---|---|---|
| Jakarta EE | 8.0, 9.1, 10.0 | servlet, jpa, jaxrs, jsonp, jsonb, cdi, beans, … |
| Java EE | 6.0, 7.0, 8.0 | (旧版 Jakarta EE) |
| MicroProfile | 4.0, 4.1, 5.0, 6.0, 7.0 | mpConfig, mpHealth, mpMetrics, mpOpenAPI, … |
版本解析规则
当你声明:
<platform>jakartaee-10.0</platform>
<feature>servlet</feature>
<feature>jpa</feature>
Open Liberty 会:
- 查找 Jakarta EE 10.0 平台定义
- 解析
servlet→servlet-6.0(Jakarta EE 10.0 中的版本) - 解析
jpa→jpa-3.1(Jakarta EE 10.0 中的版本) - 验证 所有 features 版本兼容
- 启动 服务器
你完全不需要关心版本号! 🎉
实战演示:从”依赖地狱”到”一键配置”
场景:构建一个 RESTful Web 应用(Jakarta EE + MicroProfile)
❌ 传统方式(痛苦)
Step 1: 查找依赖关系
你需要手动查找:
- Jakarta EE 10.0 包含哪些 feature 版本?
- MicroProfile 7.0 包含哪些 feature 版本?
- 它们之间是否有冲突?
你花了 2 小时阅读文档… ⏳
Step 2: 配置 server.xml
<featureManager>
<!-- Jakarta EE 10.0 features -->
<feature>servlet-6.0</feature>
<feature>jpa-3.1</feature>
<feature>jaxrs-3.1</feature>
<feature>jsonp-2.1</feature>
<feature>jsonb-3.0</feature>
<feature>cdi-4.0</feature>
<feature>beans-5.0</feature>
<!-- MicroProfile 7.0 features -->
<feature>mpConfig-4.0</feature>
<feature>mpHealth-5.0</feature>
<feature>mpMetrics-6.0</feature>
<feature>mpOpenAPI-4.0</feature>
</featureManager>
Step 3: 启动服务器,遇到冲突
CWWKF0033E: The singleton features mpMetrics-5.0 and mpMetrics-6.0 are coliding.
CWWKF0032E: An incompatible fature combination was detected.
你又花了 1 小时调试… 🤬
Step 4: 升级到 Jakarta EE 11.0
你需要手动修改 每一个 feature 版本号:
<!-- 修改前 -->
<feature>servlet-6.0</feature>
<feature>jpa-3.1</feature>
...
<!-- 修改后(你花了 30 分钟,还改错了 2 个) -->
<feature>servlet-6.1</feature>
<feature>jpa-3.2</feature>
...
开发体验:😫😫😫
✅ Versionless 方式(愉悦)
Step 1: 声明平台
<featureManager>
<platform>jakartaee-10.0</platform>
<platform>microProfile-7.0</platform>
</featureManager>
耗时:30 秒 ⚡
Step 2: 添加需要的 features(不需要版本号)
<featureManager>
<platform>jakartaee-10.0</platform>
<platform>microProfile-7.0</platform>
<!-- 只声明功能,不声明版本 -->
<feature>servlet</feature>
<feature>jpa</feature>
<feature>jaxrs</feature>
<feature>jsonp</feature>
<feature>jsonb</feature>
<feature>mpConfig</feature>
<feature>mpHealth</feature>
<feature>mpMetrics</feature>
</featureManager>
耗时:1 分钟 ⚡
Step 3: 启动服务器
CWWKF0012I: The server installed the following features:
servlet-6.0, jpa-3.1, jaxrs-3.1, jsonp-2.1, jsonb-3.0,
cdi-4.0, beans-5.0, mpConfig-4.0, mpHealth-5.0, mpMetrics-6.0
CWWKF0011I: The defaultServer server is ready to run a smarter planet.
没有冲突! ✅
没有错误! ✅
你节省了 3+ 小时! 🎉
Step 4: 升级到 Jakarta EE 10.0
只需要修改 一行:
<!-- 修改前 -->
<platform>jakartaee-9.1</platform>
<!-- 修改后 -->
<platform>jakartaee-10.0</platform>
所有 features 自动升级! 🚀
三种使用方式
Open Liberty 提供 3 种方式 使用 versionless features。
方法 1:显式 platform 元素(推荐)⭐⭐⭐⭐⭐
<featureManager>
<platform>jakartaee-10.0</platform>
<platform>microProfile-7.0</platform>
<feature>servlet</feature>
<feature>jpa</feature>
<feature>mpHealth</feature>
</featureManager>
优势:
- ✅ 最明确(代码即文档)
- ✅ 版本控制友好(可以 diff)
- ✅ 推荐方式
方法 2:环境变量 PREFERRED_PLATFORM_VERSIONS
Step 1: 配置 server.env
PREFERRED_PLATFORM_VERSIONS=microProfile-7.0,jakartaee-10.0
Step 2: 在 server.xml 中使用 versionless features
<featureManager>
<feature>servlet</feature>
<feature>jpa</feature>
<feature>mpHealth</feature>
</featureManager>
⚠️ 注意:
- ❌ 如果只在 shell 中设置环境变量,打包服务器时会丢失
- ✅ 推荐在
server.env中设置(会包含在打包文件中)
方法 3:隐式平台声明(不推荐)
如果你启用了 只有一个平台包含的 versioned feature,Open Liberty 会自动推断平台。
<featureManager>
<!-- mpHealth-3.0 只在 MicroProfile 4.0 中存在 -->
<feature>mpHealth-3.0</feature>
<!-- 自动推断:使用 MicroProfile 4.0 平台 -->
<feature>mpMetrics</feature>
<feature>mpConfig</feature>
</featureManager>
⚠️ 不推荐理由:
- ❌ 隐式行为(代码不清晰)
- ❌ 如果 feature 在多个平台中存在,会失败
- ❌ 调试困难
平台参考:所有可用的 Versionless Features
MicroProfile 平台
参考: https://openliberty.io/docs/latest/reference/feature/platform/MicroProfile.html
| MicroProfile 版本 | 包含的 Versionless Features |
|---|---|
| 7.0 | mpConfig, mpHealth, mpMetrics, mpOpenAPI, mpRestClient, … |
| 6.0 | mpConfig, mpHealth, mpMetrics, mpOpenAPI, mpRestClient, … |
| 5.0 | mpConfig, mpHealth, mpMetrics, mpOpenAPI, mpRestClient, … |
Jakarta EE 平台
参考: https://openliberty.io/docs/latest/reference/feature/platform/JakartaEE.html
| Jakarta EE 版本 | 包含的 Versionless Features |
|---|---|
| 10.0 (Stable) | servlet, jpa, jaxrs, jsonp, jsonb, cdi, beans, … |
| 9.1 | servlet, jpa, jaxrs, jsonp, jsonb, cdi, beans, … |
Java EE 平台(旧版)
参考: https://openliberty.io/docs/latest/reference/feature/platform/JavaEE.html
| Java EE 版本 | 包含的 Versionless Features |
|---|---|
| 8.0 | servlet, jpa, jaxrs, jsonp, cdi, beans, … |
| 7.0 | servlet, jpa, jaxrs, jsonp, cdi, beans, … |
最佳实践
✅ 推荐做法
- 使用 Versionless Features – 永远不要再手动指定版本号
- 使用显式
platform元素 – 最明确,最易维护 - 在
server.xml中声明 platform – 版本控制友好 - 检查平台文档 – 确认 feature 是否在平台中
- 使用稳定的平台版本 – 例如 Jakarta EE 10.0
❌ 避免的做法
- 避免混合 versioned 和 versionless features – 选择一种方式
- 避免使用隐式平台声明 – 代码不清晰
- 避免在 shell 中设置
PREFERRED_PLATFORM_VERSIONS– 使用server.env - 避免假设所有 features 都有 versionless 版本 – 检查平台文档
- 避免使用过新的平台版本
配置示例
server.xml
<featureManager>
<!-- 平台声明 -->
<platform>microProfile-7.0</platform>
<platform>jakartaee-10.0</platform>
<!-- Versionless Features (自动解析) -->
<feature>servlet</feature>
<feature>jpa</feature>
<feature>jaxrs</feature>
<feature>jsonp</feature>
<feature>jsonb</feature>
<feature>beans</feature>
<feature>cdi</feature>
<!-- MicroProfile Versionless Features -->
<feature>mpConfig</feature>
<feature>mpHealth</feature>
<!-- Security Features (versioned - 不在平台中) -->
<feature>appSecurity-5.0</feature>
<feature>transportSecurity-1.0</feature>
</featureManager>
解析后的版本:
| Versionless Feature | 解析后版本 | 来源平台 |
|---|---|---|
servlet | servlet-6.0 | Jakarta EE 10.0 |
jpa | jpa-3.1 | Jakarta EE 10.0 |
jaxrs | jaxrs-3.1 | Jakarta EE 10.0 |
jsonp | jsonp-2.1 | Jakarta EE 10.0 |
jsonb | jsonb-3.0 | Jakarta EE 10.0 |
mpConfig | mpConfig-4.0 | MicroProfile 7.0 |
mpHealth | mpHealth-5.0 | MicroProfile 7.0 |
升级场景:从 Jakarta EE 10.0 到 11.0
传统方式: 需要修改 7 个 feature 版本号
Versionless 方式: 只需要修改 1 行
<!-- 修改前 -->
<platform>jakartaee-10.0</platform>
<!-- 修改后 -->
<platform>jakartaee-11.0</platform>
所有 features 自动升级! 🚀
常见问题(FAQ)
Q1: 所有 features 都支持 versionless 吗?
A: 不是。只有 包含在平台中的 features 才有 versionless 版本。
示例:
- ✅
servlet– 在 Jakarta EE 平台中 - ✅
mpHealth– 在 MicroProfile 平台中 - ❌
springBoot– 不在任何平台中,所以没有 versionless 版本
Q2: 我可以同时使用多个平台吗?
A: 可以!最多可以同时使用 2 个平台:
- 一个 MicroProfile 平台
- 一个 Jakarta EE 或 Java EE 平台
示例:
<featureManager>
<platform>microProfile-7.0</platform>
<platform>jakartaee-10.0</platform>
</featureManager>
Q3: Versionless features 会影响性能吗?
A: 不会。版本解析只在 服务器启动时 进行一次,运行时性能 零影响。
Q4: 我可以混合使用 versioned 和 versionless features 吗?
A: 可以,但 不推荐。建议选择一种方式,保持配置清晰。
示例(不推荐):
<featureManager>
<platform>jakartaee-10.0</platform>
<!-- Versionless (推荐) -->
<feature>servlet</feature>
<feature>jpa</feature>
<!-- Versioned (不推荐混合) -->
<feature>springBoot-3.0</feature>
</featureManager>
更好的方式:
<featureManager>
<platform>jakartaee-10.0</platform>
<!-- Versionless (平台中的 features) -->
<feature>servlet</feature>
<feature>jpa</feature>
<!-- Versioned (不在平台中的 features) -->
<feature>springBoot-3.0</feature>
</featureManager>
Q5: 如何查看 versionless feature 解析后的版本?
A: 查看 Liberty 日志:
CWWKF0012I: The server installed the following features:
servlet-6.0, jpa-3.1, jaxrs-3.1, ...
或者使用 featureManager 的 report-versions 目标:
mvn liberty:report-versions
结论:Versionless Features 改变了什么?
传统开发体验 😫
- 手动查找 feature 版本号 ⏳
- 手动解决版本冲突 🤬
- 升级平台时修改 N 个版本号 😫
- 维护成本高 💸
Versionless 开发体验 🚀
- 声明平台 – 30 秒 ⚡
- 添加 features(无版本号) – 1 分钟 ⚡
- 自动解决冲突 – 零耗时 ✅
- 升级只需要修改 1 行 – 10 秒 ⚡
- 维护成本低 💰