= CDI Dynamic Inject
:index-group: CDI
:jbake-type: page
:jbake-status: published

== Introdução

As vezes precisamos escrever várias implementações para uma interface de regras de negócios, para aumentar o desacoplamento vamos injetar dinamicamente a implementação em tempo de execução.

== Exemplo 1

Neste exemplo, temos uma interface `Payment` e suas implementações: 

- Cash
- CreditCard 

Em nosso teste (`FinalizePaymentTest`) nós injetamos a classe FinalizePayment, e chamamos o método `finishWithCash`.

Esse método irá injetar dinamicamente a implementação correta usando os recursos do CDI

[source,java]
----
public String finishWithCash() {

	paymentChoosed = paymentsLazy.select(Cash.class).get();
	return paymentChoosed.pay();
}
----

observe que está sendo usado uma variável chamada de `paymentsLazy` essa variável irá conter todas as implementações da interface `Payment`

[source,java]
----
@Inject
@Any
private Instance<Payment> paymentsLazy;
----


Nessa variável estamos usando:

- Anotação `@inject` 

Indica ao CDI que gostariamos de realizar um injeção de dependencia

- Anotação `@Any` 

Indicar que deve ser listada todas as implementações possíveis.

- Objeto `Instance`

Objeto responsável por conhecer todas as implementações possíveis e instancia-las no momento desejado.

com essa variável pronta podemos chama-la usando o:

[source,java]
----
paymentsLazy.select(Cash.class).get();
----

onde `Cash.class` informa qual e a implementação e `.get()` retorna a instancia pronta para uso.

== Exemplo 2

Neste exemplo, temos uma interface `Payment` e suas implementações: 

- Cash
- CreditCard 

Em nosso teste (`FinalizePaymentQualifierTest`) nós injetamos a classe FinalizePayment, e chamamos o método `finishByQualifier`.

Esse método irá injetar dinamicamente a implementação correta usando um `Qualifier`(PaymentType).

[source,java]
----
public String finishByQualifier(PaymentType type) {

    paymentChoosed = paymentsLazy.select( new PayByQualifier(type) ).get();
    return paymentChoosed.pay();
}
----

Para essa abordagem funcionar precisaremos criar uma nova classe chamada `PayByQualifier` que extende `AnnotationLiteral` que espera a passagem de um qualifier em seu parametro `T extends Annotation`(Generics).

[source,java]
----
public class PayByQualifier extends AnnotationLiteral<PaymentQualifier> implements PaymentQualifier {
	
	private PaymentType type;

	public PayByQualifier(PaymentType type) {
		
		this.type = type;
	}
	
	@Override
	public PaymentType type() {
		return this.type;
	}
}
----

o importante e implementar o método da Anotação em nosso caso o `public PaymentType type();`

Para faciliar essa implementação recebemos esse valor por construtor de nossa nova classe

[source,java]
----
public PayByQualifier(PaymentType type) {
		
    this.type = type;
}
----

Com essa classe pronta podemos usa-la em nossa classe de negócio:

[source,java]
----
paymentChoosed = paymentsLazy.select( new PayByQualifier(type) ).get();
----

Obs: A estrutura de qualifier foi reaproveitada do project https://github.com/cassunde/tomee/tree/master/examples/cdi-qualifier
