About Goncalo Marques
In this tutorial you will learn how to inject multiple interface implementations with Java EE CDI (dependency disambiguation) avoiding org.jboss.weld.exceptions.DeploymentException: WELD-001409 Ambiguous dependencies for type [...] with qualifiers [...] at injection point [...]
1. Introduction
In Java EE CDI it is possible to provide multiple implementations of a given interface – or service – to the service clients. The client should then be responsible for selecting the desired service implementation to be injected into a given injection point. In this tutorial we will see how to achieve this behaviour in detail.
This tutorial considers the following environment:
- JDK 1.7.0.21
- Weld 1.1.10
Weld is the CDI reference implementation
Note: When we provide multiple interface implementations with CDI and we don’t specifically define any dependency disambiguation, the container will complain stating that it can not determine which implementation to inject at a given injection point.
Example exception:
org.jboss.weld.exceptions.DeploymentException: WELD-001409 Ambiguous dependencies for type [...] with qualifiers [...] at injection point [...]. Possible dependencies [...] with qualifiers [...], Managed Bean [...] with qualifiers [...]
2. The service
We start by defining a simple interface and a couple of interface implementations to serve as an example in this tutorial:
The interface
package com.byteslounge.service;public interface NotificationService { void sendNotification();} EmailNotificationService implementation
package com.byteslounge.service.impl;import com.byteslounge.service.NotificationService;public class EmailNotificationService implements NotificationService { @Override public void sendNotification() { System.out.println("Sending email notification"); }} SmsNotificationService implementation
package com.byteslounge.service.impl;import com.byteslounge.service.NotificationService;public class SmsNotificationService implements NotificationService { @Override public void sendNotification() { System.out.println("Sending SMS notification"); }} What happens now when we inject the NotificationService bean?
NotificationService injection
@Injectprivate NotificationService notificationService;
The container will not know which of the available implementations should be injected and will complain about it. We will see how to do dependency disambiguation in the next section.
3. Dependency disambiguation
One of the mechanisms provided by CDI to do dependency disambiguation is Qualifiers. Qualifiers are defined as Java annotations and are used by CDI to specify which dependency should be injected at a given injection point.
Let’s define a Qualifier to be used in our NotificationService:
CDI qualifier
package com.byteslounge.service;import static java.lang.annotation.ElementType.FIELD;import static java.lang.annotation.ElementType.TYPE;import static java.lang.annotation.ElementType.METHOD;import static java.lang.annotation.RetentionPolicy.RUNTIME;import java.lang.annotation.Retention;import java.lang.annotation.Target;import javax.inject.Qualifier;@Qualifier@Retention(RUNTIME)@Target({FIELD, TYPE, METHOD})public @interface NotificationServiceType { ServiceType value(); public enum ServiceType{ EMAIL, SMS; }} We defined a Java annotation that will be used to disambiguate between EmailNotificationService and SmsNotificationService service implementations. Also note that for convenience we defined an Enum which will be used as the value of our qualifier: EMAIL or SMS.
Now we go back to the service implementations and use the Qualifier annotation we just defined:
EmailNotificationService implementation
package com.byteslounge.service.impl;import com.byteslounge.service.NotificationService;import com.byteslounge.service.NotificationServiceType;import com.byteslounge.service.NotificationServiceType.ServiceType;@NotificationServiceType(ServiceType.EMAIL)public class EmailNotificationService implements NotificationService { @Override public void sendNotification() { System.out.println("Sending email notification"); }} SmsNotificationService implementation
package com.byteslounge.service.impl;import com.byteslounge.service.NotificationService;import com.byteslounge.service.NotificationServiceType;import com.byteslounge.service.NotificationServiceType.ServiceType;@NotificationServiceType(ServiceType.SMS)public class SmsNotificationService implements NotificationService { @Override public void sendNotification() { System.out.println("Sending SMS notification"); }} As you can see we used the Qualifier in each service implementation – @NotificationServiceType – where the value is EMAIL or SMS respectively.
Now when we inject the service we also use the Qualifier in order to specify which service implementation should be used:
NotificationService injection
@Inject@NotificationServiceType(ServiceType.EMAIL)private NotificationService notificationService;
By annotating the injection point with @NotificationServiceType(ServiceType.EMAIL) we will make possible for the container to know that it should inject the EmailNotificationService service implementation.
4. Dependency disambiguation in CDI Producer methods
It is also possible to do dependency disambiguation in CDI Producer methods. Please see Java EE CDI Producer methods tutorial.
5. Downloadable sample
You can find a downloadable sample at the end of this page showing CDI dependency disambiguation in action. The sample is configured to be run on Tomcat and the service is injected into a testing servlet.
Download source code from this tutorial
Source : http://www.javacodegeeks.com/2013/06/java-ee-cdi-dependency-disambiguation-example.html