Download - Use CDI em seus projetos Java !
Porque você deveria usarCDI em todos os seus projetos Java
CDI
@sergio_caelumsergiolopes.org
CDI
(
CDI
CDI
CDI
public class ProdutoDao { public void salvar(Produto produto) {
entityManager.persist(produto); }}
public class ProdutoDao { public void salvar(Produto produto) { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpa"); EntityManager entityManager = factory.createEntityManager();
entityManager.persist(produto); }}
CDI
public class ProdutoDao {
public void salvar(Produto produto) { entityManager.persist(produto); }}
public class ProdutoDao { private EntityManager entityManager;
public ProdutoDao(EntityManager em) { this.entityManager = em; }
public void salvar(Produto produto) { entityManager.persist(produto); }}
public class ProdutoDao { private EntityManager entityManager; // recebo dependência pronta public ProdutoDao(EntityManager em) { this.entityManager = em; }
// uso dependência public void salvar(Produto produto) { entityManager.persist(produto); }}
injeção dedependências!
injeção dedependências!
inversão de controle.
injeção dedependências!
separação de responsabilidades.inversão de controle.
)
CDI
especificação cdiimplementação weld
public class ProdutoDao { private EntityManager entityManager;
public ProdutoDao(EntityManager em) { this.entityManager = em; }
public void salvar(Produto produto) { entityManager.persist(produto); }}
public class ProdutoDao { private EntityManager entityManager; @Inject public ProdutoDao(EntityManager em) { this.entityManager = em; }
public void salvar(Produto produto) { entityManager.persist(produto); }}
public class ProdutoDao {
@Inject private EntityManager entityManager;
public void salvar(Produto produto) { entityManager.persist(produto); }}
CDI
injeção com @Inject
public class ProdutoController {
private ProdutoDao dao; public void insere() { Produto produto = // pega dados no request dao.salvar(produto); }}
public class ProdutoController {
@Inject private ProdutoDao dao; public void insere() { Produto produto = // pega dados no request dao.salvar(produto); }}
injeção fácil!
e oEntityManager?
CDI
métodos produtores
public class JPAUtil {
public EntityManager criaEM() {
}}
public class JPAUtil {
public EntityManager criaEM() { EntityManagerFactory factory = Persistence .createEntityManagerFactory("jpa"); return factory.createEntityManager(); }}
public class JPAUtil {
public EntityManager criaEM() { EntityManagerFactory factory = Persistence .createEntityManagerFactory("jpa"); return factory.createEntityManager(); }}
public class JPAUtil {
@Produces public EntityManager criaEM() { EntityManagerFactory factory = Persistence .createEntityManagerFactory("jpa"); return factory.createEntityManager(); }}
quando criar oEntityManager?
public class JPAUtil {
@Produces @RequestScoped public EntityManager criaEM() { EntityManagerFactory factory = Persistence .createEntityManagerFactory("jpa"); return factory.createEntityManager(); }}
mas e afactory?
public class JPAUtil {
@Produces @RequestScoped public EntityManager criaEM(){ return factory.createEntityManager(); }}
public class JPAUtil {
@Produces public EntityManagerFactory criaFactory() { return Persistence.createEntityManagerFactory("jpa"); } @Produces @RequestScoped public EntityManager criaEM(){ return factory.createEntityManager(); }}
public class JPAUtil {
@Produces public EntityManagerFactory criaFactory() { return Persistence.createEntityManagerFactory("jpa"); } @Produces @RequestScoped public EntityManager criaEM(){ return factory.createEntityManager(); }}
public class JPAUtil {
@Produces public EntityManagerFactory criaFactory() { return Persistence.createEntityManagerFactory("jpa"); } @Produces @RequestScoped public EntityManager criaEM(EntityManagerFactory factory){ return factory.createEntityManager(); }}
public class JPAUtil {
@Produces @ApplicationScoped public EntityManagerFactory criaFactory() { return Persistence.createEntityManagerFactory("jpa"); } @Produces @RequestScoped public EntityManager criaEM(EntityManagerFactory factory){ return factory.createEntityManager(); }}
e quemfecha?
public class JPAUtil {
public void fechaEM(EntityManager em) { em.close(); }
}
public class JPAUtil {
public void fechaEM(@Disposes EntityManager em) { em.close(); }
}
gerenciamentodo ciclo de vida!
e mais de umbanco de dados?
public class JPAUtil {
@Produces @ApplicationScoped public EntityManagerFactory criaFactory1() {}
@Produces @RequestScoped public EntityManager criaEM1(EntityManagerFactory factory){}
}
public class JPAUtil {
@Produces @ApplicationScoped public EntityManagerFactory criaFactory1() {}
@Produces @RequestScoped public EntityManager criaEM1(EntityManagerFactory factory){}
@Produces @ApplicationScoped public EntityManagerFactory criaFactory2() {}
@Produces @RequestScoped public EntityManager criaEM2(EntityManagerFactory factory){} }
public class JPAUtil {
@Produces @ApplicationScoped public EntityManagerFactory criaFactory1() {}
@Produces @RequestScoped public EntityManager criaEM1(EntityManagerFactory factory){}
@Produces @ApplicationScoped public EntityManagerFactory criaFactory2() {}
@Produces @RequestScoped public EntityManager criaEM2(EntityManagerFactory factory){} }
?
CDI
qualifiers
public class JPAUtil {
@Produces @ApplicationScoped @Geral public EntityManagerFactory criaFactory1() {}
@Produces @RequestScoped public EntityManager criaEM1(EntityManagerFactory factory){}
@Produces @ApplicationScoped @Diretor public EntityManagerFactory criaFactory2() {}
@Produces @RequestScoped public EntityManager criaEM2(EntityManagerFactory factory){} }
public class JPAUtil {
@Produces @ApplicationScoped @Geral public EntityManagerFactory criaFactory1() {}
@Produces @RequestScoped public EntityManager criaEM1(@Geral EntityManagerFactory f){}
@Produces @ApplicationScoped @Diretor public EntityManagerFactory criaFactory2() {}
@Produces @RequestScoped public EntityManager criaEM2(@Diretor EntityManagerFactory f){} }
@Retention(RUNTIME)public @interface Diretor {}
@Retention(RUNTIME)public @interface Geral {}
@Qualifier@Retention(RUNTIME)public @interface Diretor {}
@Qualifier@Retention(RUNTIME)public @interface Geral {}
public class ProdutoDao {
@Inject private EntityManager entityManager;
public void salvar(Produto produto) { entityManager.persist(produto); }}
public class ProdutoDao {
@Inject @Geral private EntityManager entityManager;
public void salvar(Produto produto) { entityManager.persist(produto); }}
public class JPAUtil {
@Produces @ApplicationScoped @Geral public EntityManagerFactory criaFactory1() {}
@Produces @RequestScoped @Geral public EntityManager criaEM1(@Geral EntityManagerFactory f){}
@Produces @ApplicationScoped @Diretor public EntityManagerFactory criaFactory2() {}
@Produces @RequestScoped @Diretor public EntityManager criaEM2(@Diretor EntityManagerFactory f){} }
public class BackupDeTudo {
public void backupBDs() {
}}
public class BackupDeTudo {
@Inject @Any private Instance<EntityManager> todosEntityMangers; public void backupBDs() {
}}
public class BackupDeTudo {
@Inject @Any private Instance<EntityManager> todosEntityMangers; public void backupBDs() { for (EntityManager em : todosEntityMangers) { // ... } }}
múltiplosbeans!
quem controlatransações?
public class ProdutoDao { @Inject private EntityManager entityManager; public void salvar(Produto produto) { entityManager.getTransaction().begin(); entityManager.persist(produto); entityManager.getTransaction().commit(); }
}
public class ProdutoDao { @Inject private EntityManager entityManager; public void salvar(Produto produto) { entityManager.getTransaction().begin(); entityManager.persist(produto); entityManager.getTransaction().commit(); } public void apagar(Produto produto) { entityManager.getTransaction().begin(); entityManager.remove(produto); entityManager.getTransaction().commit(); }}
public class ProdutoDao { @Inject private EntityManager entityManager; public void salvar(Produto produto) { entityManager.getTransaction().begin(); entityManager.persist(produto); entityManager.getTransaction().commit(); } public void apagar(Produto produto) { entityManager.getTransaction().begin(); entityManager.remove(produto); entityManager.getTransaction().commit(); }}
public class ProdutoController {
@Inject private ProdutoDao dao; public void substitui() { dao.salvar(produtoNovo); dao.apagar(produtoAntigo); }}
CDI
interceptadores
public class ProdutoController {
@Inject private ProdutoDao dao; @Transacional public void substitui() { dao.salvar(produtoNovo); dao.apagar(produtoAntigo); }}
@InterceptorBinding@Retention(RUNTIME)public @interface Transacional { }
public class ProdutoDao { @Inject private EntityManager entityManager; public void salvar(Produto produto) { entityManager.persist(produto); } public void apagar(Produto produto) { entityManager.remove(produto); }}
@Interceptor @Transacionalpublic class TransacionalInterceptor {
}
@Interceptor @Transacionalpublic class TransacionalInterceptor {
@AroundInvoke public Object intercept(InvocationContext ctx) {
}}
@Interceptor @Transacionalpublic class TransacionalInterceptor {
@AroundInvoke public Object intercept(InvocationContext ctx) { // ... antes da lógica
Object resultado = ctx.proceed();
// ... depois da lógica return resultado; }}
@Interceptor @Transacionalpublic class TransacionalInterceptor {
@Inject private EntityManager em;
@AroundInvoke public Object intercept(InvocationContext ctx) { em.getTransaction().begin();
Object resultado = ctx.proceed();
em.getTransaction().commit(); return resultado; }}
<beans> <interceptors> <class> br.com.caelum.TransacionalInterceptor </class> </interceptors></beans>
maisencapsulado!
um processo decompra complexo
public class Pagamento {
public void efetuaCobranca() { // ... comunica com Cielo }}
public class Estoque {
public void reservaMercadoria() { // ... reserva produto no estoque }}
public class Notificacoes {
public void notificaCompra() { // envia email confirmando pro usuario }}
public class FinalizaCompraController {
public void finalizaCompra() {
}}
public class FinalizaCompraController {
@Inject private Pagamento pagamento;
public void finalizaCompra() { pagamento.efetuaCobranca();
}}
public class FinalizaCompraController {
@Inject private Pagamento pagamento; @Inject private Estoque estoque;
public void finalizaCompra() { pagamento.efetuaCobranca(); estoque.reservaMercadoria();
}}
public class FinalizaCompraController {
@Inject private Pagamento pagamento; @Inject private Estoque estoque; @Inject private Notificacoes notificacoes; public void finalizaCompra() { pagamento.efetuaCobranca(); estoque.reservaMercadoria(); notificacoes.notificaCompra(); }}
como desacoplaro processo?
CDI
eventos
public class FinalizaCompraController {
public void finalizaCompra() {
}}
public class FinalizaCompraController {
public void finalizaCompra() { Compra compra = new Compra(produto, cliente);
}}
public class FinalizaCompraController {
@Inject @Any private Event<Compra> eventoCompra; public void finalizaCompra() { Compra compra = new Compra(produto, cliente);
}}
public class FinalizaCompraController {
@Inject @Any private Event<Compra> eventoCompra; public void finalizaCompra() { Compra compra = new Compra(produto, cliente); eventoCompra.fire(compra); }}
public class Pagamento {
public void efetuaCobranca(Compra c) { // ... comunica com Cielo }}
public class Pagamento {
public void efetuaCobranca(@Observes Compra c) { // ... comunica com Cielo }}
public class Pagamento {
public void efetuaCobranca(@Observes Compra c) { // ... comunica com Cielo }}public class Estoque {
public void reservaMercadoria(@Observes Compra c) { // ... reserva produto no estoque }}
maisdesacoplado!
não quero cobraro cartão em teste
public class Pagamento {
public void efetuaCobranca(@Observes Compra c) {WebServiceCielo.cobraDeVerdade(c.getCartao());
}}
CDI
alternatives
public class PagamentoDeVerdade {
}
public class PagamentoDeMentira {
}
public class PagamentoDeVerdade {
public void efetuaCobranca(@Observes Compra c) {
}}
public class PagamentoDeMentira {
public void efetuaCobranca(@Observes Compra c) {
}}
public class PagamentoDeVerdade {
public void efetuaCobranca(@Observes Compra c) {WebServiceCielo.cobraDeVerdade(c.getCartao());
}}
public class PagamentoDeMentira {
public void efetuaCobranca(@Observes Compra c) { LogDeTeste.fariaUmaCompraAqui(); }}
public class PagamentoDeVerdade implements Pagamento {
public void efetuaCobranca(@Observes Compra c) {WebServiceCielo.cobraDeVerdade(c.getCartao());
}}
public class PagamentoDeMentira implements Pagamento {
public void efetuaCobranca(@Observes Compra c) { LogDeTeste.fariaUmaCompraAqui(); }}
public class PagamentoDeVerdade implements Pagamento {
public void efetuaCobranca(@Observes Compra c) {WebServiceCielo.cobraDeVerdade(c.getCartao());
}}
@Alternativepublic class PagamentoDeMentira implements Pagamento {
public void efetuaCobranca(@Observes Compra c) { LogDeTeste.fariaUmaCompraAqui(); }}
<beans> <alternatives> <class> br.com.caelum.PagamentoDeMentira </class> </alternatives></beans>
CDI
extensions spi
posso estendero próprio CDI!
public class HelloExtension implements Extension {
}
public class HelloExtension implements Extension {
<T> void hiBean(@Observes ProcessAnnotatedType<T> pat) {
}}
public class HelloExtension implements Extension {
<T> void hiBean(@Observes ProcessAnnotatedType<T> pat) { Class<T> clazz = pat.getAnnotatedType().getJavaClass(); System.out.println("Hi! " + clazz.getName()); }}
META-INF/services/javax.enterprise.inject.spi.Extension
br.com.caelum.HelloExtension
posso modificaros beans do CDI
public class ModulosOpcionaisExtension implements Extension{
}
public class ModulosOpcionaisExtension implements Extension{
<T> void bloqueia(@Observes ProcessAnnotatedType<T> pat) {
}
}
public class ModulosOpcionaisExtension implements Extension{
<T> void bloqueia(@Observes ProcessAnnotatedType<T> pat) { Class<T> clazz = pat.getAnnotatedType().getJavaClass(); String packageName = clazz.getPackage().getName();
}
}
public class ModulosOpcionaisExtension implements Extension{
<T> void bloqueia(@Observes ProcessAnnotatedType<T> pat) { Class<T> clazz = pat.getAnnotatedType().getJavaClass(); String packageName = clazz.getPackage().getName(); if (deveSerBloqueado(packageName)) {
} }
private boolean deveSerBloqueado(String pkg) { // TODO ler um arquivo de config de módulos bloqueados? return pkg.startsWith("br.com.caelum.entrega"); }}
public class ModulosOpcionaisExtension implements Extension{
<T> void bloqueia(@Observes ProcessAnnotatedType<T> pat) { Class<T> clazz = pat.getAnnotatedType().getJavaClass(); String packageName = clazz.getPackage().getName(); if (deveSerBloqueado(packageName)) { pat.veto(); } }
private boolean deveSerBloqueado(String pkg) { // TODO ler um arquivo de config de módulos bloqueados? return pkg.startsWith("br.com.caelum.entrega"); }}
dá pra estendermuito mais
decoratorsstereotypesinjection pointscustom scopesconversation scopemais de extensions
CDI+
Você deveria usarCDI em todos os seus projetos Java!
CDI
Obrigado!@sergio_caelum