cdi do básico ao avançado

Post on 11-May-2015

1.982 Views

Category:

Technology

8 Downloads

Preview:

Click to see full reader

TRANSCRIPT

CDI, do básico ao avançado

Thursday, September 5, 13

Alberto Souza

• @alberto_souza

• github.com/asouza

Thursday, September 5, 13

Usar ou criar?

@ManagedBeanpublic class ProdutosBean {

@PostConstruct public void carregaProdutos(){ ProdutoDAO produtos = new ProdutoDAO(); produtos.setConnection(ConnectionFactory.createConnection()); this.lista = dao.lista(); }}

Thursday, September 5, 13

Usar!

@ManagedBeanpublic class ProdutosBean { private ProdutoDAO produtos; private ProdutosBean(ProdutoDAO produtos){ this.produtos = produtos; }

@PostConstruct public void carregaProdutos(){ this.lista = dao.lista(); }}

Thursday, September 5, 13

Injeção de Dependências

• JAVAEE 6/7

• CDI 1.0/1.1

• WELD 2

Thursday, September 5, 13

Uso fácil

@ManagedBeanpublic class ProdutosBean { @Inject private ProdutoDAO produtos; @PostConstruct public void carregaProdutos(){ return dao.lista(); }}

Thursday, September 5, 13

Injeção de Dependências

• E como configura?

Thursday, September 5, 13

Injeção de Dependências

• Não precisa mais

Thursday, September 5, 13

Outro exemplo

class ProdutoDAO{ @Inject private EntityManager em; public List<Produto> lista(){ return em.createQuery("select p from Produto p"); }}

Thursday, September 5, 13

Criação de EntityManager

EntityManagerFactory emf = Persistence. createEntityManagerFactory("loja"); EntityManager em = emf.createEntityManager();

Thursday, September 5, 13

Tem que ensinar

class EntityManagerProducer{private EntityManagerFactory emf = Persistence.createEntityManagerFactory("loja"); @Produces public EntityManager create(){ return factory.createEntityManager(); }}

Thursday, September 5, 13

Escopo?

class EntityManagerProducer{private EntityManagerFactory emf = Persistence.createEntityManagerFactory("loja"); @Produces @RequestScoped public EntityManager create(){ return factory.createEntityManager(); }}

Thursday, September 5, 13

Escopo?

