如何在@FacesConverter中注入@EJB,@PersistenceContext,@Inject,@Autowired等? [英] How to inject @EJB, @PersistenceContext, @Inject, @Autowired, etc in @FacesConverter?

查看:206
本文介绍了如何在@FacesConverter中注入@EJB,@PersistenceContext,@Inject,@Autowired等?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何注入一个依赖关系,如 @EJB @PersistenceContext @Inject @AutoWired 等在 @FacesConverter 中?在我的具体情况下,我需要通过 @EJB 注入EJB:

  @FacesConverter 
public class MyConverter implements Converter {

@EJB
protected MyService myService;

@Override
public Object getAsObject(FacesContext context,UIComponent component,String value){
// myService.doSomething
}

}

但是,它没有被注入,它仍然是 null ,导致NPE。似乎 @PersistenceContext @Inject 也无效。



如何在转换器中注入服务依赖关系,以便我可以访问数据库?

解决方案


我可以使用 @EJB 将我的服务注入到一个 @FacesConverter


不,直到JSF 2.3发布。 JSF / CDI的人正在为JSF 2.3工作。另请参阅 JSF规范问题1349 和相关的JSF 2.3的新功能我的同事Arjan Tijms的文章。只有这样,依赖注入就像 @EJB @PersistenceContext @Inject 等将在 @FacesConverter 中工作,当您将 managed = true 属性添加到注释时。 p>

  @FacesConverter(value =yourConverter,managed = true)
public class YourConverter实现Converter {

@Inject
private YourService服务;
// ...
}







如果没有,那么正确的方法是什么?


在JSF 2.3之前,您有几个选项:


  1. 将其设为托管bean。您可以通过 @ManagedBean @Named @Component 。以下示例使其成为JSF托管的bean。

      @ManagedBean 
    @RequestScoped
    public class YourConverter实现Converter {

    @EJB
    private YourService服务;
    // ...
    }

    下面的例子使它成为CDI管理的bean。

      @Named 
    @RequestScoped
    public class YourConverter implements Converter {

    @Inject
    private YourService服务;
    // ...
    }

    将其引用为< h:inputXxx converter =#{yourConverter}> 而不是< h:inputXxx converter =yourConverter> ,或作为< f:转换器绑定=#{yourConverter}> 而不是< f:converter converterId =yourConverter > 。不要忘记删除 @FacesConverter 注释!



    缺点是您不能指定 forClass ,因此需要在必要时在视图中手动定义转换器。


  2. 将其注入常规托管bean。

      @ManagedBean 
    @RequestScoped
    public class YourBean {

    @EJB
    private YourService service;
    // ...
    }

    在转换器中,通过EL调用它。

      YourBean yourBean = context.getApplication()。evaluateExpressionGet(context,#{yourBean},YourBean 。类); 

    //然后例如
    YourEntity yourEntity = yourBean.getService()。findByStringId(value);
    //或
    YourEntity yourEntity = yourBean.findEntityByStringId(value);

    这样你可以继续使用 @FacesConverter


  3. 从JNDI手动抓取EJB。

      YourService yourService =(YourService)new InitialContext()。lookup(java:global / appName / YourService); 

    缺点是有一定的风险,这不是完全可移植的。另请参阅以编程方式从JSF托管的bean中注入EJB bean


  4. 安装 OmniFaces 。自1.6版以来,它在中透明地添加了对 @EJB (和 @Inject )的支持。 @FacesConverter ,无需进一步修改。另见展示。如果您恰好需要< f:selectItem(s)> 的转换器,则替代方案是使用其 SelectItemsConverter 它将根据选择的项目自动执行转换作业,而不需要任何数据库交互。

     < h: selectOneMenu ... converter =omnifaces.SelectItemsConverter> 

    另请参见转换器的转换错误设置值




另见:




  • 如何在@FacesValidator中使用@EJB注入@PersistenceContext,@Inject,@Autowired

  • 将CDI注入FacesConverter

  • 获取 @EJB @FacesValidator @FacesConverter


    • How can I inject a dependency like @EJB, @PersistenceContext, @Inject, @AutoWired, etc in a @FacesConverter? In my specific case I need to inject an EJB via @EJB:

      @FacesConverter
      public class MyConverter implements Converter {
      
        @EJB
        protected MyService myService;    
      
        @Override
        public Object getAsObject(FacesContext context, UIComponent component, String value) {
          // myService.doSomething
        }
      
      }
      

      However, it didn't get injected and it remains null, resulting in NPEs. It seems that @PersistenceContext and @Inject also doesn't work.

      How do I inject a service dependency in my converter so that I can access the DB?

      解决方案

      Can I use @EJB to inject my service into a @FacesConverter?

      No, not until JSF 2.3 is released. The JSF/CDI guys are working on that for JSF 2.3. See also JSF spec issue 1349 and this related "What's new in JSF 2.3?" article of my fellow Arjan Tijms. Only then dependency injection like @EJB, @PersistenceContext, @Inject, etc will work in a @FacesConverter when you explicitly add managed=true attribute to the annotation.

      @FacesConverter(value="yourConverter", managed=true)
      public class YourConverter implements Converter {
      
          @Inject
          private YourService service;
          // ...
      }
      


      If not, what's the "correct" way to do this?

      Before JSF 2.3, you have several options:

      1. Make it a managed bean instead. You can make it a JSF, CDI or Spring managed bean via @ManagedBean, @Named or @Component. The below example makes it a JSF managed bean.

        @ManagedBean
        @RequestScoped
        public class YourConverter implements Converter {
        
            @EJB
            private YourService service;
            // ...
        }
        

        And the below example makes it a CDI managed bean.

        @Named
        @RequestScoped
        public class YourConverter implements Converter {
        
            @Inject
            private YourService service;
            // ...
        }
        

        Reference it as <h:inputXxx converter="#{yourConverter}"> instead of <h:inputXxx converter="yourConverter">, or as <f:converter binding="#{yourConverter}"> instead of <f:converter converterId="yourConverter">. Don't forget to remove the @FacesConverter annotation!

        The disadvantage is that you cannot specify forClass and thus need to manually define the converter everywhere in the view where necessary.

      2. Inject it in a regular managed bean instead.

        @ManagedBean
        @RequestScoped
        public class YourBean {
        
            @EJB
            private YourService service;
            // ...
        }
        

        And in your converter, grab or call it via EL.

        YourBean yourBean = context.getApplication().evaluateExpressionGet(context, "#{yourBean}", YourBean.class);
        
        // Then e.g. either
        YourEntity yourEntity = yourBean.getService().findByStringId(value);
        // Or
        YourEntity yourEntity = yourBean.findEntityByStringId(value);
        

        This way you can keep using @FacesConverter.

      3. Manually grab the EJB from JNDI.

        YourService yourService = (YourService) new InitialContext().lookup("java:global/appName/YourService");
        

        The disadvantage is that there is a certain risk that this is not entirely portable. See also Inject EJB bean from JSF managed bean programmatically.

      4. Install OmniFaces. Since version 1.6, it transparently adds support for @EJB (and @Inject) in a @FacesConverter without any further modification. See also the showcase. If you happen to need the converter for <f:selectItem(s)>, then the alternative is to use its SelectItemsConverter which will automatically perform the conversion job based on select items without the need for any database interaction.

        <h:selectOneMenu ... converter="omnifaces.SelectItemsConverter">
        

        See also Conversion Error setting value for 'null Converter'.

      See also:

      这篇关于如何在@FacesConverter中注入@EJB,@PersistenceContext,@Inject,@Autowired等?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