JBoss中jboss-deployment-structure.xml排除隐式模块无效求助
我们将应用从Java 11迁移到Java 17并部署在JBoss 8上后,部分单元测试失败。经调试发现,EAR包中自带的jakarta.el.api.jar被JBoss隐式引入的不同版本Jar覆盖。
JBoss自带的jakarta.el.api模块信息
<module xmlns="urn:jboss:module:1.9" name="jakarta.el.api"> <resources> <resource-root path="jboss-el-api_5.0_spec-4.0.1.Final-redhat-00001.jar"/> </resources> <dependencies> <module name="java.desktop"/> </dependencies> </module>
版本不符的验证信息
ModuleClassLoader for Module "jakarta.el.api" version 4.0.1.Final-redhat-00001 from local module loader @41294f8 (finder: local module finder @225129c (roots: /app/jboss/modules,/app/jboss/modules /system/layers/base))
我们需要让应用使用EAR包内的jakarta.el.api版本,已尝试在jboss-deployment-structure.xml的exclusions中添加该模块,但无效果,当前配置如下:
<?xml version="1.0" encoding="UTF-8"?> <jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.3"> <deployment> <exclusions> <module name="org.apache.logging.log4j.api" /> <module name="org.apache.commons.logging" /> <module name="org.slf4j" /> <module name="org.slf4j.impl" /> <module name="org.jboss.logging" /> <module name="jakarta.el.api" /> <module name="org.glassfish.expressly" /> </exclusions> <exclude-subsystems> <subsystem name="webservices" /> <subsystem name="jaxrs" /> </exclude-subsystems> </deployment> @SUB_DEPLOYMENTS@ </jboss-deployment-structure>
解决方案
1. 补全子部署的排除规则
配置中的@SUB_DEPLOYMENTS@说明EAR包含子部署(如WAR包),仅在<deployment>节点排除模块无法覆盖子部署。需要为每个子部署单独添加排除:
<sub-deployment name="your-web-app.war"> <exclusions> <module name="jakarta.el.api" /> <module name="org.glassfish.expressly" /> </exclusions> </sub-deployment>
2. 显式声明本地Jar并强制优先级
在jboss-deployment-structure.xml中,除了排除JBoss自带模块,还要显式将EAR内的Jar标记为资源,并设置优先加载:
<deployment> <!-- 保留原有排除规则 --> <exclusions> <module name="jakarta.el.api" /> <module name="org.glassfish.expressly" /> <!-- 其他排除项 --> </exclusions> <!-- 声明EAR内的jakarta.el.api为本地资源 --> <resources> <resource-root path="jakarta.el.api.jar" /> </resources> <!-- 强制依赖本地版本 --> <dependencies> <module name="jakarta.el.api" export="true" optional="false" /> </dependencies> </deployment>
3. 调整类加载顺序
添加模块选项强制优先加载本地资源:
<deployment> <exclusions> <module name="jakarta.el.api" /> </exclusions> <module-options> <option name="org.jboss.as.server.deployment.module.order" value="LOCAL" /> </module-options> </deployment>
4. 检查EAR打包结构
确保jakarta.el.api.jar放在EAR的lib目录下(作为共享依赖),而非子部署的WEB-INF/lib中,这样能被整个EAR的类加载器优先读取。
5. 修正单元测试依赖
如果单元测试在本地运行,需在测试依赖中排除JBoss提供的版本,仅使用EAR内的版本。以Maven为例:
<dependency> <groupId>jakarta.el</groupId> <artifactId>jakarta.el-api</artifactId> <version>你的目标版本</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.spec.javax.el</groupId> <artifactId>jboss-el-api_5.0_spec</artifactId> <scope>provided</scope> <exclusions> <exclusion> <groupId>*</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency>
内容的提问来源于stack exchange,提问作者Wesley Padilha

