如何在@FacesConverter中注入@ EJB,@ PersistenceContext,@ Inject,@ Autowired等?

Rob*_*ume 28 jsf dependency-injection ejb converter

我怎么可以注入的依赖一样@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
  }

}
Run Code Online (Sandbox Code Playgroud)

然而,它没有被注射并且仍然存在null,导致NPE.看来,@PersistenceContext@Inject也不起作用.

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

Bal*_*usC 53

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

不,直到JSF 2.3发布.JSF/CDI的人正在研究JSF 2.3.另请参阅JSF规范问题1349以及此相关的"JSF 2.3中有哪些新内容?" 我的同事Arjan Tijms的文章.只有这样,依赖注入一样@EJB,@PersistenceContext,@Inject,等会在工作@FacesConverter时明确添加managed=true属性的注释.

@FacesConverter(value="yourConverter", managed=true)
public class YourConverter implements Converter {

    @Inject
    private YourService service;
    // ...
}
Run Code Online (Sandbox Code Playgroud)

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

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

  1. 改为使其成为托管bean.你可以把它JSF,CDI或Spring通过托管Bean @ManagedBean,@Named或者@Component.下面的示例使它成为JSF托管bean.

    @ManagedBean
    @RequestScoped
    public class YourConverter implements Converter {
    
        @EJB
        private YourService service;
        // ...
    }
    
    Run Code Online (Sandbox Code Playgroud)

    以下示例使其成为CDI托管bean.

    @Named
    @RequestScoped
    public class YourConverter implements Converter {
    
        @Inject
        private YourService service;
        // ...
    }
    
    Run Code Online (Sandbox Code Playgroud)

    引用它<h:inputXxx converter="#{yourConverter}">代替<h:inputXxx converter="yourConverter"><f:converter binding="#{yourConverter}">代替<f:converter converterId="yourConverter">.别忘了删除@FacesConverter注释!

    缺点是您无法指定forClass,因此需要在视图中的任何位置手动定义转换器.

  2. 将它注入常规托管bean中.

    @ManagedBean
    @RequestScoped
    public class YourBean {
    
        @EJB
        private YourService service;
        // ...
    }
    
    Run Code Online (Sandbox Code Playgroud)

    在转换器中,通过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);
    
    Run Code Online (Sandbox Code Playgroud)

    这样你就可以继续使用了@FacesConverter.

  3. 从JNDI手动获取EJB.

    YourService yourService = (YourService) new InitialContext().lookup("java:global/appName/YourService");
    
    Run Code Online (Sandbox Code Playgroud)

    缺点是存在一定的风险,即这不是完全便携的.另请参见以编程方式从JSF托管bean中注入EJB bean.

  4. 安装OmniFaces.从版本1.6开始,它在没有任何进一步修改的情况下透明地增加对@EJB(和@Inject)的支持@FacesConverter.另见展示.如果您碰巧需要转换器<f:selectItem(s)>,那么替代方法是使用它SelectItemsConverter,它将根据选择项自动执行转换作业,而无需任何数据库交互.

    <h:selectOneMenu ... converter="omnifaces.SelectItemsConverter">
    
    Run Code Online (Sandbox Code Playgroud)

    另请参见"null Converter"的"转换错误"设置值.

也可以看看:


归档时间:

查看次数:

13792 次

最近记录:

8 年,6 月 前