Search code examples
jakarta-eedependency-injectioncdi

JavaEE: Inject @Alteriative to Insance<Interface> with no default implementation


I've got an ejb-JAR consistig of some Classes counting different values [Counter1, Counter2,...] all implementing the same Interface [ICountable]. Also part of this JAR is a class looping over all extisting counters and returning its values [CounterCollector].

Now I have two other WARs with the EJB packed into it.

My intention is to have the first WAR only using Counter1 and Counter3. The other WAR using Counter1 and Counter2. (The real scenario is a litte bit more complicated but I think it's enough information to get the idea)

I thougt of using @Alternative-Annotation on all Counters and having only the enabled Alternatives injected in CounterCollector as follows:

...

@Inject
private Instance<ICountable> counters;

public List<Integer> getCounts()
{
    List<Integer> c = new ArrayList<>();
    for (ICountable countable : counters) {
         c.add(countable.count());
    }
    return c;
}

...

In WAR1 I activate counters 1 and 3 in the beans.xml:

<alternatives>
  <class>Counter1</class>
  <class>Counter3</class>
</alternatives>

in the second WARs beans.xml:

<alternatives>
  <class>Counter1</class>
  <class>Counter2</class>
</alternatives>

As long as the ICounter-implementations are NOT annotated as @Alternative everything works as expected (besides obviously all counters are triggert).

As soon as I annotate the ICounters with @Alternative they are not injected at all. No matter if they are enabled via beans.xml.

Isn't it possible to inject @Alternative-Annotated classes into javax.enterprise.inject.Instance?

Am I using the @Alternative in a way it is not ment to work or am I missing something?


Solution

  • Your problem is unrelated to Instance<T>, it's just about bean archives and selecting alternatives.

    I suppose your WAR looks something like this:

    WEB-INF/
        beans.xml
        classes/
        lib/
            ejb.jar
    

    and WEB-INF/beans.xml is the place where you activate your alternatives.

    Now it is important to note that WEB-INF/classes and ejb.jar are two distinct bean archives. Selecting an alternative via beans.xml only affects the bean archive containing this file.

    So in your case, anything you do in WEB-INF/beans.xml will have no effect on lib/ejb.jar

    You could try selecting your alternatives at application level using @Priority annotations on producer methods or on derived classes.

    @ApplicationScoped
    @Priority(Interceptor.Priority.APPLICATION)
    public class Counter1SelectedForWar extends Counter1 { ... }