WELD-001409 – Ambiguous dependencies


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.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s