Weld/CDI resolves bean injection mainly based on type or name. This is sufficient for most cases and works like a charm. You can either specify a name yourself or inject it by simply letting CDI resolve the type for you. The following snippet shows how easy it is.
@Named("yourName") public class SomeClass implements SomeInterface { //Your class implementation } public class YourImplementation { @Inject SomeInterface someClass; //Or @Inject @Named("yourName") SomeClass someClass; }
Now in my case I had multiple classes that all implemented the same signature. Based on the name I wanted to inject one or another class. However, when letting CDI resolve the injection by type or name I got an error stating that the bean could not be injected because multiple options exist. The error message looked something like this:
org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type AuthorizationInterface with qualifiers @Default at injection point [BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] @Inject @Named public nl.janssen.my.class[SomeInterface] at nl.janssen.theClassInWhichYouTryTheInjection Possible dependencies: - Managed Bean [ class nl.janssen.interfaceBasedClassOne] with qualifiers [@Default @Named @Any], - Managed Bean [ class nl.janssen.interfaceBasedClassTwo] with qualifiers [@Default @Named @Any],
It states that CDI cannot inject the class because it has more then one dependency. It cannot decide which one to pick. The solution is to create your own qualifiers. CDI already has some default qualifiers (default, any etc.) which you can see in the error but they are not sufficient in this case. You have to create a custom qualifier for each implementation of the interface that you want to inject. With these qualifiers you can tell CDI that you want inject a bean of type X and it has to have a qualifier y. By adding a custom qualifier to each interfaced object I can tell CDI to inject a specific class. A custom qualifier looks like this:
import javax.inject.Qualifier; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; @Qualifier @Retention(RUNTIME) @Target({TYPE, PARAMETER}) public @interface One { }
The @Target indicates the location in which you can use the qualifier. This qualifier you can use when injecting a parameter or a type.
Now you have to specify your implementations with the correct qualifiers:
import javax.enterprise.inject.Default; //Interface implementation with the custom qualifiers @One public class SomeClassOne implements SomeInterface { //Your class implementation } @Two @Default public class SomeClassTwo implements SomeInterface { //Your class implementation } //Injection of the public class YourImplementation { @Inject @One SomeInterface classOne; @Inject @Two SomeInterface classTwo; @Inject SomeInterface classTwoIsDefault;
CDI will now resolve the correct implementation and no longer complain about ambiguous dependencies. When you do not provide a qualifier CDI will raise the same ambiguous error again. This because it doesn’t know which implementation is the default. You can specify this by adding the “@Default” annotation to one of your classes.