class EntityManagerProducer{private EntityManagerFactory emf = Persistence.createEntityManagerFactory("loja"); //outro método aqui... public void close(@Disposes EntityManager entityManager){ entityManager.close(); }}

Thursday, September 5, 13

Qual é o remetente?

public class FinalizadorDeCompra{ private String remetente; public void envia(){ mailer.send(remente,...); }}

Thursday, September 5, 13

Trocar a injeção de String?

public class FinalizadorDeCompra{ @Inject private String remetente; public void envia(){ mailer.send(remente,...); }}

Thursday, September 5, 13

Só quero para determinada String

public class FinalizadorDeCompra{ @Inject @RemetenteCompra private String remetente; public void envia(){ mailer.send(remente,...); }}

Thursday, September 5, 13

Qualifier

//outras annotations chatas@Qualifier@interface RemetenteCompra{}

Thursday, September 5, 13

Qualifier@ApplicationScoped

class RemetentesProducer { @Produces @RemetenteCompra public String remetenteCompra(){ return properties.getProperty("remetente.compra"); } @Produces @RemetenteNewsletter public String remetenteNewsletter(){ return properties.getProperty("remetente.newsletter"); }}

Thursday, September 5, 13

Indo além

• VRaptor CDI e integração com o Container

Thursday, September 5, 13

Injeção de coisas do container

• Quero usar um EJB, EntityManager...

Thursday, September 5, 13

Injeção de coisas do container

@Componentpublic class ProdutoDAO { @Inject private final EntityManager entityManager;

public void salva(Produto produto) { entityManager.persist(produto); }

Thursday, September 5, 13

Injeção de coisas do container

@Stateless @Componentpublic class ProdutoDAO { @Inject private final EntityManager entityManager;

public void salva(Produto produto) { entityManager.persist(produto); }

Thursday, September 5, 13

Injeção de coisas do container

@Resourcepublic class ProdutosController {

//@EJB @Inject private ProdutoDAO produtoDAO; ...}

Thursday, September 5, 13

EJB?

• Por sinal o DAO é um EJB porque?

Thursday, September 5, 13

EJB?

@Componentpublic class ProdutoDAO { @Inject private final EntityManager entityManager;

@Transactional public void salva(Produto produto) { entityManager.persist(produto); }

Thursday, September 5, 13

Exemplo de uso

• Coloco no interceptor e tá tudo certo!

Thursday, September 5, 13

Componente padrão

@RequestScopedpublic class DefaultPathResolver implements PathResolver { public String pathFor(ResourceMethod method) { String format = resolver.getAcceptFormat();

String suffix = ""; if (format != null && !format.equals("html")) { suffix = "." + format; } //WEB-INF/jsp/controller/metodo.jsp String name = method.getResource().getType().getSimpleName(); String folderName = extractControllerFromName(name); return getPrefix() + folderName + "/" + method.getMethod().getName() + suffix + "."+getExtension(); }

Thursday, September 5, 13

Componente customizado

class CustomPathResolver implements PathResolver{ public String pathFor(ResourceMethod method) { String format = resolver.getAcceptFormat();

String suffix = ""; if (format != null && !format.equals("html")) { suffix = "." + format; } //WEB-INF/resources/controller/metodo.jsp String name = method.getResource().getType().getSimpleName(); String folderName = extractControllerFromName(name); return "WEB-INF/resources" + folderName + "/" + method.getMethod().getName() + suffix + "."+getExtension(); }}

Thursday, September 5, 13

Alternative

@Alternativeclass CustomPathResolver implements PathResolver{ public String pathFor(ResourceMethod method) { String format = resolver.getAcceptFormat();

String suffix = ""; if (format != null && !format.equals("html")) { suffix = "." + format; } //WEB-INF/jsp/controller/metodo.jsp String name = method.getResource().getType().getSimpleName(); String folderName = extractControllerFromName(name); return "WEB-INF/resources" + folderName + "/" + method.getMethod().getName() + suffix + "."+getExtension(); }}

Thursday, September 5, 13

Registra no beans.xml

<?xml version="1.0" encoding="UTF-8"?><beans> <alternatives> <class>br.com.caelum.vraptor.view.CustomPathResolver</class> </alternatives>

</beans>

Thursday, September 5, 13

ilhazinha

• Alternative habilitado só no bean archive

Thursday, September 5, 13

ilhazinha

• VRaptor não enxergava

Thursday, September 5, 13

Prioridade

@Alternative@Priority(Interceptor.Priority.APPLICATION)

class CustomPathResolver implements PathResolver{ public String pathFor(ResourceMethod method) { String format = resolver.getAcceptFormat();

String suffix = ""; if (format != null && !format.equals("html")) { suffix = "." + format; } //WEB-INF/jsp/controller/metodo.jsp String name = method.getResource().getType().getSimpleName(); String folderName = extractControllerFromName(name); return "WEB-INF/resources" + folderName + "/" + method.getMethod().getName() + suffix + "."+getExtension(); }}

Thursday, September 5, 13

Prioridade

• Podemos sempre sobreescrever!

Thursday, September 5, 13

Servidor já injeta Request

• Request do VRaptor é modificado

Thursday, September 5, 13

Aproveita o que já existe

public class VRaptorRequest implements MutableRequest,HttpServletRequest {

private final Hashtable<String, String[]> extraParameters = new Hashtable<String, String[]>();

//qual que ele vai injetar? @Inject private HttpServletRequest request;}

Thursday, September 5, 13

Aproveitamos o existente

@Decoratorpublic class VRaptorRequest implements MutableRequest,HttpServletRequest { @Delegate private HttpServletRequest delegate;

@Override public String getParameter(String name) { if (extraParameters.containsKey(name)) { String[] values = extraParameters.get(name); if (values.length == 1) { return values[0]; } else { return Arrays.toString(values); } } return delegate.getParameter(name); }

Thursday, September 5, 13

Configuramos

<decorators> <class>br.com.caelum.vraptor.http.VRaptorRequest</class> </decorators>

Thursday, September 5, 13

Priority

• Pode usar Priority também!

Thursday, September 5, 13

Injetar Requestspublic class DefaultFormatResolver implements FormatResolver {

private final HttpServletRequest request; private final AcceptHeaderToFormat acceptHeaderToFormat;

@Inject public DefaultFormatResolver(HttpServletRequest request, AcceptHeaderToFormat acceptHeaderToFormat) { this.request = request; this.acceptHeaderToFormat = acceptHeaderToFormat; } public String getAcceptFormat() { String format = request.getParameter("_format"); if (format != null) { return format; }

format = request.getHeader("Accept");

Thursday, September 5, 13

Trocar o request o tempo todo

@Inject private CDIHttpServletRequestFactory requestFactory; @Inject private CDIHttpSessionFactory sessionFactory; public <T> T provideForRequest(RequestInfo request) { //configurando produtores requestFactory.setRequest(request); sessionFactory.setSession(request); return execution.insideRequest(container); }

Thursday, September 5, 13

Notifica o povo

@Inject private Event<HttpServletRequest> eventosDeRequest; public <T> T provideForRequest(RequestInfo requestInfo, Execution<T> execution) { //configurando produtores eventosDeRequest.fire(requestInfo.getRequest()); return execution.insideRequest(container); }

Thursday, September 5, 13

Quero ser notificado

public class CDIHttpServletRequestFactory implements ComponentFactory<HttpServletRequest>{

private HttpServletRequest request;

public void handle(@Observes HttpServletRequest request){ this.request = request; } public HttpServletRequest getInstance(){ return request; }

}

Thursday, September 5, 13

VRaptor já tem @RequestScoped

public @interface RequestScoped {}

Thursday, September 5, 13

Eu sou você!

@Stereotype@javax.enterprise.context.RequestScoped@Namedpublic @interface RequestScoped {}

Thursday, September 5, 13

VRaptor não usa @Inject

@Resourcepublic class ProdutoDAO {

private final EntityManager entityManager;

public CDIResourceComponent(EntityManager entityManager) { this.entityManager = entityManager; }

}

Thursday, September 5, 13

Oxi, sem @Inject?

• Cadê o @Inject?

Thursday, September 5, 13

Pedimos a ele para colocar

public class AddInjectToConstructorExtension implements Extension{

public void processAnnotatedType(@Observes final ProcessAnnotatedType pat) { AnnotatedTypeBuilder builder = new AnnotatedTypeBuilder(); builder.readFromType(pat.getAnnotatedType()); if (hasArgsConstructorAndNoInjection) { Constructor constructor = constructors.get(0); //pulo do gato builder.addToConstructor(constructor,new AnnotationLiteral<Inject>() {}); //trocando a configuração original pat.setAnnotatedType(builder.create()); } }

Thursday, September 5, 13

VRaptor já tem Factories

@Componentpublic class CDIComponent implements ComponentFactory {

private final MyRequestComponent component; public CDIComponent(MyRequestComponent component) { this.component = component; }

public ComponentToBeProduced getInstance() { return new ComponentToBeProduced(); }}

Thursday, September 5, 13

Oxi, e o @Produces?

• E o @Produces?

Thursday, September 5, 13

@Produces em cima do método

public class ComponentFactoryExtension implements Extension{

public void addProduces(@Observes ProcessAnnotatedType pat) { builder.readFromType(pat.getAnnotatedType()); if (ComponentFactory.class.isAssignableFrom(javaClass)) { builder.addToMethod(getInstance,new ProducesAnnotion()); } }}

class ProducesAnnotion extends AnnotationLiteral<Produces>{}

Thursday, September 5, 13

Configura extensão

• META-INF/services/javax.enterprise.inject.spi.Extension

Thursday, September 5, 13

Configura extensão

br.com.caelum.vraptor.ioc.cdi.extensions.AddInjectToConstructorExtension

br.com.caelum.vraptor.ioc.cdi.extensions.ComponentFactoryExtension

Thursday, September 5, 13

E para testar?

• E para testar?

Thursday, September 5, 13

Arquillian

@RunWith(Arquillian.class)public class CDIProviderRegisteringComponentsTest { @Deployment public static JavaArchive createDeployment() { return ShrinkWrap.create(JavaArchive.class) .addClass(DefaultPathResolver.class) .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); }

Thursday, September 5, 13

Arquillian

public static JavaArchive createDeployment() { return ShrinkWrap.create(JavaArchive.class) .addPackage("com.thoughtworks.xstream") }

Thursday, September 5, 13

Problemas

• Falta de controle sobre o container

Thursday, September 5, 13

DeltaSpike

cdiContainer = CdiContainerLoader.getCdiContainer(); cdiContainer.boot();

Thursday, September 5, 13

Controle do escopo

public void start(Class<? extends Annotation> scope) { cdiContainer.getContextControl().startContext(scope); }

Thursday, September 5, 13

Controle do escopo

start(RequestScoped.class); start(SessionScoped.class); //logica stop(SessionScoped.class); stop(RequestScoped.class);

Thursday, September 5, 13

Últimos detalhes

• Funcionalidade com muitos passos

Thursday, September 5, 13

Funcionalidade com vários passos

@Controllerpublic class PagamentoController implements Serializable{

private InformacoesDoComprador info = new InformacoesDoComprador(); @Inject public PagamentoController(Result result) { super(); this.result = result; }

@Post("compra/endereco") public void associaEndereco(String endereco){ info.setEnderecoDeEntrega(endereco); }

Thursday, September 5, 13

Funcionalidade com vários passos

@Controllerpublic class PagamentoController implements Serializable{

//resto que não coube e eu não soube ajeitar. @Post("compra/endereco") public void associaEndereco(String endereco){ info.setEnderecoDeEntrega(endereco); }

@Post("compra/cartao") public void associaCartao(String numero){ //como mantém as informações do comprador? info.setNumeroDoCartao(numero); result.include("dadosComprador",info); }}

Thursday, September 5, 13

Como implementar?

• 2 Maneiras?

Thursday, September 5, 13

Exemplo de implementação

• Stateless?

Thursday, September 5, 13

Outro exemplo

• Stateful?

Thursday, September 5, 13

Meio termo

• Mangue moderado!

Thursday, September 5, 13

Conversation

@Controller @ConversationScopedpublic class PagamentoController implements Serializable{ @Inject private Conversation conversation; @Post("compra/endereco") public void associaEndereco(String endereco){ conversation.begin(); info.setEnderecoDeEntrega(endereco); result.redirectTo("/compra/cartao?cid="+conversation.getId()); }

Thursday, September 5, 13

Conversation

@Controller @ConversationScopedpublic class PagamentoController implements Serializable{ @Inject private Conversation conversation; @Post("compra/cartao") public void associaCartao(String numero){ info.setNumeroDoCartao(numero); //grava e vamo aí.. conversation.end(); result.include("dadosComprador",info); }

Thursday, September 5, 13

Conversation

@Controller @ConversationScopedpublic class PagamentoController implements Serializable{ @Inject public PagamentoController(Result result) { super(); this.result = result; }

Thursday, September 5, 13

E esse result?

• O Result tem que ser passivavel :(

Thursday, September 5, 13

Não mais :)

@Controller @ConversationScopedpublic class PagamentoController implements Serializable{ @Inject public PagamentoController(@TransientReference Result result) { super(); this.result = result; }

Thursday, September 5, 13

Valeu! @alberto_souza

github.com/asouza

Thursday, September 5, 13

top related