Addressing Ambiguity in Spring Autowiring

With autowiring Spring can automatically inject dependencies into the beans. But it would work only if Spring finds only a unique bean that it should inject. When there are multiple beans that satisfy the injecting criteria, Spring is not certain which bean to inject and throws a NoUniqueBeanDefinitionException.


Ambiguity Condition

The code block below shows a setter method that is used to autowire a vehicle property.

@Autowired
public void setDessert(Vehicle vehicle) {
    this.vehicle = vehicle;
}

Now consider the two beans below, both of these are candidates that can be wired with the vehicle property since both Car abd Bus are of type Vehicle (They implements Vehicle interface). This situation causes an ambiguity and Spring throws a NoUniqueBeanDefinitionException.

@Component
public class Car implements Vehicle { ... }

@Component
public class Bus implements Vehicle { ... }

Addressing Ambiguity with Primary Bean

One way to address the ambiguity is to define a primary bean, using the @Primary annotation. In case an ambiguity arises, the primary bean will be wired.

/** If bean is discovered using component scan **/
@Primary
@Component public class Car implements Vehicle { ... } /** If configured using Java Config **/ @Primary @Bean public Vehicle car(){ return new Car(); }

If the bean is configured using xml, we can use the 'primary' attribute in the <bean> element as shown below:

<bean id="car" class="cubearticle.examples.Car" primary="true" />

Qualifying Beans

Even though the @Primary serves our purpose, there is nothing that can stop us from having multiple primary beans, which can again result in ambiguity. What if we annotate @Primary in both Bus and Car?

The @Qualifier annotation comes to the rescue. Spring provides the @Qualifier annotation that helps us to identify a bean in ambiguity conditions. The code shown below injects the bus into the vehicle property:

@Autowired
@Qualifier("bus")    //'bus' is the bean id of Bus bean
public void setDessert(Vehicle vehicle) {
    this.vehicle = vehicle;
}

Custom Qualifier

We may still run into issues with @Qualifier when we refactor the name of the Bus bean, because the bean id might change (remember that the default bean name is derived from the classname) and hence autowiring will fail. To address this we can use custom qualifiers.

We can use a custom name instead of the bean id. Here we will also need to annotated the bean declaration with @Qualifier.

Note: Custom Qualifiers cannot be used with XML configuration.

@Autowired
@Qualifier("smallCar")
public void setDessert(Vehicle vehicle) {
    this.vehicle = vehicle;
}

/** Qualifier annotation in bean configuration **/ @Component @Qualifier("smallCar") public class Car implements Vehicle { ... } /** If configured using Java Configuration **/ @Bean @Qualifier("smallCar") public Vehicle car(){ return new Car(); }

Let's consider one more scenario, what if we have two small cars? We again end up in ambiguity. One way to resolve it is to have multiple @Qualifier annotation with different different values, say 'smallCar' and 'redCar'. But only problem here is that Java doesn't allow the same annotation to be applied twice.

To handle this we can create annotations that represents our Qualifiers as shown below:

@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface SmallCar { }

@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface RedCar { }

Now we can use these annotation in our classes:

@Autowired
@SmallCar
@RedCar
public void setDessert(Vehicle vehicle) {
    this.vehicle = vehicle;
}

@Component
@SmallCar
@RedCar
public class Car implements Vehicle { ... }
POPULAR ARTICLES

Creating Conditional Beans in Spring

The concept of condition beans enables Spring to restrict the creation of any bean depending on the evaluation of a condition. These beans get created only when a preset condition is evaluated as true

View Article

Accepting Request Param and Path Variable in Spring Controller

Spring MVC provides various ways through which a client browser can pass data to the Controller. In this article we will discuss about accepting Request Parameters and Path Variables in Spring Contr..

View Article

Generate Namespace & Schema Information using JAXB

Most xml documents used in enterprise applications makes use of namespace to avoid element name conflicts. This article talks about generating these namespace and schema information when marshaling...

View Article

Switching Database Profile using Spring Profiles

We are most likely to have separate db configuration for different environment like development and production environment. Spring profiles provide a convenient way to switch db profiles at runtime.

View Article

SQL and its Sub-Languages

SQL (Structured Query Language) is a language understood by most modern databases. It is an ANSI (American National Standard Institute) standard language which is used to manipulate databases.

View Article

Introducing JUnit Rule

Junit Rules allows developers to add additional functionalities that can applied to all test methods in a test class. It is similar to the concept of custom test runners but with reduced restrictions.

View Article

Addressing Ambiguity in Spring Autowiring

Spring autowiring is powerful concept, but we should be very cautious while using it. We may end up in creating ambiguity while autowiring beans, which will cause autowiring to fail.

View Article

Creating and Using Synonym in Oracle Database

Synonyms are database objects used to provide duplicate names to existing objects in the database. It is just an alternate name used to hide the original name of the object.

View Article

Creating and Using Sequence in Oracle Database

A sequence is used to auto-generate numbers in ascending or descending order which can serve as a primary key or a part of it (in case of composite key).

View Article

Creating and Manipulating Constraints in Oracle Database

Constraints are used to impose certain rules on columns to avoid invalid data entry into the table. If any of the constraint is violated the operation fails.

View Article

Integrating Log4J with Perf4J for Performance Logging

Perf4j is an open source logging framework used primarily for monitoring performance statistics in java applications. Log4j has the ability to integrate with perf4j to capture performance data.

View Article

Tagging in GIT

Tagging allows us to mark a specific point in the commit history or snapshot. A tag is typically used to mark a project release. This article shows how to create tags in Git.

View Article