【问题标题】:CDI interface-based bean in JSFJSF 中基于 CDI 接口的 bean
【发布时间】:2012-04-13 16:16:30
【问题描述】:

我在 JSF 项目中使用 CDI 时遇到问题。我不能强制 CDI 将 interface-based bean 注入 JSF 文件。

@Named
public class ClassBasedNamedBean {
    public String getMessage() {
        return "Class-based Hello World!";
    }
}

@Named
public interface InterfaceBasedNamedBean {
    public String getMessage();
}

public class InterfaceBasedNamedBeanImpl implements InterfaceBasedNamedBean {
    @Override
    public String getMessage() {
        return "Interface-based Hello World!";
    }
}

我可以在 WebServlet 环境中使用这两个 bean:

@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
    @Inject
    private ClassBasedNamedBean classBasedNamedBean;

    @Inject
    private InterfaceBasedNamedBean interfaceBasedNamedBean;

    protected void doGet(...) ... {
        PrintWriter pw = response.getWriter();
        pw.println("classBasedNamedBean: " + classBasedNamedBean.getMessage());
        pw.println("interfaceBasedNamedBean: " + interfaceBasedNamedBean.getMessage());

        // Output:
        // classBasedNamedBean: Class-based Hello World!
        // interfaceBasedNamedBean: Interface-based Hello World!
    }
}

但是 interfaceBasedNamedBean 在 JSF 页面中不可用:

<p>ClassBasedNamedBean: #{classBasedNamedBean.message}</p>
<p>InterfaceBasedNamedBean: #{interfaceBasedNamedBean.message}</p>

Output:
<p>ClassBasedNamedBean: Class-based Hello World!</p>
<p>InterfaceBasedNamedBean: </p>

我该如何解决这个问题? JSF 是否需要对interfaceBasedNamedBean 进行一些显式配置?

【问题讨论】:

    标签: jsf jakarta-ee interface jsf-2 cdi


    【解决方案1】:

    我的最佳猜测:

    我认为规范中没有提到这一点,但我很确定@Named 不打算在接口上使用。

    毕竟,它只是类型和 EL 名称之间的匹配 - 似乎 EL 解析器在接口名称下找不到任何东西(具体)。

    所以,尝试注释实现,而不是接口 - 这应该可以。如果您需要灵活地使用同一 bean 类型的各种实现 - 将其注入控制器 bean 并使该 bean 可访问。

    【讨论】:

      【解决方案2】:

      您将javax.enterprise.inject.spi.BeanManager 设置为您的BeanManager?

      如果您将@Named("InterfaceBasedNamedBean") 添加到您的类定义并从接口中删除注释会发生什么?无论如何,您出于什么原因使用注释?与 spring 相比,CDI 不需要它们。

      您是否尝试过使用生产者方法?

      【讨论】:

      • @Named 需要从 JSF 页面中访问 bean ;-)
      • 如何为 JSF 设置正确的 BeanManager(我对 JSF 和 CDI 都很陌生,令人惊讶的是,谷歌在前 3 个结果中没有返回明确的答案 :])?我想我必须在web.xmlfaces-config.xml 中设置它。这似乎是最有可能的解决方案。 (JSF 实现:Mojarra,CDI 实现:焊接,AS:GlassFish)
      • 如果您在标准 JEE 6 环境中(如 Glassfish),请不要担心 BeanManager 配置,这一切都应该设置好。尝试将 @Named 移至实现,这可能是一种解决方法。如果这不能更好地工作,请通过控制器使 bean 可访问,直到我们找出问题的真正原因。
      【解决方案3】:

      例如,尝试使用 @RequestScoped 将范围添加到您的 bean。来自 Weld 文档:

      @Named 注释并不是使类成为 bean 的原因。 bean 档案中的大多数类已经被识别为 bean。 @Named 注释只是使从 EL 引用 bean 成为可能,最常见的是从 JSF 视图。

      【讨论】:

        【解决方案4】:

        CDI 将@Named 定义为基于字符串的限定符。限定符的目的是区分在注入点使用哪个实现。 @Named 的 javadoc 给出了一个例子:

        public class Car {
           @Inject @Named("driver") Seat driverSeat;
           @Inject @Named("passenger") Seat passengerSeat;
           ...
        }
        

        因此@Named 必须注释特定的实现。

        @Named 作为在 JSF 视图中使用 CDI bean 的一种方式可以被视为辅助功能。 @Named 不像看起来那样“@Inject for JSF”。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-07-14
          • 2015-04-15
          • 1970-01-01
          • 2013-08-20
          • 2016-08-02
          • 2012-07-23
          • 1970-01-01
          • 2014-07-17
          相关资源
          最近更新 更多