JPMS集成Weld CDI触发WELD-ENV-000033错误求助
解决JPMS环境下Weld抛出WELD-ENV-000033异常的思路
核心原因
WELD-ENV-000033异常本质是Weld在扫描Bean归档时发现重复的配置或类资源,在JPMS模块模式下,空的module-info.java会触发JVM的模块隔离机制,导致Weld的扫描逻辑与模块可见性规则冲突,而非单纯的beans.xml重复。
1. 给module-info.java添加必要的模块声明
空模块会让JVM将项目标记为模块化,但Weld无法自动访问模块内的类或依赖模块。至少需要补充以下配置:
module sandbox.jpms.cdi.weld { // 声明依赖Weld核心模块 requires weld.se.core; requires weld.api; requires jakarta.cdi; // 导出Bean所在包给Weld,允许其扫描和反射访问 exports com.example.sandbox to weld.se.core, weld.api; // 开放测试包给JUnit和Weld(若测试类在同一模块内) opens com.example.sandbox.test to junit.jupiter.api, weld.se.core; }
2. 统一beans.xml配置,避免跨模块扫描冲突
- 仅保留
src/main/resources/META-INF/beans.xml,删除测试目录下的同名文件,确保配置唯一:<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd" version="4.0" bean-discovery-mode="annotated"> </beans> - 检查Maven的
resources插件配置,禁止将测试目录的资源打包到主模块中。
3. 调整Weld初始化逻辑,指定模块扫描范围
在测试类中显式指定扫描目标模块,避免Weld自动扫描所有模块导致重复:
@BeforeEach void initWeld() { Weld weld = new Weld() .disableDiscovery() // 关闭自动扫描 .addModule(ModuleLayer.boot().findModule("sandbox.jpms.cdi.weld").get()) // 指定目标模块 .addPackages(true, ExampleBean.class.getPackage()); // 指定Bean所在包 container = weld.initialize(); }
4. 确保依赖版本的JPMS兼容性
- 使用Weld 5.x及以上版本(完全适配Jakarta EE 9+和JPMS),检查Maven依赖中Weld的jar包是否包含自身的
module-info.java。 - 后续启用JPA相关代码时,需同步添加
requires jakarta.persistence到模块声明中。
5. 给测试代码单独配置模块(可选)
若测试类与主代码需隔离,可在src/test/java下添加module-info.java,声明为测试模块:
open module sandbox.jpms.cdi.weld.test { requires sandbox.jpms.cdi.weld; requires weld.se.core; requires junit.jupiter.api; requires junit.jupiter.engine; }
open module允许测试框架和Weld通过反射访问测试类。
内容的提问来源于stack exchange,提问作者r-uu
相关产品推荐
相关产品推荐

