1

I have a Interface Hello.java which is implemented by 2 classes HelloImpl1.java and HelloImpl2.java

I have declared HelloImpl1.java as part of META-INF/services.

Now, when I try to I Inject Hello class, it's failing saying ambiguity due to 2 implementations.

My question is when I already defined HelloImpl1.java as part of META-INF/services , why inject is not picking that class?

Kindly help me resolving the issue.

I need to inject the Interface so that the Impl classes will be manged by CDI

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555

1 Answers1

2

In CDI, a bean is identified by its types and qualifiers. By default, types are derived from a transitive type closure of the bean class defining it (or a return type of a producer method/field defining the bean).

Therefore, in your case, there are two bean with following types:

  • {Hello, HelloImpl1}
  • {Hello, HelloImpl2}

You didn't use any qualifiers, which is why you see the ambiguity; when you @Inject Hello hello, CDI can see two eligible beans and cannot make a decision on which one is correct.

I have declared HelloImpl1.java as part of META-INF/services.

I have no idea what you mean by that. Just declaring a bean there has no effect on CDI itself.

The correct solution is to use CDI qualifiers, they are a natural fit to disambiguate two or more beans with equal types. In your case, you didn't use any, so CDI automatically adds default qualifiers.

Here is how you can declare your own qualifier:

@Qualifier
@Retention(RUNTIME)
@Target({ TYPE, FIELD, METHOD, PARAMETER })
public @interface MyQualifier {
}

You then annotate both, your bean declaration and any injection point where this is meant to be injected.

@Dependent // this is just an example, use any scope you need or have been using
@MyQualifier // specify qualifier of this bean
public class HelloImpl1 implements Hello {
// some very cool code
}

The following injection point is not ambiguous, because there will be only one bean with required type Hello and qualifier @MyQualifier.

// declare the injection point with qualifier(s)
@Inject
@MyQualifier
Hello helloBean;

Finally, I'd recommend you read more about this in CDI specification. Sections such as typesafe resolution or qualifiers are what you're looking for.

Siliarus
  • 6,393
  • 1
  • 14
  • 30
  • 1
    As a sidenote: java.util.ServiceLoader along with META-INF/services is a totally different mechanism, which is ignored by all known implementations of a CDI container. For CDI, the bean has to be part of a bean archive, and that's all there is to it. – mtj Nov 23 '22 at 07:44