简体   繁体   English

如何使用CDI将@Iternative与CDI一起注入EJB模块

[英]How to Inject @Alternative with CDI from WAR into EJB Module

I want to let CDI "pick up" an Alternative Class as Implementation of an Interface. 我想让CDI“选择”替代类作为接口的实现。

While everything is bundles in a EAR the Alternative Implementation will be in the war file and the rest (Class injecting the Interfaces, the Interface, "Default" Implementation of the Interfaces) will be in the ejb jar. 虽然EAR中的所有内容都是捆绑包,但是替代实现将在war文件中,其余的(类接口,接口,接口的“默认”实现)将在ejb jar中。

Here some code to illustrate it: 这里有一些代码来说明它:

EJB Module: EJB模块:

public interface I {}

public class C implements I {}

public class A {
  @Inject I var

  public void test() {
    System.out.println(var instanceof C); // I want to have here as Result: false
  }
}

WAR Module: WAR模块:

@Alternative
public class D implements I {}

Setting the beans.xml in the war file did not help.. 在war文件中设置beans.xml没有帮助..

With the structure that you are describing, there is no way to obtain the desired injection. 根据您描述的结构,无法获得所需的注射。

The EJB classloader will never be able to access the classes inside the WAR , hence the injection will never consider the alternative implementation. EJB类加载器永远不能访问WAR内的类,因此注入永远不会考虑替代实现。

A solution is possible if you are willing to alterate the EAR structure, placing the alternative (D) in a lib/jar , along with the appropriare beans.xml . 如果您愿意更改EAR结构,将替代(D)放在lib / jar中,以及appropriare beans.xml ,则可以使用解决方案。 The D class will become visible to your EJB and to your WAR, and the injection shoul proceed as desired. D类将对您的EJB和WAR可见,并且注入应根据需要进行。

EDIT 编辑

The solution you posted, which I descibe here, is almost working. 您发布的解决方案,我在这里所说的,几乎正在运行。

EAR
  - ejb-module-1.jar 
     - A.class (@Inject I)
     - I.class
     - C.class (@Stateless implements I)
     - META-INF/beans.xml
  - ejb-module-2.jar
     - D.class (@Alternative @Stateless implements I)
     - META-INF/beans.xml (<alternatives><class>D</class></alternative>)
  - app.war
     - calls A.test()
     - WEB-INF/beans.xml

The only catch is that you misplaced the beans.xml alternative declaration. 唯一的问题是你错放了beans.xml替代声明。

The CDI specification (1.1, but applicable as well to the previous implementation) states at chapter 5.1 that: CDI规范(1.1,但适用于以前的实现)在第5.1章中指出:

An alternative is not available for injection, lookup or EL resolution to classes or JSP/JSF pages in a module unless the module is a bean archive and the alternative is explicitly selected in that bean archive. 除非模块是bean存档,并且在该bean存档中明确选择了替代方案,否则替代方法不能用于注入,查找或EL解析模块中的类或JSP / JSF页面。

In other words, you must select the alternative in the same module of the class which uses the bean . 换句话说,您必须在使用该bean的类的同一模块中选择替代方案。

Here is the revised (and working) structure: 这是修订(和工作)的结构:

EAR
  - ejb-module-1.jar 
     - A.class (@Inject I)
     - I.class
     - C.class (@Stateless implements I)
     - META-INF/beans.xml (<alternatives><class>D</class></alternative>)
  - ejb-module-2.jar
     - D.class (@Alternative @Stateless implements I)
     - META-INF/beans.xml (empty <beans></beans>)
  - app.war
     - calls A.test()
     - WEB-INF/beans.xml (empty <beans></beans>)

Also remember that, although for standard beans the alternative selection works only for the module in in witch the alternative is declared in beans.xml , the same is not true for EJBs. 还要记住,虽然对于标准bean,替代选择仅适用于 bean 中的模块,但是在beans.xml声明了替代选择 ,对于EJB来说也是如此。 So your D alternative, (being @Stateless ) is valid for the entire application. 所以你的D替代品( @Stateless )对整个应用程序都有效。

Since CDI 1.1. 自CDI 1.1起。 you can use @Priority so your alternative is discoverd in a global context - see here Dependency injection and programmatic lookup 您可以使用@Priority,以便在全局上下文中发现您的替代方案 - 请参阅此处依赖注入和编程查找

And if you use @Priority you do not need to declare the alternative in the beans.xml - see here Using Alternatives in CDI Applications 如果您使用@Priority,则无需在beans.xml中声明替代方法 - 请参阅此处在CDI应用程序中使用替代方案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM