INTRODUÇÃO

Vamos começar falando um pouco sobre os qualificadores da CDI, como muitos devem saber a CDI a uma especificação JAVA que deu muito poder e extensividade a Linguagem, não vou entrar no mérito de falar sobre a especificação, apenas sobre a funcionalidade de Qualificadores.

QUALIFICADORES OU QUALIFIER

Imagine que temos uma interface com várias implementações, uma das utilidades dos qualifier é informarmos qual implementação vamos usar, se liga no exemplo.

public interface PaymentMethod {
    public void pay();
}

ai temos 2 implementações para a interface PaymentMethod

public class CreditCard implements PaymentMethod {
    @Override
    public void pay() {
        System.out.println("payment by cred card");
    }
}
public class Cash implements PaymentMethod {

    @Override
    public void pay() {
        System.out.println("payment by CASH");
    }
}

Se em nossa classe cliente apenas injetarmos a interface PaymentMethod a CDI lançará uma exceção de ambiguidade, informando que não sabe qual implementação irá injetar, tranquilo até ai ?

public class Checkout {

    @Inject
    private PaymentMethod payment;

    public void checkout() {
        payment.pay();
    }

}

Da uma olha no error que vai aparecer no seu console.

WELD-001475: The following beans match by type, but none have matching qualifiers:
- Managed Bean [class br.com.cassunde.cdi.qualifier.Cash] with qualifiers [@Any @Payment],
- Managed Bean [class br.com.cassunde.cdi.qualifier.CreditCard] with qualifiers [@Any @Payment]

Para resolvermos isso teremos que criar um qualifier CDI, a sua criação e bem simples, basta criar uma anotação java padrão com uma pequena diferença, essa nossa anotação terá um @Qualifier, como o próprio nome já diz, será o responsável por indicar que essa nossa anotação e um qualifier. ficara mais ou menos assim.

@Retention(RUNTIME)
@Target({ TYPE, FIELD, METHOD, PARAMETER })
@Qualifier
public @interface PaymentCreditCard {}

vamos fazer um exemplo ruim e depois vamos ver uma forma melhor de resolver esse problema usando qualifier, em nosso exemplo a interface PaymentMethod tem 2 implementações a CreditCard e a Cash, em nossa abordagem ruim faremos uma outra anotação para qualificarmos a segunda implementação então vamos lá: Qualifier para Implementação Cash:

@Retention(RUNTIME)
@Target({ TYPE, FIELD, METHOD, PARAMETER })
@Qualifier
public @interface PaymentCash {}

para usarmos esses qualifier ficara mais ou menos assim: - Implementação CreditCard

@PaymentCreditCard
public class CreditCard implements PaymentMethod {

    @Override
    public void pay() {
        System.out.println("payment by creditcard");
    }
}

Classe cliente

public class Checkout {

    @Inject
    @PaymentCreditCard
    private PaymentMethod payment;

    public void checkout() {
        System.out.println("Starting checkout");
        payment.pay();
    }
}

Dessa forma não fica muito legal, caso apareça uma nova implementação teremos que criar uma nova anotação e por ai vai… vamos agora melhorar essa abordagem, vamos inserir uma enum em nosso qualifier.

Vou criar essa enum e um terceiro qualifier chamado Payment

public enum PaymentType {
    CREDIT,
    CASH,
    DEBIT
}

Nosso terceiro qualifier ficaria assim:

@Retention(RUNTIME)
@Target({ TYPE, FIELD, METHOD, PARAMETER })
@Qualifier
public @interface Payment {
    PaymentType type();
}

agora podemos substituir os primeiros qualifier que criamos por esse último, ficando mais ou menos assim:

Implementação CreditCard

@Payment(type=PaymentType.CREDIT)
public class CreditCard implements PaymentMethod {

    @Override
    public void pay() {
        System.out.println("payment by cred card");
    }
}

Método Cliente

public class Checkout { 

    @Inject
    @Payment(type=PaymentType.CREDIT)
    private PaymentMethod payment; 

    public void checkout() {
        System.out.println("Starting checkout");
        payment.pay();
    }
}

Implementação Cash

@Payment(type=PaymentType.CASH)
public class Cash implements PaymentMethod {

    @Override
    public void pay() {
        System.out.println("payment by cred card");
    }
}

Método Cliente

public class Checkout { 

    @Inject
    @Payment(type=PaymentType.CASH)
    private PaymentMethod payment; 

    public void checkout() {
        System.out.println("Starting checkout");
        payment.pay();
    }
}

Observem que agora estamos usando apenas uma única anotação e estamos “tipando” nosso qualifier, dessa forma temos mais liberdade para evoluir o código.

Por enquanto e só isso.


Curtiu ? Me segue nas redes 😉