如何正确使用@Alternative进行客户端实现

时间:2012-10-04 16:39:55

标签: java-ee ejb cdi ejb-3.1 qualifiers

编辑:我将CDI注入点从使用@EJB更改为使用@Inject,如下面的注释中所示。只是一个FYI。


我有两个EAR项目,两者基本相同。他们唯一的区别是需要时的一些客户特定实现。但是,我遇到了问题。

这就是我所拥有的:

EAR#1包含以下模块:

web.war 
ejb-default.jar
ejb-client-1.jar

EAR#2包含以下模块:

web.war
ejb-default.jar
ejb-client-2.jar

在ejb-default中包含以下内容:

@Singleton
@Startup
public class ApplicationSettingsBean implements ApplicationSettingsBeanLocal

现在,对于EAR#1,ejb-client-1.jar可能为空,因此任何EJB注入都应该使用ejb-default中的任何内容。

但是,对于EAR#2,我想用特定于客户端的实现覆盖默认实现。例如:

@Singleton
@Startup    
@Alternative
public class ApplicationSettingsBean implements ApplicationSettingsBeanLocal {

我还在ejb-client-2中创建了以下beans.xml条目:

<beans xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
    <alternatives>
        <class>com.client2.ejb.ApplicationSettingsBean</class>
    </alternatives>
</beans>

我希望在存在这样的实现时会注入@Alternative实现。如果在注入点指定了@Default,则应注入默认实现(ejb-default)。虽然,这不会发生:

    // Inject the alternative implementation
    @Inject
    private ApplicationSettingsBeanLocal appSettingsBean;

使用此CDI,默认是注入,而不是替代。这不是预期的行为。

2 个答案:

答案 0 :(得分:4)

beans.xml ,您必须在其中指定替代品, 必须位于 ejb-client.jar 内,而不是 ejb-client-2.jar

CDI规范(1.1,但适用于之前的实施)在第5.1章中指出:

  

替代品不适用于注射,查找或EL分辨率   除非模块是bean,否则模块中的类或JSP / JSF页面   存档和替代是在该bean中明确选择的   档案

换句话说,您必须在使用bean的类的同一模块中选择替代方案。

答案 1 :(得分:3)

对于那些想知道发生了什么的人来说,这会混合CDI和EJB(EE5)注入。这就是第一个错误发生的原因。替代品是CDI的想法,而@EJB不承认它们。

默认而不是替代的原因是因为这是注入时使用的限定符(替代方案没有暗示@Default)。这基本上告诉CDI我确切地知道我想要哪个实例,它是我在注射时使用的具有相同限定符的实例。处理这样的事情的最好方法是简单地使用@Inject而不使用任何限定符,除非你确切知道你想要哪个实例并将这些限定符添加到注入(实现类中的相同)。