= Alternativas e Estereótipos do CDI
:index-group: CDI
:jbake-type: page
:jbake-status: published  mocking

== Introdução
CDI é uma revolução para o mundo Java EE. Está especificação é a melhor para evitar acoplamento entre classes.

Este exemplo simplesmente pretende substituir ligações em tempo de execução para simplificar o trabalho de mocking.

Aqui usamos dois tipos de mocks:

1) um mock com nenhuma implementação no classloader

2) um mock com uma implementação no classloader

A resposta mock do CDI é chamada de _alternative_.

Anotando com o `@Alternative` uma classe significa que será usado como implementação se não houver outra implementação
ou se for forçado (através do `META-INF/beans.xml`).

== Explicação do Código

=== Código Principal

Nós usamos um EJB `Journey` para modelar um journey onde o vehicle e society pode mudar. Aqui um EJB é usado
por que isto simplifica o teste. Uma journey envolve a informação de vehicle e society .

Nós definimos duas interfaces para injetar no EJB `Journey`:` Vehicle` e `Society`.

Finalmente, adicionamos uma implementação para a interface `Society`:` LowCostCompanie`.

Se paramos aqui, o objeto `Journey` não poderá ser criado porque não há uma implementação `Vehicle` acessível.

NOTE: se tivermos uma implementação de `Vehicle`, a Society injetada deverá ser `LowCostCompanie`.

=== Código de Teste

O objetivo aqui é para testar o nosso EJB `Journey`. Portanto, temos que fornecer uma implementação de `Vehicle`:` SuperCar`.

Queremos forçar a interface `Society` a ser a implementação do `AirOpenEJB` para o nosso teste.

Uma solução poderia ser simplesmente adicionar a anotação `@ Alternative` no` AirOpenEJB` e ativá-la através do
arquivo `META-INF / beans.xml`.

Aqui queremos escrever um código mais explícito. Então, queremos substituir a anotação `@Alternative` por uma` `@Mock`.

Então nós definimos uma anotação `@Mock` para classes, resolvíveis em tempo de execução como um estereótipo (` @Stereotype`)
que substitui o `@Alternative`.

Aqui a anotação:

[source,java,numbered]
----
 @Stereotype // we define a stereotype
 @Retention(RUNTIME) // resolvable at runtime
 @Target(TYPE) // this annotation is a class level one
 @Alternative // it replace @Alternative
 public @interface Mock {}
----

NOTE: você pode adicionar mais anotações CDI após `@Alternative` e obterá o comportamento esperado (o escopo para a instância).

Então agora temos a nossa anotação `@ Mock`, que é um estereótipo capaz de substituir a anotação` @ Alternative` quando
adicionado às nossas mocks.

Se você executar isso agora, nós receberemos está exceção:

[source,java,numbered]
----
 javax.enterprise.inject.UnsatisfiedResolutionException: Api type [org.superbiz.cdi.stereotype.Vehicle] is not found with the qualifiers
 Qualifiers: [@javax.enterprise.inject.Default()]
 for injection into Field Injection Point, field name :  vehicle, 
 Bean Owner : [Journey, Name:null, WebBeans Type:ENTERPRISE, API Types:[java.lang.Object,org.superbiz.cdi.stereotype.Journey], 
 Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default]]
----

Isso significa que o estereótipo não está ativado. Para fazer isso basta adicioná-lo ao seu `META-INF / beans.xml`:

----
 <alternatives>
   <stereotype>org.superbiz.cdi.stereotype.Mock</stereotype>
 </alternatives>
----
NOTE: se você não especificar `AirOpenEJB` como` @ Alternative` (feito através de nossa anotação mock) você receberá está exceção:

[source,java,numbered]
----
 Caused by: javax.enterprise.inject.AmbiguousResolutionException: 
 There is more than one api type with : org.superbiz.cdi.stereotype.Society with qualifiers : 
 Qualifiers: [@javax.enterprise.inject.Default()] for injection into Field Injection Point, field name :  society, 
 Bean Owner : [Journey, Name:null, WebBeans Type:ENTERPRISE, 
 API Types:[org.superbiz.cdi.stereotype.Journey,java.lang.Object], 
 Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default]]
 found beans:
 AirOpenEJB, Name:null, WebBeans Type:MANAGED, 
API Types:[org.superbiz.cdi.stereotype.Society,org.superbiz.cdi.stereotype.AirOpenEJB,java.lang.Object], 
Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default]
 LowCostCompanie, Name:null, WebBeans Type:MANAGED, 
API Types:[org.superbiz.cdi.stereotype.Society,org.superbiz.cdi.stereotype.LowCostCompanie,java.lang.Object], 
Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default]
----

o que significa simplesmente que duas implementações estão disponíveis para o mesmo ponto de injeção (`Journey.society`).

== Conclusão

Com o CDI é realmente fácil definir anotações com um forte significado. Você pode definir anotações de negócios
ou simplesmente anotações técnicas para simplificar seu código (como fizemos com a anotação mock).

NOTE: se você usou qualificadores para injetar objetos `Society` você poderia ter colocado todos esses qualificadores em
a classe mock ou definiu uma anotação `@SocietyMock` para poder injetar a mesma implementação para
todos os qualificadores em seus testes.

== Saída

----
 Running org.superbiz.cdi.stereotype.StereotypeTest
 Apache OpenEJB 7.0.0-SNAPSHOT    build: 20111030-07:54
 http://tomee.apache.org/
 INFO - openejb.home = /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes
 INFO - openejb.base = /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes
 INFO - Using 'javax.ejb.embeddable.EJBContainer=true'
 INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
 INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
 INFO - Found EjbModule in classpath: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes/target/test-classes
 INFO - Found EjbModule in classpath: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes/target/classes
 INFO - Beginning load: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes/target/test-classes
 INFO - Beginning load: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes/target/classes
 INFO - Configuring enterprise application: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes
 INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
 INFO - Auto-creating a container for bean cdi-alternative-and-stereotypes_test.Comp: Container(type=MANAGED, id=Default Managed Container)
 INFO - Configuring Service(id=Default Singleton Container, type=Container, provider-id=Default Singleton Container)
 INFO - Auto-creating a container for bean Journey: Container(type=SINGLETON, id=Default Singleton Container)
 INFO - Enterprise application "/opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes" loaded.
 INFO - Assembling app: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes
 INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/cdi-alternative-and-stereotypes_test.Comp!org.apache.openejb.BeanContext$Comp")
 INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/cdi-alternative-and-stereotypes_test.Comp")
 INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/cdi-alternative-and-stereotypes.Comp!org.apache.openejb.BeanContext$Comp")
 INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/cdi-alternative-and-stereotypes.Comp")
 INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/Journey!org.superbiz.cdi.stereotype.Journey")
 INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/Journey")
 INFO - Jndi(name="java:global/EjbModule162291475/org.superbiz.cdi.stereotype.StereotypeTest!org.superbiz.cdi.stereotype.StereotypeTest")
 INFO - Jndi(name="java:global/EjbModule162291475/org.superbiz.cdi.stereotype.StereotypeTest")
 INFO - Created Ejb(deployment-id=cdi-alternative-and-stereotypes_test.Comp, ejb-name=cdi-alternative-and-stereotypes_test.Comp, container=Default Managed Container)
 INFO - Created Ejb(deployment-id=cdi-alternative-and-stereotypes.Comp, ejb-name=cdi-alternative-and-stereotypes.Comp, container=Default Managed Container)
 INFO - Created Ejb(deployment-id=org.superbiz.cdi.stereotype.StereotypeTest, ejb-name=org.superbiz.cdi.stereotype.StereotypeTest, container=Default Managed Container)
 INFO - Created Ejb(deployment-id=Journey, ejb-name=Journey, container=Default Singleton Container)
 INFO - Started Ejb(deployment-id=cdi-alternative-and-stereotypes_test.Comp, ejb-name=cdi-alternative-and-stereotypes_test.Comp, container=Default Managed Container)
 INFO - Started Ejb(deployment-id=cdi-alternative-and-stereotypes.Comp, ejb-name=cdi-alternative-and-stereotypes.Comp, container=Default Managed Container)
 INFO - Started Ejb(deployment-id=org.superbiz.cdi.stereotype.StereotypeTest, ejb-name=org.superbiz.cdi.stereotype.StereotypeTest, container=Default Managed Container)
 INFO - Started Ejb(deployment-id=Journey, ejb-name=Journey, container=Default Singleton Container)
 INFO - Deployed Application(path=/opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes)
 INFO - Undeploying app: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes
----
