Bruno
Bruno

Reputation: 151

@Alternative and Default implementation CDI

@Inject
Instance<FooInterface> fooInstances;

DefaultImplementation implements FooInterface{}

@Alternative
@Priority(1)
AlternativeImplementation implements FooInterface{}

Would like to iterate through and return the fooImplementation requested as parameter, although the Instance only has the AlternativeImplementation and not the DefaultImplementation.

What would be a solution to sort this problem out? I really need both implementations available.

public FooInterface getImplementation(String name){
   Iterator<FooInterface> iterator = fooInstances.iterator();
    while (iterator.hasNext()) {
          FooInterface fooInterface = iterator.next();
         if (fooInterface .getName().equals(strategyName)) {
              return fooInterface ;
         }
    }
}

Upvotes: 0

Views: 1263

Answers (2)

Illya Kysil
Illya Kysil

Reputation: 1746

According to the CDI Specification:

5.1.2. Enabled and disabled beans

A bean is said to be enabled if:

  • it is deployed in a bean archive, and
  • it is not a producer method or field of a disabled bean, and
  • it is not specialized by any other enabled bean, as defined in Specialization, and either
  • it is not an alternative, or it is a selected alternative of at least one bean archive or the application.

Otherwise, the bean is said to be disabled.

In your scenario, DefaultImplementation is a disabled bean since an alternative AlternativeImplementation bean is selected due to the presence of the @Priority annotation.


Proceed as following:

  1. Remove @Alternative annotations from all classes implementing FooInterface

  2. Introduce a qualifier to select preferred instance:

    @Qualifier
    @Retention(RUNTIME)
    @Target({METHOD, FIELD, PARAMETER, TYPE})
    public @interface Preferred {
    }
    
  3. Annotate DefaultImplementation with that qualifier

    @Preferred
    DefaultImplementation implements FooInterface{}
    
  4. Use the following injection point declaration to get access to all beans implementing the interface:

    @Inject
    @Any
    Instance<FooInterface> fooInstances;
    

    You would need to handle the @Priority explicitly in the code though.

  5. Use the following injection point declaration to get the preferred bean:

    @Inject
    @Preferred
    FooInterface preferredFooInstance;
    

Upvotes: 1

Laird Nelson
Laird Nelson

Reputation: 16174

That's what the @Any qualifier is for. All beans have the @Any qualifier unless someone has gone to extraordinary lengths to omit it.

@Inject
@Any
Instance<FooInterface> fooInstances;

Be aware that you will now have to apply the relevant alternative-and-priority-and-default instance logic yourself. Chances are you're after something else, but strictly speaking this is the answer to your question.

Upvotes: 1

Related Questions