You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用嵌入式Jetty 12部署Mojarra 4.0时出现CDI不可用异常

问题:嵌入式Jetty 12运行Jakarta Faces 4.0(Mojarra)时CDI不可用异常

环境与配置

我使用Java 21.0.7 + 嵌入式Jetty 12.0.22运行Jakarta Faces 4.0(Mojarra 4.0.11),因Jetty暂不满足Mojarra 4.1所需的Jakarta EE 11要求。采用无web.xml的编程式配置:

var servletContext = new ServletContextHandler("/", true, false);
var facesServlet = new ServletHolder("facesServlet", jakarta.faces.webapp.FacesServlet.class);
servletContext.addServlet(facesServlet, "*.xhtml");
servletContext.addEventListener(new com.sun.faces.config.ConfigureListener());
servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration", "true");

启动异常

启动时抛出如下异常:

Exception in thread "main" java.lang.IllegalStateException: CDI is not available
at com.sun.faces.util.Util.getCdiBeanManager(Util.java:1526)
at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:126)
at org.eclipse.jetty.ee10.servlet.ServletContextHandler.callContextInitialized(ServletContextHandler.java:1591)
at org.eclipse.jetty.ee10.servlet.ServletContextHandler.contextInitialized(ServletContextHandler.java:500)
at org.eclipse.jetty.ee10.servlet.ServletHandler.initialize(ServletHandler.java:676)
at org.eclipse.jetty.ee10.servlet.ServletContextHandler.startContext(ServletContextHandler.java:1325)
at org.eclipse.jetty.ee10.servlet.ServletContextHandler.lambda$doStart$0(ServletContextHandler.java:1051)
at org.eclipse.jetty.server.handler.ContextHandler$ScopedContext.call(ContextHandler.java:1463)
at org.eclipse.jetty.ee10.servlet.ServletContextHandler.doStart(ServletContextHandler.java:1048)

已尝试的操作

  1. 类路径添加以下JAR:
    • jakarta.faces.4.0.11.jar
    • weld-servlet-shaded-4.0.3.Final.jar
    • jakarta.servlet.jsp.jstl-api-2.0.0.jar
  2. 使用Jetty EE10版本JAR(包含jetty-ee10-cdi-12.0.22.jar),确保使用jakarta.enterprise.cdi-api-4.0.1.jar而非3.0.1版本
  3. 在webapp资源文件夹添加空的beans.xml:
<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"
bean-discovery-mode="annotated"
version="4.0"></beans>

请问需要补充或修改哪些配置才能让Jakarta Faces 4.0在嵌入式Jetty 12上正常运行?


解决方案

1. 手动启用Jetty的CDI集成

嵌入式Jetty默认不会自动初始化CDI容器,需显式配置Jetty的CDI组件并集成Weld:

Server server = new Server(8080);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");

// 添加Jetty CDI核心组件
CdiDecorator cdiDecorator = new CdiDecorator();
context.addDecorator(cdiDecorator);
context.addEventListener(new CdiInitializer());

// 配置Weld初始化监听器
Weld weld = new Weld();
context.addEventListener(new WeldInitialListener(weld));
context.setInitParameter("org.jboss.weld.environment.servlet.javax.enterprise.inject.spi.BeanManager", "true");

2. 调整Mojarra的CDI相关配置

Mojarra 4.0要求CDI容器在自身初始化前就绪,需做以下调整:

  • 移除手动添加的ConfigureListener,让Weld自动扫描并初始化它(若项目无CDI注解类,将beans.xml的bean-discovery-mode改为all)
  • 添加Mojarra的CDI启用参数:
context.setInitParameter("com.sun.faces.cdi.enableCDI", "true");
context.setInitParameter("jakarta.enterprise.inject.spi.BeanManager", "java:comp/BeanManager");

3. 确保依赖无冲突

  • 彻底移除任何旧版Jakarta EE API JAR(如jakarta.enterprise.cdi-api 3.x)
  • 确认weld-servlet-shaded-4.0.3.Final.jar包含完整Weld运行时依赖,无需额外添加其他Weld模块

4. 完整配置示例

public static void main(String[] args) throws Exception {
    Server server = new Server(8080);

    ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
    context.setContextPath("/");
    context.setResourceBase("src/main/webapp"); // 设置webapp资源目录

    // 配置CDI
    CdiDecorator cdiDecorator = new CdiDecorator();
    context.addDecorator(cdiDecorator);
    context.addEventListener(new CdiInitializer());

    Weld weld = new Weld();
    context.addEventListener(new WeldInitialListener(weld));
    context.setInitParameter("org.jboss.weld.environment.servlet.javax.enterprise.inject.spi.BeanManager", "true");

    // 配置Faces Servlet
    ServletHolder facesServlet = new ServletHolder(FacesServlet.class);
    context.addServlet(facesServlet, "*.xhtml");

    // Mojarra核心配置
    context.setInitParameter("com.sun.faces.forceLoadConfiguration", "true");
    context.setInitParameter("com.sun.faces.cdi.enableCDI", "true");
    context.setInitParameter("jakarta.enterprise.inject.spi.BeanManager", "java:comp/BeanManager");

    server.setHandler(context);
    server.start();
    server.join();
}

关键说明

  • Jetty 12 EE10的CDI支持需显式添加CdiInitializer和CdiDecorator来启用容器级集成
  • WeldInitialListener必须优先于Mojarra的配置监听器执行,通过Jetty监听器加载顺序或自动扫描保证
  • 若项目无自定义CDI Bean,beans.xml的bean-discovery-mode设为all可确保Mojarra内部类被CDI容器识别

内容的提问来源于stack exchange,提问作者dannerfr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 20:05:54