Search code examples
jakarta-eeejbcdiejb-3.1qualifiers

How to properly use @Alternative for client implementations


EDIT: I changed the CDI injections points from using @EJB to using @Inject as indicated in my below comments. Just an FYI.


I have two EAR projects, both basically the same. The only difference they have are a few client specific implementations, where required. I'm having a problem, however.

This is what I have:

EAR #1 contains the following modules:

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

EAR #2 contains the following modules:

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

In ejb-default contains the following:

@Singleton
@Startup
public class ApplicationSettingsBean implements ApplicationSettingsBeanLocal

Now, for EAR #1, the ejb-client-1.jar might be empty, so any EJB injections should use whatever is in ejb-default.

For EAR #2, however, I want to override the default implementation with a client specific one. For example:

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

I also created the following beans.xml entry in ejb-client-2:

<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>

I would expect that the @Alternative implementation would be injected when such an implementation exists. If @Default is specified at the injection point, then the default implementation (ejb-default) should be injected. Though, that doesn't happen:

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

With this CDI, the default is being injected, not the alternative. That's not the expected behavior.


Solution

  • The beans.xml where you have to specify the Alternatives, have to be inside the ejb-default.jar not in the ejb-client-2.jar.

    The CDI specification (1.1, but applicable as well to the previous implementation) states at chapter 5.1 that:

    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.

    In other words, you must select the alternative in the same module of the class which uses the bean.