Search code examples
javacdiqualifiers

what is the values() that I have seen in various CDI qualifiers in java?


I have seen various references to values() inside @Qualifier definitions. I understand @Qualifier to be a tagging system, yet you define them as an interface.

An interface can allow enums, but I don't understand the word values() that I've seen in the two unrelated examples I've listed below.

Could you please explain to me the word values() means?

@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE, METHOD})
public @interface NumberOfDigits {
    Digits value();
}

public enum Digits {
    TWO,
    EIGHT,
    TEN,
    THIRTEEN
}

package com.byteslounge.bean;

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 MessageTransport {

  MessageTransportType value();

}

Solution

  • These are not interfaces. These are annotations. It is possible to declare static information on annotations and annotate them. Code that inspects annotations can then utilize this information.

    Annotations declared as Qualifiers let CDI disambiguate between implementations of the same type.

    Consider the qualifier Foo:

    @Qualifier @Retention(RUNTIME) @Target({FIELD, TYPE, METHOD})
    public @interface Foo { int value(); }
    

    Types annotated with Foo:

    @Foo(1) public class Bar implements Runnable {
       //...impl
    
    @Foo(2) public class Baz implements Runnable {
       //...impl
    

    A CDI bean:

    public class Bean {
      @Inject @Foo(1) Runnable a;
      @Inject @Foo(2) Runnable b;
      //...impl
    

    Here, a will be resolved to an instance of Bar while b will be resolved to an instance of Baz.

    Without the qualifier annotation, the CDI API wouldn't be able to tell which instance of Runnable to inject. All the values must be an exact match.