【问题标题】:CDI Injection into a FacesConverter将 CDI 注入 FacesConverter
【发布时间】:2023-04-07 18:32:02
【问题描述】:

从几次搜索来看,这似乎是一个已经存在一段时间的问题。我编写了一个 FacesConverter,如下所示。 Category 对象是一个 JPA 实体,CategoryControl 是获取它的 DAO。

@FacesConverter(value = "categoryConverter")
public class CategoryConverter implements Converter {

@Inject private CategoryControl cc;

public CategoryConverter() { }

@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
    if (cc != null) return cc.getByName(value);
    System.out.println("CategoryConverter().getAsObject(): no injection!");
    return null;
}

@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
    if (!(value instanceof Category)) return null;
    return ((Category) value).getName();
}

}

您现在可能已经猜到了,我从来没有注射过。我从this page 得到了这个解决方法,看起来像这样。:

Workaround for this problem: create this method in your localeController: 

public Converter getConverter() 
{ 
    return   FacesContext.getCurrentInstance().getApplication().createConverter("localeConverter"); 
} 

and use converter="#{localeController.converter}" in your h:selectOneMenu.

但是我也无法完成这项工作。我的支持 bean 可以创建并返回一个转换器,但它没有将对象注入其中。

我正在使用 MyFaces CODI 1.0.1。使用当前的 GlassFish/Weld 容器。在我重新编码不使用转换器之前,任何人都可以提出解决方案吗?

【问题讨论】:

    标签: jsf-2 cdi myfaces


    【解决方案1】:

    替换

    @FacesConverter(value = "categoryConverter")
    

    通过

    @Named
    

    并使用

    <h:inputSomething converter="#{categoryConverter}" />
    

    <f:converter binding="#{categoryConverter}" />
    

    而不是

    <h:inputSomething converter="categoryConverter" />
    

    <f:converter converterId="categoryConverter" />
    

    顺便说一句,@EJB@FacesConverter 中也存在类似的问题。然而,它提供了一种由 JNDI 手动抓取的方法。另见Communication in JSF 2.0 - Getting an EJB in @FacesConverter and @FacesValidator。这样您就可以使用@FacesConverter(forClass=Category.class),而无需每次都手动定义它。不幸的是,我不知道如何为 CDI bean 实现这一点。


    更新:如果您碰巧使用 JSF 实用程序库 OmniFaces,因为 1.6 版添加了对在 @FacesConverter 类中使用 @Inject@EJB 的透明支持,无需任何额外配置或注释。另见the CDI @FacesConverter showcase example

    【讨论】:

    • 好吧,我会被诅咒的。我实现了一个解决方法,基本上调用应用程序来评估转换器内部的表达式,但我认为这更优雅。所以我还有一个问题@BalusC——你是不是该写一本关于 JSF 的书了?
    • 好吧,你不必写太多——只需编辑你已经写的所有东西。说真的,我已经想到了一本书的大纲,如果您对合作感兴趣,请告诉我。
    • 那么你能相信吗?在最初发布几乎整整一年后,我在一个新项目中再次遇到这个问题,进行谷歌搜索,并附上我自己的帖子!我不记得上面写过,但计算机从不撒谎。
    • @BalusC 与您的许多其他答案一样,人们至今仍链接到这个答案,例如stackoverflow.com/questions/18183176/…。您可能会考虑在 1.6 中编辑以包含 Omnifaces 提供的支持:)
    • 来自 [OmniFaces] (code.google.com/p/omnifaces) 项目的 SelectItemsConverter 拯救了我的一天。谢谢@BalusC!
    【解决方案2】:

    @Inject 注解仅适用于 CDI 托管实例。如果您想在非 CDI 托管实例(如 JSF Validator 或 JSF Converter)中使用 CDI 功能,您可以针对 CDI API 进行编程。

    这仅适用于至少 Java EE 7 + CDI 1.1 服务器。

    @FacesValidator("userNameValidator")
    public class UserNameValidator implements Validator {
    
        private UserService userService;
    
        public UserNameValidator(){
            this.userService = CDI.current().select(UserService.class).get();
        }
    
        @Override
        public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
         ....
        }
    }
    

    https://docs.oracle.com/javaee/7/api/javax/enterprise/inject/spi/CDI.html

    由于 Java EE 中的所有 AnnotationHell,人们忘记了如何编码。

    【讨论】:

      【解决方案3】:

      只需将@Advanced 的 CODI 用于您的 @FacesConverter,请参阅 Wiki

      只要转换器或验证器使用@Advanced 注释,就可以使用@Inject。

      【讨论】:

        【解决方案4】:

        根据 BalusC 的回答 here,我决定添加仅包含 @FacesConverter 和 Converter 的 JSF(requestscoped)托管 bean 以在我的应用程序中解决此问题,因为我正在从 JSF 托管 bean 迁移到 CDI 托管 bean。

        我针对@FacesConverter 尝试了CODI @Advanced,但它根本没有注入bean。

        【讨论】:

          猜你喜欢
          • 2020-03-08
          • 2012-10-20
          • 2012-04-21
          • 1970-01-01
          • 2015-04-15
          • 2012-10-21
          • 2016-08-02
          • 1970-01-01
          相关资源
          最近更新 更多