blob: 82bd1a0baaad203cfbad327ff3f79d80e3aff5ed [file] [log] [blame]
= 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
----