blob: 1a4ef3d4d790457f3670b58e2ee7e82f899db241 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Trabalhando com Injeção e Qualificadores no CDI: Tutorial do NetBeans IDE</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="description" content="A demonstration of how to use CDI injection and apply qualifiers to Java EE projects using NetBeans IDE 7.0">
<meta name="keywords" content="NetBeans, IDE, integrated development environment,
Contexts and Dependency Injection, CDI, Web Beans, injection, qualifier">
<link rel="stylesheet" type="text/css" href="../../../netbeans.css">
</head>
<body>
<!--
Copyright (c) 2009, 2010, 2011, Oracle and/or its affiliates. All rights reserved.
-->
<h1>Trabalhando com Injeção e Qualificadores no CDI</h1>
<p><em>Contribuição de Andy Gibson</em></p>
<div class="margin-around">
<div class="feedback-box margin-around float-left" style="margin-right:15px">
<h3>Injeção de Dependência e Contextos</h3>
<ol>
<li><a href="cdi-intro.html">Introdução ao CDI e ao JSF 2.0</a></li>
<li><strong>Trabalhando com Injeção e Qualificadores no CDI</strong>
<ul style="margin: 5px 0 0 -2em">
<li><a href="#inject">Injeção: o "I" no CDI</a></li>
<li><a href="#qualifier">Trabalhando com Qualificadores</a></li>
<li><a href="#alternative">Métodos de Injeção Alternativos</a></li>
<li><a href="#seealso">Consulte Também</a></li>
</ul></li>
<li><a href="cdi-validate.html">Aplicando Anotações @Alternative Beans e de Ciclo de Vida</a></li>
<li><a href="cdi-events.html">Trabalhando com Eventos no CDI</a></li>
</ol>
</div>
</div>
<img alt="O conteúdo desta página se aplica ao NetBeans IDE 7.2, 7.3, 7.4 e 8.0" class="stamp" src="../../../images_www/articles/73/netbeans-stamp-80-74-73.png" title="O conteúdo desta página se aplica ao NetBeans IDE 7.2, 7.3, 7.4 e 8.0">
<p>A Injeção de Dependência e Contextos (CDI), especificada por <a href="http://jcp.org/en/jsr/detail?id=299">JSR-299</a>, é parte integrante do Java EE 6 e fornece uma arquitetura que permite aos componentes do Java EE, como os servlets, enterprise beans e JavaBeans, existirem dentro do ciclo de vida de uma aplicação com escopos bem definidos. Além disso, os serviços CDI permitem que os componentes do Java EE, como beans de sessão EJB e beans gerenciados do JavaServer Faces (JSF), sejam injetados e interajam de maneira acoplada flexível, disparando e observando eventos.</p>
<p>Este tutorial tem base no post do blog de Andy Gibson, intitulado <a href="http://www.andygibson.net/blog/index.php/2009/12/22/getting-started-with-cdi-part-2-injection/">Introdução ao CDI parte 2: Injeção</a>. Ele demonstra como é possível utilizar a injeção de CDI para <em>injetar</em> classes ou interfaces em outras classes. Também mostra como aplicar <em>qualificadores </em> CDI ao código, de modo que seja possível especificar qual tipo de classe deverá ser injetada em um determinado ponto de injeção.</p>
<p>O NetBeans IDE fornece um suporte incorporado para a Injeção de Dependência e Contextos, incluindo a opção de geração do arquivo de configuração de CDI <code>beans.xml</code> durante a criação do projeto, do editor e do suporte de navegação para anotações, assim como vários assistentes para a criação de artefatos CDI comumente utilizados.</p>
<br style="clear:left;">
<div class="indent">
<p>Para concluir este tutorial, você precisa dos seguintes recursos e softwares.</p>
<table id="requiredSoftware">
<tbody>
<tr>
<th class="tblheader" scope="col">Software ou Recurso</th>
<th class="tblheader" scope="col">Versão Necessária</th>
</tr>
<tr>
<td class="tbltd1"><a href="https://netbeans.org/downloads/index.html">NetBeans IDE</a></td>
<td class="tbltd1">Versão Java EE 7.2, 7.3, 7.4, 8.0</td>
</tr>
<tr>
<td class="tbltd1"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">JDK (Java Development Kit)</a></td>
<td class="tbltd1">versão 7 ou 8</td>
</tr>
<tr>
<td class="tbltd1"><a href="http://glassfish.dev.java.net/">GlassFish Server</a></td>
<td class="tbltd1">Open Source Edition 3.x ou 4.x</td>
</tr>
<tr>
<td class="tbltd1"><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252FcdiDemo.zip">cdidemo.zip </a></td>
<td class="tbltd1">n/d</td>
</tr>
</tbody>
</table>
<p class="notes"><strong>Observações:</strong></p>
</div>
<ul>
<li>O pacote Java EE do NetBeans inclui também o GlassFish Server Open Source Edition, que é um contêiner compatível com Java EE.</li>
<li>Pode ser feito o download do projeto de amostra de solução para esse tutorial: <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252FcdiDemo2.zip">cdiDemo2.zip</a></li>
</ul>
<br>
<h2 id="inject">Injeção: o "I" do CDI</h2>
<p>O CDI é uma API para injeção de dependências e contextos. Em Seam e Spring, as dependências funcionam, principalmente, nomeando beans e os vinculando aos seus pontos de injeção pelos nomes. Se estiver seguindo este tutorial depois de ter concluído <a href="cdi-intro.html">Introdução a Injeção de Dependência e Contextos e JSF 2.0</a>, você terá, até agora, feito referência apenas a um bean gerenciado por nome, da página do JSF, quando definimos o nome para o bean utilizando a anotação <code>@Named</code>. A atribuição principal da anotação <code>@Named</code> é definir o bean com o objetivo de resolver instruções EL na aplicação, normalmente por meio dos resolvedores JSF EL. A injeção <em>poderia</em> ser executada com o uso de nomes, mas não era assim que a injeção no CDI deveria funcionar, já que o CDI nos proporciona uma maneira muito mais rica de expressar pontos de injeção e os beans a serem injetados neles.</p>
<p>No exemplo a seguir, você cria um <code>ItemProcessor</code> que pega uma lista de itens de uma classe que implementa a interface do <code>ItemDao</code>. Aproveite a anotação <code>@Inject</code> do CDI para demonstrar como é possível <em>injetar</em> um bean em outra classe. O diagrama a seguir retrata o cenário construído neste exercício.</p>
<div class="indent">
<img alt="Diagrama de CDI que mostra os objetos criados neste exercício" class="margin-around" src="../../../images_www/articles/73/javaee/cdi-inject/cdi-diagram-inject.png" title="Use a injeção de CDI para acoplar, livremente, as classes na sua aplicação">
</div>
<p class="tips">DAO significa <em>data access object</em>.</p>
<ol>
<li>Comece extraindo o projeto de início da amostra do arquivo <code>cdiDemo.zip</code> (Consulte a <a href="#requiredSoftware">tabela que lista os recursos necessários</a> acima.) Abra o projeto no IDE escolhendo Arquivo > Abrir Projeto (Ctrl-Shift-O; ⌘-Shift-O no Mac) e, em seguida, selecionando o projeto no seu local no computador.</li>
<li>Clique com o botão direito do mouse no nó do projeto na janela Projetos e escolha Propriedades.</li>
<li>Selecione a categoria Executar e confirme se a instância do GlassFish está selecionada na lista drop-down Servidor. </li>
<li>Crie uma nova classe <code>Item</code> e armazene-a em um novo pacote nomeado <code>exercise2</code>. Clique no botão Novo Arquivo (<img alt="Botão Novo Arquivo" src="../../../images_www/articles/73/javaee/cdi-common/new-file-btn.png">) ou pressione CTRL-N (⌘-N no Mac) para abrir o assistente de Arquivo.</li>
<li>Selecione a categoria Java e, em seguida, a Classe Java. Clique em Próximo.</li>
<li>Informe <strong>Item</strong> como o nome da classe e, em seguida, <strong>exercise2</strong> como o pacote. (O novo pacote é criado após a conclusão do assistente.) <br> <img alt="Assistente de Classe Java" class="margin-around b-all" src="../../../images_www/articles/73/javaee/cdi-inject/java-class-wizard.png" title="Criar uma nova classe Java usando o assistente de Arquivo"></li>
<li>Clique em Finalizar. A nova classe e o novo pacote são gerados e a classe <code>item</code> é aberta no editor.</li>
<li>Crie as propriedades <code>value</code> e <code>limit</code> para o POJO do <code>Item</code> e implemente o método <code>toString()</code>. Adicione o conteúdo a seguir à classe.
<pre class="examplecode">
public class Item {
<strong>private int value;
private int limit;
@Override
public String toString() {
return super.toString() + String.format(&quot; [Value=%d, Limit=%d]&quot;, value,limit);
}</strong>
}</pre></li>
<li>Adicione os métodos getter e setter à classe. Para isso, garanta que o cursor esteja colocado entre a definição de classe (ou seja, entre as chaves da classe) e, em seguida, clique com o botão direito do mouse no editor e escolha Inserir Código (Alt-Insert; Ctrl-I no Mac). Escolha Getter e Setter. <br> <img alt="Pop-up Inserir Código" class="margin-around b-all" src="../../../images_www/articles/73/javaee/cdi-inject/insert-code.png" title="Criar getters e setters usando o pop-up Inserir Código"></li>
<li>Marque a caixa de seleção <code>Item</code> (fazer isso seleciona todas as propriedades contidas na classe). <br> <img alt="Caixa de diálogo Gerar Getters e Setters" class="margin-around b-all" src="../../../images_www/articles/73/javaee/cdi-inject/generate-getters-setters.png" title="Marque a caixa de seleção da classe para selecionar todas as propriedades contidos na classe"></li>
<li>Clique em Gerar. Os métodos getter e setter são gerados para a classe.
<pre class="examplecode">
public class Item {
private int value;
private int limit;
<strong>public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}</strong>
@Override
public String toString() {
return super.toString() + String.format(&quot; [Value=%d, Limit=%d]&quot;, value, limit);
}
}</pre></li>
<li>Crie um construtor que utilize os argumentos <code>value</code> e <code>limit</code>. Novamente, o IDE pode ajudar com isso. Pressione Ctrl-Espaço na definição da classe e escolha a opção "<code>Item(int value, int limit) - generate</code>". <br> <img alt="Lista de autocompletar código exibida no editor" class="margin-around b-all" src="../../../images_www/articles/73/javaee/cdi-inject/generate-constructor.png" title="Pressione Ctrl-Espaço para utilizar os recursos de autocompletar código do editor"> <br> O construtor a seguir é adicionado à classe.
<pre class="examplecode">
public class Item {
<strong>public Item(int value, int limit) {
this.value = value;
this.limit = limit;
}</strong>
private int value;
private int limit;
...</pre></li>
<li>Crie uma interface <code>ItemDao</code> para definir como obtemos a lista de objetos <code>Item</code>. Nesta aplicação de teste, antecipamos o uso de várias implementações, portanto, codificaremos para interfaces.
<p>
Clique no botão Novo Arquivo (<img alt="Botão Novo Arquivo" src="../../../images_www/articles/73/javaee/cdi-common/new-file-btn.png">) ou pressione CTRL-N (⌘-N no Mac) para abrir o assistente de Arquivo.</p></li>
<li>Selecione a categoria Java e, em seguida, selecione Interface Java. Clique em Próximo.</li>
<li>Digite <strong>ItemDao</strong> como o nome da classe e, em seguida, insira <strong>exercise2</strong> como o pacote.</li>
<li>Clique em Finalizar. A nova interface será gerada e aberta no editor.</li>
<li>Adicione um método chamado <code>fetchItems()</code> que retorna uma <code>Lista</code> de objetos <code>Item</code>.
<pre class="examplecode">
public interface ItemDao {
<strong>List&lt;Item&gt; fetchItems();</strong>
}</pre>
(Utilize a dica do editor para adicionar a instrução de importação de <code>java.util.List</code>.)</li>
<li>Crie uma classe <code>ItemProcessor</code>. É a classe principal em que você injetará seus beans e da qual executará o processo. Por enquanto, iniciaremos com a DAO e examinaremos como será feita a sua injeção no nosso bean processador.
<p>
Clique no botão Novo Arquivo (<img alt="Botão Novo Arquivo" src="../../../images_www/articles/73/javaee/cdi-common/new-file-btn.png">) ou pressione CTRL-N (⌘-N no Mac) para abrir o assistente de Arquivo.</p></li>
<li>Selecione a categoria Java e, em seguida, a Classe Java. Clique em Próximo.</li>
<li>Digite <strong>ItemProcessor</strong> como o nome da classe e, em seguida, <strong>exercise2</strong> como o pacote. Clique em Finalizar.
<p>A nova classe é gerada e aberta no editor.</p></li>
<li>Modifique a classe como se segue:
<pre class="examplecode">
@Named
@RequestScoped
public class ItemProcessor {
private ItemDao itemDao;
public void execute() {
List&lt;Item&gt; items = itemDao.fetchItems();
for (Item item : items) {
System.out.println(&quot;Found item &quot; + item);
}
}
}</pre></li>
<li>Corrigir importações. Clique com o botão direito do mouse no editor e selecione Corrigir Importações ou pressione Ctrl-Shift-I (⌘-Shift-I no Mac). <br> <img alt="Caixa de diálogo Corrigir Importações" class="margin-around b-all" src="../../../images_www/articles/73/javaee/cdi-inject/fix-imports.png" title="Clique com o botão direito do mouse no editor e escolha Corrigir Importações para adicionar instruções de importação à classe"></li>
<li>Clique em OK. Instruções de importação para as classes a seguir são necessárias:
<ul>
<li><code>java.util.List</code></li>
<li><code>javax.inject.Named</code></li>
<li><code>javax.enterprise.context.RequestScoped</code></li>
</ul></li>
<li>Comece com um DAO simples que apenas cria uma lista de itens e retorna uma lista fixa de itens. <br><br> Na janela Projetos, clique com o botão direito do mouse no nó de pacote <code>exercise2</code> e escolha Novo > Classe Java. No assistente de Classe Java, nomeie a classe <code>DefaultItemDao</code>. Clique em Finalizar. <img alt="Assistente de Classe Java" class="margin-around b-all" src="../../../images_www/articles/73/javaee/cdi-inject/java-class-wizard2.png" title="Criar uma nova classe Java usando o assistente de Classe Java"></li>
<li>No editor, faça com que <code>DefaultItemDao</code> implemente a interface <code>ItemDao</code> e forneça uma implementação de <code>fetchItems()</code>.
<pre class="examplecode">
public class DefaultItemDao <strong>implements ItemDao</strong> {
<strong>@Override
public List&lt;Item&gt; fetchItems() {
List&lt;Item&gt; results = new ArrayList&lt;Item&gt;();
results.add(new Item(34, 7));
results.add(new Item(4, 37));
results.add(new Item(24, 19));
results.add(new Item(89, 32));
return results;
}</strong>
}</pre>
(Pressione Ctrl-Shift-I (⌘-Shift-I no Mac) para adicionar instruções de importação para <code>java.util.List</code> e <code>java.util.ArrayList</code>.)</li>
<li>Mude para a classe <code>ItemProcessor</code> (pressione Ctrl-Tab). Para injetar o <code>DefaultItemDao</code> no <code>ItemProcessor</code>, adicionamos a anotação <code>javax.inject.Inject</code> ao campo <code>ItemDao</code> para indicar que esse campo é um ponto de injeção.
<pre class="examplecode">
<strong>import javax.inject.Inject;</strong>
...
@Named
@RequestScoped
public class ItemProcessor {
<strong>@Inject</strong>
private ItemDao itemDao;
...
}</pre>
<span class="tips">Utilize o suporte à funcionalidade autocompletar código do editor para adicionar a anotação <code>@Inject</code> e a instrução de importação à classe. Por exemplo, digite "<code>@Inj</code>" e, em seguida, pressione Ctrl-Espaço.</span></li>
<li>Finalmente, precisamos de alguma maneira para chamar o método <code>execute()</code> no <code>ItemProcessor</code>. Podemos executá-lo em um ambiente SE, mas, no momento, o manteremos em uma página JSF. Crie uma nova página chamada <code>process.xhtml</code> que contém um botão para chamar o método <code>execute()</code>. <br><br>Clique no botão Novo Arquivo (<img alt="Botão Novo Arquivo" src="../../../images_www/articles/73/javaee/cdi-common/new-file-btn.png">) ou pressione CTRL-N (⌘-N no Mac) para abrir o assistente de Arquivo.</li>
<li>Selecione a categoria JavaServer Faces e selecione a Página JSF. Clique em Próximo.</li>
<li>Digite <strong>processo</strong> como o nome do arquivo e clique em Finalizar. <br> <img alt="Assistente de Página JSF" class="margin-around b-all" src="../../../images_www/articles/73/javaee/cdi-inject/new-jsf-page.png" title="Criar uma nova página Facelets usando o assistente de arquivo JSF"></li>
<li>No novo arquivo <code>process.xhtml</code>, adicione um botão que esteja conectado ao método <code>ItemProcessor.execute()</code>. Utilizando EL, o nome default para o bean gerenciado é o mesmo que o nome da classe, mas com a primeira letra minúscula (por exemplo., <code>itemProcessor</code>).
<pre class="examplecode">
&lt;h:body&gt;
<strong>&lt;h:form&gt;
&lt;h:commandButton action=&quot;#{itemProcessor.execute}&quot; value=&quot;Execute&quot;/&gt;
&lt;/h:form&gt;</strong>
&lt;/h:body&gt;</pre></li>
<li>Antes de executar o projeto, defina o arquivo <code>process.xhtml</code> como a nova página de boas-vindas no descritor de implantação web do projeto. <br><br> Utilize a caixa de diálogo Ir para Arquivo do IDE para abrir rapidamente o arquivo <code>web.xml</code>. Escolha Navegar > Ir para Arquivo no menu principal do IDE (Alt-Shift-O; Ctrl-Shift-O no Mac) e, em seguida, digite "<code>web</code>". <br> <img alt="Caixa de diálogo Ir para Arquivo" class="margin-around b-all" src="../../../images_www/articles/73/javaee/cdi-inject/go-to-file.png" title="Use a caixa de diálogo Ir para Arquivo para localizar rapidamente um arquivo de projeto"></li>
<li>Clique em OK. Na view XML do arquivo <code>web.xml</code>, faça a alteração a seguir.
<pre class="examplecode">
&lt;welcome-file-list&gt;
&lt;welcome-file&gt;faces/<strong>process.xhtml</strong>&lt;/welcome-file&gt;
&lt;/welcome-file-list&gt;</pre></li>
<li>Clique no botão Executar Projeto (<img alt="Botão Executar Projeto" src="../../../images_www/articles/73/javaee/cdi-common/run-project-btn.png">) na barra de ferramentas principal do IDE. O projeto é compilado e implantado no GlassFish e o arquivo <code>process.xhtml</code> será aberto no browser.</li>
<li>Clique no botão "<code>Execute</code>" que é exibido na página. Volte ao IDE e examine o log do GlassFish Server. O log do servidor é exibido na janela Saída (Ctrl-4; ⌘-4 no Mac) na guia GlassFish Server. Quando o botão é clicado, o log lista os itens da nossa implementação de DAO default. <br> <img alt="Log do GlassFish Server na janela Saída" class="margin-around b-all" src="../../../images_www/articles/73/javaee/cdi-inject/output-window.png" title="Examine o log do servidor na janela Saída do IDE"> <br> <span class="tips">Clique com o botão direito do mouse na janela Saída e escolha Limpar (Ctrl-L; ⌘-L no Mac) para limpar o log. Na imagem acima, o log foi limpo pouco antes de clicar no botão "<code>Execute</code>".</span></li>
</ol>
<p>Criamos uma classe que implementa a interface <code>ItemDao</code> e quando a aplicação foi implantada, nossos beans gerenciados no módulo foram processados pela implementação do CDI (por causa do arquivo <code>beans.xml</code> no módulo). Nossa anotação <code>@Inject</code> especifica que queremos injetar um bean gerenciado nesse campo e a única coisa que sabemos sobre o bean injetável é que ele deve implementar <code>ItemDao</code> ou algum subtipo dessa interface. Nesse caso, a classe <code>DefaultItemDao</code> se adapta perfeitamente.</p>
<p>O que aconteceria se houvesse várias implementações de <code>ItemDao</code> que pudessem ter sido injetadas? O CDI não saberia qual implementação escolher e sinalizaria um erro de tempo de implantação. Para superar isso, seria necessário utilizar um qualificador CDI. Qualificadores são explorados na próxima seção.</p>
<br>
<h2 id="qualifier">Trabalhando com Qualificadores</h2>
<p>Um qualificador CDI é uma anotação que pode ser aplicada no nível da classe para indicar o tipo de bean que a classe é e, no nível do campo (entre outros lugares), para indicar que tipo de bean precisa ser injetado nesse ponto.</p>
<p>Para demonstrar a necessidade de um qualificador na aplicação que estamos construindo, vamos adicionar outra classe DAO à nossa aplicação, que também implementa a interface <code>ItemDao</code>. O diagrama a seguir retrata o cenário que você está construindo neste exercício. O CDI deve conseguir determinar qual implementação de bean deverá ser utilizada em um ponto de injeção. Como há duas implementações de <code>ItemDao</code>, podemos resolver isso criando um qualificador chamado <code>Demo</code>. Em seguida, "marcamos" o bean que queremos utilizar e o ponto de injeção em <code>ItemProcessor</code> com uma anotação <code>@Demo</code>.</p>
<div class="indent">
<img alt="Diagrama de CDI que mostra os objetos criados neste tutorial" class="margin-around" src="../../../images_www/articles/73/javaee/cdi-inject/cdi-diagram-qualify.png" title="Use a injeção e os qualificadores de CDI para acoplar, livremente, as classes na sua aplicação">
</div>
<p>Execute as seguintes etapas.</p>
<ol>
<li>Na janela Projetos, clique com o botão direito do mouse no pacote <code>exercise2</code> e escolha Novo > Classe Java.</li>
<li>No assistente Nova Classe Java, nomeie a nova classe <strong>AnotherItemDao</strong> e clique em Finalizar. A nova classe é gerada e aberta no editor.</li>
<li>Modifique a classe como se segue, de modo que ela implemente a interface <code>ItemDao</code> e defina o método <code>fetchItems()</code> da interface.
<pre class="examplecode">
public class AnotherItemDao <strong>implements ItemDao</strong> {
<strong>@Override
public List&lt;Item&gt; fetchItems() {
List&lt;Item&gt; results = new ArrayList&lt;Item&gt;();
results.add(new Item(99, 9));
return results;
}</strong>
}</pre>
<p>Certifique-se de adicionar instruções de importação para <code>java.util.List</code> e <code>java.util.ArrayList</code>. Para isso, clique com o botão direito do mouse no editor e escolha Corrigir Importações ou pressione Ctrl-Shift-I (⌘-Shift-I no Mac).</p>
<p>
Agora que há duas classes que implementam o <code>ItemDao</code>, a escolha não está tão clara com relação a em qual bean queremos injetar.</p></li>
<li>Clique no botão Executar Projeto (<img alt="Botão Executar Projeto" src="../../../images_www/articles/73/javaee/cdi-common/run-project-btn.png">) para executar o projeto. Observe que o projeto agora falha na implantação.
<p class="tips">Provavelmente, você só precisa salvar o arquivo porque o IDE implantará o projeto automaticamente, visto que a opção Implantar ao Salvar está ativada por default.</p></li>
<li>Examine o log do servidor na janela Saída (Ctrl-4; ⌘-4 no Mac). Será exibida uma mensagem de erro semelhante ao seguinte.
<pre class="examplecode">Caused by: org.jboss.weld.DeploymentException: Injection point has ambiguous dependencies.
Injection point: field exercise2.ItemProcessor.itemDao;
Qualifiers: [@javax.enterprise.inject.Default()];
Possible dependencies: [exercise2.DefaultItemDao, exercise2.AnotherItemDao]</pre>
<p class="tips">Para quebrar o texto em várias linhas na janela Saída, clique com o botão direito do mouse e escolha Quebrar texto. Isso elimina a necessidade de rolar horizontalmente.</p>
<p>
Weld, a implementação para CDI, nos proporciona um erro de dependência ambígua, o que significa que não pode determinar qual bean utilizar para o ponto de injeção determinado. A maioria dos erros, se não todos, que podem ocorrer com relação à injeção CDI em Weld são informados no momento da implantação, até mesmo se os beans ativados para passivação estiverem sem uma implementação <code>Serializable</code>.</p>
<p>
Poderíamos tornar nosso campo <code>itemDao</code> no <code>ItemProcessor</code> um tipo específico que corresponde a um dos tipos de implementação (<code>AnotherItemDao</code> ou <code>DefaultItemDao</code>), já que corresponderia, em seguida, a um e apenas um tipo de classe. No entanto, perderíamos os benefícios da codificação para uma interface e seria mais difícil alterar as implementações sem alterar o tipo de campo. Uma solução melhor seria, portanto, examinarmos os qualificadores de CDI.</p>
<p>
Quando o CDI inspeciona um ponto de injeção para encontrar um bean adequado para injetar, não leva em conta apenas o tipo de classe, mas também todos os qualificadores. Sem saber disso, já utilizamos um qualificador que é o qualificador default chamado <code>@Any</code>. Vamos criar um qualificador <code>@Demo</code> que podemos aplicar à nossa implementação de <code>DefaultItemDao</code> e também ao ponto de injeção em <code>ItemProcessor</code>.</p>
<p>
O IDE fornece um assistente que permite gerar qualificadores CDI.</p></li>
<li>Clique no botão Novo Arquivo (<img alt="Botão Novo Arquivo" src="../../../images_www/articles/73/javaee/cdi-common/new-file-btn.png">) ou pressione CTRL-N (⌘-N no Mac) para abrir o assistente de Arquivo.</li>
<li>Selecione a categoria Injeção de Dependência e Contexto e, em seguida, selecione Tipo de Qualificador. Clique em Próximo.</li>
<li>Digite <strong>Demo</strong> como o nome da classe e, em seguida, <strong>exercise2</strong> como o pacote.</li>
<li>Clique em Finalizar. O novo qualificador <code>Demo</code> será aberto no editor.
<pre class="examplecode">
package exercise2;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
*
* @author nbuser
*/
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface Demo {
}</pre>
<p>Em seguida, você adicionará este qualificador à implementação DAO default no nível da classe.</p>
</li>
<li>Altere para <code>DefaultItemDao</code> no editor (pressione Ctrl-Tab) e, em seguida, digite "<code>@Demo</code>" acima da definição da classe.
<pre class="examplecode">
<strong>@Demo</strong>
public class DefaultItemDao implements ItemDao {
@Override
public List&lt;Item&gt; fetchItems() {
List&lt;Item&gt; results = new ArrayList&lt;Item&gt;();
results.add(new Item(34, 7));
results.add(new Item(4, 37));
results.add(new Item(24, 19));
results.add(new Item(89, 32));
return results;
}
}</pre>
<span class="tips">Depois de digitar "<code>@</code>", pressione Ctrl-Espaço para chamar sugestões da funcionalidade autocompletar código. O editor reconhece o qualificador <code>Demo</code> e lista <code>@Demo</code> como uma opção para a funcionalidade autocompletar código.</span></li>
<li>Clique no botão Executar Projeto (<img alt="Botão Executar Projeto" src="../../../images_www/articles/73/javaee/cdi-common/run-project-btn.png">) para executar o projeto. O projeto será compilado e implantado sem erros.
<p class="notes"><strong>Observação.</strong> Para esta modificação talvez você precise executar explicitamente o projeto para reimplantar a aplicação, em vez de implantar incrementalmente as alterações.</p></li>
<li>No browser, clique no botão "<code>Execute</code>", retorne para o IDE e examine o log do servidor na janela Saída. Você verá a seguinte saída.
<pre class="examplecode">INFO: Found item exercise2.Item@1ef62a93 [Value=99, Limit=9]</pre>
<p>A saída lista o item da classe <code>AnotherItemDao</code>. Lembre-se de que anotamos a implementação <code>DefaultItemDao</code>, mas não o ponto de injeção em <code>ItemProcessor</code>. Adicionando o qualificador <code>@Demo</code> à implementação DAO default, tornamos a outra implementação uma correspondência mais adequada para o ponto de injeção, pois houve coincidência no tipo e no qualificador. O <code>DefaultItemDao</code> tem, no momento, o qualificador <code>Demo</code>, que não está no ponto de injeção, o que o torna, portanto, menos adequado.</p>
<p>Em seguida, você adicionará a anotação <code>@Demo</code> ao ponto de injeção em <code>ItemProcessor</code>.</p></li>
<li>Altere para <code>ItemProcessor</code> no editor (pressione Ctrl-Tab) e, em seguida, faça a seguinte alteração.
<pre class="examplecode">
@Named
@RequestScoped
public class ItemProcessor {
@Inject <strong>@Demo</strong>
private ItemDao itemDao;
public void execute() {
List&lt;Item&gt; items = itemDao.fetchItems();
for (Item item : items) {
System.out.println("Found item " + item);
}
}
}</pre></li>
<li>No browser, clique no botão "<code>Execute</code>", retorne para o IDE e examine o log do servidor na janela Saída. Você verá, novamente, a saída da implementação default (<code>DefaultItemDao</code>).
<pre class="examplecode">
INFO: Found item exercise2.Item@7b3640f1 [Value=34, Limit=7]
INFO: Found item exercise2.Item@26e1cd69 [Value=4, Limit=37]
INFO: Found item exercise2.Item@3274bc70 [Value=24, Limit=19]
INFO: Found item exercise2.Item@dff76f1 [Value=89, Limit=32]</pre>
<p>Isso ocorre porque agora estamos fazendo a correspondência com base em qualificadores do tipo <em>and</em>, e <code>DefaultItemDao</code> é o único bean com o tipo correto e a anotação <code>@Demo</code>.</p></li>
</ol>
<br>
<h2 id="alternative">Métodos de Injeção Alternativos</h2>
<p>Há várias maneiras de definir um ponto de injeção na classe injetada. Até agora, anotamos os campos que fazem referência ao objeto injetado. Não é necessário fornecer getters e setters para a injeção de campo. Se quisermos criar beans gerenciados imutáveis com campos finais, poderemos utilizar a injeção no construtor anotando-o com a anotação <code>@Inject</code>. Em seguida, poderemos aplicar quaisquer anotações aos parâmetros do construtor para qualificar os beans para injeção. (Claro, cada parâmetro tem um tipo que pode ajudar na qualificação de beans para injeção). Um bean pode ter apenas um construtor com pontos de injeção definidos, mas pode implementar mais de um construtor.</p>
<div class="indent">
<pre class="examplecode">
@Named
@RequestScoped
public class ItemProcessor {
private final ItemDao itemDao;
@Inject
public ItemProcessor(@Demo ItemDao itemDao) {
this.itemDao = itemDao;
}
}</pre>
</div>
<p>Também podemos chamar um método de inicialização que pode ser passado a um bean a ser injetado.</p>
<div class="indent">
<pre class="examplecode">
@Named
@RequestScoped
public class ItemProcessor {
private ItemDao itemDao;
@Inject
public void setItemDao(@Demo ItemDao itemDao) {
this.itemDao = itemDao;
}
}</pre>
</div>
<p>Embora no caso acima tenhamos utilizado o método setter para a inicialização, podemos criar qualquer método e utilizá-lo para a inicialização com quantos beans quisermos na chamada do método. Também podemos ter vários métodos de inicialização em um bean.</p>
<div class="indent">
<pre class="examplecode">
@Inject
public void initBeans(@Demo ItemDao itemDao, @SomeQualifier SomeType someBean) {
this.itemDao = itemDao;
this.bean = someBean;
}</pre>
</div>
<p>As mesmas regras se aplicam à correspondência de beans, independente de como o ponto de injeção é definido. O CDI tentará encontrar a melhor correspondência, com base no tipo e nos qualificadores, e haverá falha na implantação se houver vários beans correspondentes ou nenhum bean correspondente para um ponto de injeção.</p>
<div class="feedback-box">
<a href="/about/contact_form.html?to=3&amp;subject=Feedback:%20Working%20with%20Injection%20and%20Qualifiers%20in%20CDI">Enviar Feedback neste Tutorial</a>
</div>
<br style="clear:both;">
<h2 id="seealso">Consulte Também</h2>
<p>Vá para o próximo artigo desta série sobre Injeção de Dependência e Contextos:</p>
<ul>
<li><a href="cdi-validate.html">Aplicando Anotações @Alternative Beans e de Ciclo de Vida</a></li>
</ul>
<p>Para obter mais informações sobre o CDI e o Java EE, consulte os recursos a seguir.</p>
<ul>
<li><a href="cdi-intro.html">Introdução à Injeção de Dependência e Contextos e JSF 2.0</a></li>
<li><a href="javaee-gettingstarted.html">Conceitos Básicos sobre Aplicações do Java EE</a></li>
<li><a href="http://blogs.oracle.com/enterprisetechtips/entry/using_cdi_and_dependency_injection">Dica Técnica do Enterprise: Utilizando Injeção de Dependência e de CDI para Java em uma Aplicação JSF 2.0</a></li>
<li><a href="http://download.oracle.com/javaee/6/tutorial/doc/gjbnr.html">O Tutorial do Java EE 6, Parte V: Injeção de Dependência e Contextos para a Plataforma Java EE</a></li>
<li><a href="http://jcp.org/en/jsr/detail?id=299">JSR 299: Especificação para Injeção de Dependência e Contextos</a></li>
</ul>
</body>
</html>