JSF与CDI注解使用困惑求助:为何CDI注解无法正常工作?
Hey there! As a fellow JSF developer who’s been through this exact confusion early on, let’s work through your problems and get you sorted out.
First, let’s clarify the core issue: your environment likely isn’t properly configured to support CDI, which is why switching to CDI annotations breaks your demo app. JSF 2.1 does support CDI, but it requires a few key pieces to be in place—let’s break down each problem and fix them step by step.
Why Your CDI Annotations Aren’t Working
1. @Named Bean Not Recognized by EL (PropertyNotFoundException)
When you replace @javax.faces.bean.ManagedBean with @javax.inject.Named and EL can’t find your bean, it’s almost always because CDI isn’t enabled in your project. Here’s what to check:
- Missing
beans.xmlfile: CDI requires abeans.xmldescriptor (even an empty one) to activate the container. Create this file in yourWEB-INFfolder with the following content:<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"> </beans> - CDI Implementation Dependency: If you’re using a lightweight container like Tomcat (instead of a full Java EE server like WildFly or GlassFish), you need to add a CDI implementation (like Weld) to your project. For Maven, add this dependency:
<dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet</artifactId> <version>2.4.8.Final</version> <!-- Compatible with JSF 2.1/Java EE 6 --> </dependency> - Package Scanning Issues: Make sure your bean class isn’t in the default (unnamed) package—CDI containers won’t scan classes in the default package. Move your bean to a named package like
com.yourcompany.demo.beans.
2. CDI @SessionScoped Not Maintaining State
This is directly related to the CDI configuration issue above. If CDI isn’t enabled, the javax.enterprise.context.SessionScoped annotation is effectively ignored—your bean is treated as a plain POJO, so a new instance is created on every request.
Double-check:
- You’re importing the correct CDI scope annotation:
javax.enterprise.context.SessionScoped(not the JSF versionjavax.faces.bean.SessionScoped). - The CDI container is active (verify via the
beans.xmland dependency checks above). Once CDI is working, the session scope will behave as expected.
Why CDI is Recommended Over JSF Annotations
The advice to prioritize CDI annotations is spot-on for a few reasons:
- Standardization: CDI is the official Java EE (and Jakarta EE) dependency injection standard, whereas JSF’s
@ManagedBeanand scopes are JSF-specific. - Feature Richness: CDI supports advanced features like interceptors, decorators, events, and producer methods that JSF’s managed beans don’t.
- Future Compatibility: JSF 2.3 officially deprecated
@ManagedBean, and newer Jakarta Faces versions have removed it entirely. Using CDI ensures your code stays compatible with modern Java web stacks.
Example Working CDI Bean
Here’s a corrected version of a session-scoped CDI bean to reference:
package com.yourcompany.demo.beans; import javax.inject.Named; import javax.enterprise.context.SessionScoped; import java.io.Serializable; @Named @SessionScoped public class UserBean implements Serializable { private String username; // Getters and setters public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } }
In your facelet, you can reference it via EL like this:
<h:inputText value="#{userBean.username}" />
内容的提问来源于stack exchange,提问作者hagrawal7777

