EAR项目中@FacesConverter无法注入EJB问题求助
EAR项目中@FacesConverter/@FacesValidator的@EJB注入及@PostConstruct失效问题解决方案
针对你遇到的EAR项目里@FacesConverter、@FacesValidator无法注入@EJB且@PostConstruct不生效的问题,以下是实际可落地的排查和解决步骤:
1. 修正CDI bean发现配置
EAR环境下,EJB模块的META-INF/beans.xml默认可能采用bean-discovery-mode="annotated"模式,这种模式下只有带有CDI原生注解(如@Named、@Singleton)的类才会被CDI容器管理。而@FacesConverter(managed=true)仅告知JSF将组件交给CDI,但不会触发CDI的bean发现逻辑。
解决方法:
- 要么修改EJB模块的
META-INF/beans.xml,将发现模式改为all:
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd" bean-discovery-mode="all"> </beans>
- 要么在
@FacesConverter/@FacesValidator类上额外添加@Named注解,明确标记为CDI管理的bean:
@Named @FacesConverter(managed = true, value = "demoConverter") public class DemoConverter implements Converter<DemoEntity>, Serializable { @EJB DemoRemote bean; int i; @PostConstruct public void init() {i=42;} // 实现Converter接口方法 }
2. 确保EAR模块依赖正确
WEB模块需要能正确访问EJB模块的类,且CDI上下文能跨模块扫描:
- 检查EAR的
application.xml,确保WEB模块和EJB模块都被正确声明,且存在依赖关系:
<application xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="8" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/application_8.xsd"> <module> <ejb>your-ejb-module.jar</ejb> </module> <module> <web> <web-uri>your-web-module.war</web-uri> <context-root>/your-app</context-root> </web> </module> </application>
- 或者在WEB模块的
MANIFEST.MF中添加对EJB模块的依赖:
Dependencies: your-ejb-module.jar
3. 调整类加载器配置
EAR环境下的类加载层次可能导致WEB模块无法访问EJB模块的CDI上下文:
- Payara:在EAR的部署描述符(或Payara管理控制台)中开启
delegate-first类加载模式,让WEB模块优先从父类加载器(EJB模块类加载器)获取类。 - WildFly:修改
jboss-deployment-structure.xml,确保WEB模块依赖EJB模块的类加载器:
<jboss-deployment-structure> <deployment> <dependencies> <module name="deployment.your-ear-name.your-ejb-module.jar" export="true"/> </dependencies> </deployment> </jboss-deployment-structure>
4. 替代方案:使用CDI生产者方法
如果以上方法无效,可以通过CDI生产者手动创建Converter/Validator实例并注入依赖:
- 移除原Converter类上的
@FacesConverter和@EJB注解,添加setter方法:
public class DemoConverter implements Converter<DemoEntity>, Serializable { private DemoRemote bean; int i; public void setBean(DemoRemote bean) { this.bean = bean; } public void init() {i=42;} // 实现Converter接口方法 }
- 创建CDI生产者类:
@Named public class ConverterProducer { @EJB private DemoRemote bean; @Produces @FacesConverter(value = "demoConverter") public Converter<DemoEntity> createDemoConverter() { DemoConverter converter = new DemoConverter(); converter.setBean(bean); converter.init(); // 手动执行原@PostConstruct逻辑 return converter; } }
5. 验证CDI日志
调整CDI相关日志级别,查看容器是否正确发现并实例化了Converter/Validator:
- Payara:开启
javax.enterprise.inject和javax.enterprise.context的DEBUG级别日志,检查是否有Converter类的实例化记录。 - WildFly:开启
org.jboss.weld的DEBUG级别日志,排查CDI bean的扫描和实例化过程。
内容的提问来源于stack exchange,提问作者Thomas P
相关产品推荐
相关产品推荐

