用途
本技能用于解决 SAP BTP 从 Neo 迁移到 Cloud Foundry(CF)过程中出现的第三方库兼容性问题。迁移目标环境为 Java 25、Jakarta EE 10 与 HANA Cloud,许多第三方库会因以下原因失效:
- Java 25 模块系统:JDK 移除了 javax.xml.bind、javax.xml.ws 等 javax.* 模块。
- javax → jakarta 命名空间变更:针对 javax.servlet、javax.ws.rs 等编译的库无法与 Jakarta EE 10 链接。
- 数据库变更:模式迁移工具可能无法识别 HANA Cloud。
- DI 框架冲突:平台变更后,监听器顺序、JNDI 假设与初始化顺序被破坏。
本技能会扫描项目依赖,识别已知兼容性问题并应用针对性修复。
注:jakarta-java25-migration 技能负责核心的 javax→jakarta 迁移与 Java 25 语言升级;本技能处理核心迁移未覆盖的第三方库专属问题。
适用检测条件
满足以下任一模式即适用:
- pom.xml 中出现:liquibase-core、flyway-core、guice、guice-servlet、weld-servlet-core、poi-ooxml、itextpdf、ehcache、hazelcast、quartz、retrofit。
- Java 源码中出现 DI 框架导入(com.google.inject.、GuiceServletContextListener)、Liquibase 编程式用法(liquibase.Liquibase、LiquibaseServletListener)、CDI 注解(javax.enterprise.context.、jakarta.enterprise.context.*)。
- web.xml 中出现 Liquibase 监听器或 Guice 过滤器/监听器配置。
前置条件
调用本技能前,必须确保已调用:
- jakarta-java25-migration —— Java 25 与 Jakarta EE 10 迁移必须先行完成(必需)。
- sdk-replacement —— SAP Cloud SDK 设置必须先行完成(必需)。
转换步骤
步骤 1:模式迁移工具(条件性)
仅当检测到模式迁移工具时应用。
1a:Liquibase —— 升级到 4.x 以支持 Java 25 + HANA Cloud
Liquibase 3.x 在 CF 上存在两个关键问题:
- JAXB 依赖:3.x 内部使用 javax.xml.bind 解析 XML changelog,Java 25 移除了该模块,导致 NoClassDefFoundError: javax/xml/bind/annotation/XmlElement。
- 未知数据库 HDB:3.x 无法识别 HANA Cloud 数据库标识,回退到 UnsupportedDatabase。
修复:升级到 4.x 并添加官方 HANA 扩展(org.liquibase.ext:liquibase-hanadb),同时移除旧的 com.github.lbitonti:liquibase-hana(与 4.x 不兼容)。示例版本为 liquibase-core 4.30.0、liquibase-hanadb 4.30.0、liquibase-slf4j 5.1.0(应在迁移时查阅 Maven Central 最新 4.x 版本)。
1b:Flyway —— 为 Jakarta EE 10 + HANA Cloud 升级
Flyway 9.x+ 原生支持 Jakarta EE 与 HANA Cloud;Flyway 10.x 需要 Java 17+。若版本低于 9.0,升级到 10.x(示例 10.20.1),并添加 flyway-database-saphana 以获得 HANA 支持。
步骤 2:DI 框架集成(条件性)
仅当检测到 DI 框架时应用(Google Guice、CDI/Weld、HK2)。
2a:模式迁移工具的监听器顺序
当应用同时使用 DI 框架与模式迁移工具时,web.xml 中的监听器顺序至关重要。LiquibaseServletListener 会自行进行 JNDI 查找 DataSource,这在 DataSource 由 DI 框架提供时会失败。正确顺序为:DI 框架监听器 → 模式迁移监听器 → 应用监听器。解决方案是用自定义 ServletContextListener 替换内置监听器,从 DI 容器获取 DataSource(资料提供了 CFLiquibaseRunner 模板,需按 DI 框架调整 getDataSourceFromDI() 方法)。
2b:Tomcat 上 Jersey + CDI(Weld)—— Bean 发现缺失
当使用 jersey-cdi2-se 与 Weld 在 Tomcat(非 TomEE)上运行时,Weld SE 只扫描 META-INF/beans.xml,不识别 WEB-INF/beans.xml,导致所有 @Inject 报 WELD-001408。修复:在 src/main/resources/META-INF/ 添加 beans.xml(bean-discovery-mode="all"),WAR 应同时包含 WEB-INF/beans.xml 与 WEB-INF/classes/META-INF/beans.xml。
2c:Tomcat 上 Jersey + CDI —— HttpServletRequest 歧义
修复 2b 后可能出现 WELD-001409:HttpServletRequest 歧义依赖。原因是使用 @Inject 而非 @Context 注入 HttpServletRequest。将 @Inject 改为 @Context 可解决该歧义,但会引发运行时失败(见 2e)。仅变更 HttpServletRequest 注入,其他 CDI Bean 保持 @Inject。
2d:Tomcat 上 Jersey + CDI —— Configuration 歧义
修复 2c 后可能出现 Configuration 歧义依赖(WELD-001409)。修复:为 JAX-RS Application 子类添加 @jakarta.enterprise.inject.Vetoed,使其不被 CDI 发现。
2e:Tomcat 上 Jersey + CDI —— WELD-000710 无法注入 Servlet 类型
修复 2c 与 2d 后,运行时会出现 WELD-000710:Cannot inject HttpServletRequest outside of a Servlet request(资料在此处截断)。
限制
- 上述 2b、2c、2d 问题不影响基于 TomEE 的应用(TomEE 自带 OpenWebBeans,不使用 jersey-cdi2-se)。
- 资料未提供 2e 的完整解决方案,相关内容暂未提供。
- 版本号与具体修复需在迁移时结合实际情况确认。