Tomcat运行JSF项目报Unable to find CDI BeanManager错误求助
根因分析
你遇到的Unable to find CDI BeanManager异常核心是两个问题:
- Tomcat是纯Servlet容器,本身不内置CDI实现,你当前的pom配置未引入CDI相关依赖和配置
- 你使用的
jakarta.faces.bean包下的@ManagedBean、@ViewScoped、@ManagedProperty注解已经从Jakarta Faces 2.3版本开始标记为废弃,新版本Faces默认优先依赖CDI做Bean管理,没有可用的CDI环境就会抛出该异常。
解决方案
推荐方案:迁移到CDI标准Bean管理
1. 新增CDI依赖
在pom.xml的dependencies节点中添加CDI官方实现Weld的相关依赖:
<!-- CDI API --> <dependency> <groupId>jakarta.enterprise</groupId> <artifactId>jakarta.enterprise.cdi-api</artifactId> <version>3.0.0</version> </dependency> <!-- Weld CDI实现,适配Tomcat和Jakarta EE 9 --> <dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet-core</artifactId> <version>4.0.3.Final</version> </dependency>
2. 新增CDI配置文件
在src/main/webapp/WEB-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_3_0.xsd" bean-discovery-mode="all"> </beans>
3. 替换废弃注解为CDI标准注解
所有Bean的注解按如下规则替换:
- 原
@ManagedBean替换为jakarta.inject.Named - 原
jakarta.faces.bean.ViewScoped替换为jakarta.faces.view.ViewScoped - 原
@SessionScoped替换为jakarta.enterprise.context.SessionScoped - 原
@ManagedProperty替换为jakarta.inject.Inject,如果需要指定Bean名称再加@Named("对应Bean名称")
修改后的示例Bean代码如下:
package Controller; import Entity.TodoItem; import Entity.TodoList; import jakarta.faces.view.ViewScoped; import jakarta.inject.Inject; import jakarta.inject.Named; import java.io.Serializable; @Named @ViewScoped public class AddOrEdit implements Serializable { @Inject TodoItem item; @Inject TodoList list; public String test(){ System.out.println("blub"); this.list.addItem(item); System.out.println(this.list.getItems().size()); return "index.xhtml?faces-redirect=true"; } public TodoItem getItem() { return item; } public void setItem(TodoItem item) { this.item = item; } public TodoList getList() { return list; } public void setList(TodoList list) { this.list = list; } }
注意会话作用域的TodoList Bean也需要同步替换为@Named + @SessionScoped注解。
4. 配置web.xml
在WEB-INF/web.xml中添加Weld启动监听器:
<listener> <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class> </listener>
同时确认你的内嵌Tomcat配置正确加载了WEB-INF下的所有配置文件。
临时备选方案:继续使用废弃的JSF托管Bean
如果暂时不想迁移到CDI,可以在WEB-INF/faces-config.xml中添加配置关闭CDI校验:
<application> <feature-descriptor> <feature-name>DISABLE_CDI</feature-name> <enabled>true</enabled> </feature-descriptor> </application>
该方案仅做临时兼容使用,不建议长期保留,旧的JSF托管Bean机制已经停止维护。
内容的提问来源于stack exchange,提问作者Daniel Pfeil
相关产品推荐
相关产品推荐

