DEV Community

Cover image for Understanding Jakarta EE 8 - C.D.I. (Part 2) - Qualifying your beans.
Buhake Sindi
Buhake Sindi

Posted on • Edited on

Understanding Jakarta EE 8 - C.D.I. (Part 2) - Qualifying your beans.

[As we continue with this series, we will refer to some content and examples from the CDI 2.x specification].

In order for the CDI container to recognise your bean for injection, your bean needs to be qualified. This can be achieved by associating a bean with a qualifier type. A qualifier type represents some client-visible semantic associated with a type that is satisfied by some implementations of the type (and not by others). In other words, a qualifier type identifies a bean with a type that can be satisfied to one specific implementation of the same type (else it becomes an unsatisfied dependency).

Let's look at how a bean can be qualified using a bean qualifier types.

Bean Qualifier Types

There's 3 standard qualified types that are defined in the javax.enterprise.inject package:

  1. @Any: Every bean has the built-in qualifier @Any, even if it does not explicitly declare this qualifier, except for the special @New.
  2. @Default: If a bean does not explicitly declare a qualifier other than @Named, the bean has the qualifier @Default.
  3. @New: The @New qualifier allows the application to obtain a new instance of a bean which is not bound to the declared scope, but has had dependency injection performed.

The following declarations are equivalent:

@Default
public class Order { ... }
Enter fullscreen mode Exit fullscreen mode
public class Order { ... }
Enter fullscreen mode Exit fullscreen mode

Both declarations result in a bean with two qualifiers: @Any and @Default.

The default qualifier is also assumed for any injection point that does not explicitly declare a qualifier, Thus, the following declarations, in which the use of the @Inject annotation identifies the constructor parameter as an injection point, are equivalent:

public class Order {
    @Inject
    public Order(@Default OrderProcessor processor) { ... }
}
Enter fullscreen mode Exit fullscreen mode
public class Order {
    @Inject
    public Order(OrderProcessor processor) { ... }
}
Enter fullscreen mode Exit fullscreen mode

In conclusion, the @Any and the @Default qualifier are always assumed during bean qualification as well as at injection point when the qualifier hasn't been explicitly declared.

The @Named Qualifier

The @Named is defined by the package javax.inject. This qualifier is used to specify the name of a bean. For example, this bean is named currentOrder:

@Named("currentOrder")
public class Order { ... }
Enter fullscreen mode Exit fullscreen mode

The above declaration results in a bean with three qualifiers: @Any, @Default and @Named("currentOrder").

If @Named is declared by the bean with no bean name provided, the default bean name is used, after converting the first character of the class name to lowercase. For example, using the example above, if Order class was just annotated with @Named, the default bean name will be order.

For more information, please refer to section 3.1.5 Default bean name for a managed bean.

If @Named is not declared by the bean, nor by its stereotypes, a bean has no name.

Now that you have a basic insight on qualifying beans, let's look at various examples of qualifying beans using bean qualifier types. Note that we've set the bean-discovery-mode as all, the CDI container successfully recognised our classes as a qualified classes, ready for injection.

Example 1: CDI injection of implicit @Default bean class (with no interfaces)

The tutorial source code can be found here and the running executable class file can be found here and it follows the example as mentioned in the previous article. The DefautService and MainController classes are simple classes that don't extend nor inherit any other class or interfaces respectively and has not been annotated with any bean qualifiers. This is due to the fact that all qualified bean are implicitly set as @Any and @Default.

Example 2: CDI injection of implicit @Default bean class (injection on interface)

This is the extension of Example 1 but, in this case, the DefaultService implements the Service interface.
The tutorial source code can be found here and the running executable class file can be found here. On MainController class we simply inject on the property which links to the Service interface.
Seeing that there are no annotations on DefaultService, the CDI container has managed to successfully discovery one implementation of the Service interface and thus, creating a contextual context around the Service interface (which in turn will inject DefaultService when needed).
The DefaultService implicitly is qualified as a @Any and @Default.

Let's pause on here. In the next tutorial we'll look on how to tackle injections of classes / interfaces that can produce more than 1 dependency injections using @Alternative as well as defining our own custom qualifier type.

Top comments (0)