Wildfly部署Liferay后Camel路由热部署遇JAXB ClassNotFoundException问题
这个问题的核心是Liferay作为OSGi应用打乱了Wildfly的类加载上下文,导致Camel Spring模块无法正确解析JAXB的ContextFactory——哪怕你删除了Liferay自带的JAXB jar,OSGi的类加载隔离和依赖传递依然会干扰Wildfly原有模块的类路径解析。下面是具体的分析和修复步骤:
问题根源
Liferay 7.3.x基于OSGi构建,它会自带JAXB相关的bundle,这些bundle会在Wildfly的类加载体系中注册优先级更高的类加载器。而Wildfly Camel子系统(2.25.0版本)依赖的JAXB类,原本是从JDK8内置模块或Wildfly自带的JAXB模块加载,但Liferay的OSGi bundle会打乱这个依赖链,导致Camel模块找不到正确的com.sun.xml.bind.v2.ContextFactory实现。
修复方案
1. 调整Camel Spring模块的依赖配置
直接修改Wildfly中Camel Spring模块的module.xml,让它明确依赖JAXB的API和实现模块:
- 找到Wildfly安装目录下的
modules/system/layers/base/org/apache/camel/spring/main/module.xml - 在
<dependencies>节点中添加以下依赖:
保存后重启Wildfly,让模块依赖生效。<module name="javax.xml.bind.api" /> <module name="com.sun.xml.bind" /> <module name="javax.activation.api" /> <!-- JDK11需要额外添加这个 -->
2. 给Camel路由应用添加类加载隔离配置
在你的Camel路由应用中创建jboss-deployment-structure.xml文件(放在WEB-INF或META-INF下),强制应用使用Wildfly自带的JAXB模块,排除Liferay的干扰:
<jboss-deployment-structure> <deployment> <!-- 明确依赖Wildfly的JAXB模块 --> <dependencies> <module name="javax.xml.bind.api" export="true" /> <module name="com.sun.xml.bind" export="true" /> <module name="javax.activation.api" export="true" /> </dependencies> <!-- 排除Liferay可能引入的冲突模块 --> <exclusions> <module name="com.liferay.portal.kernel" /> <module name="com.liferay.osgi.util" /> <!-- 排除可能冲突的JAXB相关bundle --> <module name="com.sun.xml.bind.jaxb-impl" /> </exclusions> </deployment> </jboss-deployment-structure>
3. 调整Wildfly的全局类加载设置
如果上面的方法无效,检查Wildfly的standalone.xml(或domain.xml),确保JAXB相关模块没有被Liferay的配置覆盖:
- 找到
<subsystem xmlns="urn:jboss:domain:ee:4.0">节点 - 检查
<global-modules>,如果有Liferay添加的JAXB相关模块,移除它们,确保Wildfly自带的JAXB模块优先级更高:<global-modules> <!-- 只保留Wildfly原生的必要模块,移除Liferay添加的JAXB模块 --> <module name="javax.xml.bind.api" slot="main" /> </global-modules>
4. JDK11额外适配
由于JDK11完全移除了JAXB,你需要确保Wildfly的模块中包含完整的JAXB实现:
- 下载
jaxb-api-2.3.1.jar、jaxb-impl-2.3.1.jar、jaxb-core-2.3.0.jar、javax.activation-1.2.0.jar - 在Wildfly的
modules/system/layers/base/com/sun/xml/bind/main目录下(如果没有就创建),放入这些jar,然后更新module.xml:<module xmlns="urn:jboss:module:1.3" name="com.sun.xml.bind"> <resources> <resource-root path="jaxb-impl-2.3.1.jar"/> <resource-root path="jaxb-core-2.3.0.jar"/> </resources> <dependencies> <module name="javax.xml.bind.api"/> <module name="javax.activation.api"/> <module name="javax.xml.stream.api"/> <module name="javax.xml.ws.api" optional="true"/> <module name="org.jboss.logging"/> </dependencies> </module>
为什么删除Liferay的JAXB jar没用?
Liferay是OSGi应用,它的bundle会通过OSGi的依赖机制从其他bundle或Wildfly的全局模块中加载JAXB类——你删除Liferay自带的jar后,它可能会自动从Wildfly的全局模块中拉取,而这个全局模块的类加载上下文已经被Liferay的配置修改,所以Camel模块依然无法正确找到ContextFactory。
内容的提问来源于stack exchange,提问作者André Kreienbring

