Escolar Documentos
Profissional Documentos
Cultura Documentos
br
Note que a classe DespesaService possui o objeto despesaDAO, construindo esse objeto diretamente na classe com o operador new. Observe tambm que os mtodos dessa classe usam esse objeto em seus mtodos. Dizemos que a classe DespesaService depende da classe DespesaDAO. Em outras palavras, a classe DespesaDAO dependncia de DespesaService, pois sem a classe DAO a classe Service no conseguiria fazer o seu trabalho. Sem novidades at o momento, mas qual o problema de fazer isso? Tem alguma coisa errada? A resposta obviamente no, no tem problema nenhum, enquanto meu sistema bem pequenininho... porm, se ele for crescendo, ganhando mais funcionalidades, mais casos de uso, e o usurio ir pedindo cada vez mais coisas, fato super comum nos sistemas, no tenha dvida que eu ter problemas pela frente. O que aconteceria se agora com o sistema muito maior, com dezenas de classes Service, vrias dessas classes tendo DespesaDAO como dependncia, precisar fazer alguma modificao no DAO. Ser que essa modificao seria segura? Causaria algum problema em outra parte que usa essa dependncia?
DespesaDAO.java package public dao; class DespesaDAO { public void gravar(){ System.out .println("gravando..."); } public void remover(){ System.out .println("removendo..."); } public void alterar(){ System.out .println("alterando..."); }
Vamos aos conceitos, Inverso de Controle (IoC) um padro de projetos que retira do implementador o controle de construo de criao dos objetos. Injeo de Dependncia (DI) uma das formas de se realizar a Inverso de Controle, onde a dependncia de uma determinada classe injetada de alguma forma. Se no sou eu que crio os objetos, quem cria? Como funciona essa injeo de dependncias? A Inverso de controle j usada um algum tempo, sendo o Spring um dos frameworks que despontou na frente com Injeo de Dependncia dentre outras funcionalidades, que facilita e torna mais produtivo o desenvolvimento de software. Sendo assim, pode-se usar o Spring para injetar as dependncias na suas classes. E ento, quem cria minhas classes? o Spring! Somente ele faz isso? At pouco tempo no existia nenhuma forma oficial em Java para realizar esse trabalho, no existia um padro, somente agora com o JEE6, essas funcionalidades esto disponveis diretamente nos Servidores de Aplicao. Quer dizer que voc pode fazer sua aplicao, usando Injeo de Dependncia, e um Servidor de Aplicao JEE6 ir injetar suas dependncias. Quais so esses Servidores? Ora, o Glassfish 3 e o JbossAS 6. Tomcat faz? No, mas isso no significa que no vou poder usar Inverso de Controle nas minhas aplicaes que rodam no Tomcat. A diferena que quando eu uso JbossAS6 ou Glassfish 3, no precisa fazer absolutamente nada para ativar essas funcionalidades, o prprio continer capaz de realizar a Injeo, e no caso do Tomcat, a aplicao dever ser autocontida, ou seja, a aplicao dever fazer a Injeo por si mesma, ter que trazer consigo as bibliotecas e ser toda configurada apropriadamente.
Uma vez estabelecido as funcionalidades e distribudo em interfaces, devemos ter as implementaes. Vamos modelar uma implementao para cada interface. Temos a classe DespesaServiceNacional implementando a interface DespesaService. Essa classe tem as regras de negocio para manipular as despesas em mbito nacional, (faz abatimentos no imposto de renda, dentre outras regras). Temos tambm a classe JDBCDespesaDAO que faz a manipulao do banco de dados usando JDBC. DespesaControle representa a camada de Controle, onde recebe as solicitaes da camada de visualizao e delega para o service realizar as regras de negocio.
Hands on
Vamos implementar e ver como tudo isso funciona. Nosso exemplo ser implementado no Eclipse IDE Helios, com JBoss Tools, E JBossAS6 como servidor de aplicao. Primeiramente crie um Dynamic Web Project com o nome Financeiro. Defina o JBoss como Target runtime, Dynamic web module version 3.0.
Marque as opes CDI (Context and Dependency Injection) DespesaService.java package public servico; interface DespesaService { public void gravar(); public void remover(); public void alterar();
DespesaDAO.java Avance at a etapa a seguir, verifique se esta marcada a opo de criao do arquivo beans.xml, ele requisito para ativar a funcionalidade de Injeo de Dependncia. package public dao; interface DespesaDAO { public void gravar(); public void remover(); publicvoidalterar();
DespesaServiceNacional.java package servico.impl; import javax.inject.Inject; import servico.DespesaService; import dao.DespesaDAO; public Escolha a opo para usar diretamente do Servidor de Aplicao: a biblioteca JSF class DespesaServiceNacional implements DespesaService{ @Inject DespesaDAO despesaDao; public void gravar(){ System. out .println("gravando nacional"); despesaDao.gravar(); } public void remover(){ System.out .println("removendo nacional"); despesaDao.remover(); } Com isso temos nosso Projeto pronto pra usar DI. O prximo passo criar as interfaces DespesaService e DespesaDAO, e seguidamente as suas implementaes (DespesaServiceNacional e JDBCDespesaDAO respectivamente). Criamos tambm a classe de controle DespesaControle que ser o ManagedBean e um xhtml para poder solicitar os servios. public void alterar(){ System.out .println("alterando nacional"); despesaDao.alterar(); } }
JDBCDespesaDAO.java package dao.jdbc; import dao.DespesaDAO; public class JDBCDespesaDAO implements DespesaDAO { public void gravar(){ System. out .println("gravando JDBC..."); } public void remover(){ System. out .println("removendo JDBC..."); } public void alterar(){ System. out .println("alterando JDBC..."); } }
DespesaControle.java package import import import import controle; javax.enterprise.context.RequestScoped; javax.inject.Inject; javax.inject.Named; servico.DespesaService;
Onde antes voc faria : JDBCDespesaDAO despesaDao = new JDBCDespesaDAO(); Temos agora: @Inject DespesaDAO despesaDao;
@RequestScoped @Named public class DespesaControle { @Inject DespesaService despesaService; public void gravar(){ despesaService.gravar(); } public void remover(){ despesaService.remover(); } public void alterar(){ despesaService.alterar(); } }
Temos na classe de controle outro ponto de injeo, onde solicitado que seja injetado um objeto que implementa a interface DespesaService(no caso DespesaServiceNacional, pois a nica implementao disponvel). Temos tambm duas anotaes novas @RequestScoped e @Named, Como definimos anteriormente a classe de controle o ManagedBean, que responsvel por receber as solicitaes da visualizao e delegar ao Service. Para que os mtodos do Controle possam ser visveis na visualizao, adicionamos a anotao @Named, semelhante a anotao JSF2 @MangedBean. A anotao @RequestScoped define o escopo do ManagedBean, que o bean tem o tempo de vida de um request.
Vamos fazer o deploy da aplicao e iniciar o servidor. A visualizao despesas.xhtml acessada pelo browser em http://localhost:8080/Financeiro/despesas.jsf e mostra apenas 3 botes que realiza o seguinte fluxo:
Observe a presena da anotao @Inject, ela descreve o ponto de injeo de dependncia. Instanciamos o objeto despesaDAO, representante da interface, em momento algum foi citado a implementao, a modelagem esta livre de implementao. Esse o ponto de baixo acoplamento, conhecemos o contrato, ento solicitamos que seja executado de alguma forma essa funcionalidade. Mas oque ser injetado? Oque voc espera que seja injetado? A resposta mais obvia que seja injetado um representante da Classe JDBCDespesaDAO. exatamente oque acontece, como colocamos uma interface no ponto de injeo, a classe que implementa essa interface ser automaticamente injetada. Em outras palavras, inverte o controle que o desenvolvedor tem de criar os objetos, delegando essa atividade ao Servidor de Aplicao.
Ampliando o Sistema Um dos motivos para se usar o mecanismo de DI era a tornar plugvel os componentes do sistema, vamos ver de que forma isso acontece. Imagine ento que usaremos Hibernate no lugar do JDBC. Outra mudana seria usar agora outra regra de negocio, o nosso controle de despesas vai trabalhar em mbito internacional, e agora as regras so diferentes ( converso de moeda, tarifas internacionais, restituio de impostos, etc ). Como fazer essas modificaes sem ter que reescrever toda a aplicao? Vamos modelar novamente, acrescentando a classe DespesaServiceInternacional e a classe HbnDespesaDAO.
HbnDespesaDAO.java package dao.hibernate; import dao.DespesaDAO; public class HbnDespesaDAO implements DespesaDAO { public void gravar(){ System. out .println("gravando Hibernate..."); } public void remover(){ System. out .println("removendo Hibernate..."); } public void alterar(){ System. out .println("alterando Hibernate..."); DespesaServiceInternacional.java package import import import servico.impl; javax.inject.Inject; servico.DespesaService; dao.DespesaDAO; } }
public class DespesaServiceInternacional implements DespesaService{ @Inject DespesaDAO despesaDao; public void gravar(){ System.out .println("gravando internacional"); despesaDao.gravar(); } public void remover(){ System.out .println("removendo internacional"); despesaDao.remover(); } public void alterar(){ System.out .println("alterando internacional"); despesaDao.alterar(); } }
Agora temos duas implementaes para a interface DespesaService e duas para DespesaDAO. E agora, oque sera injetado? Como eu escolho oque sera injetado? Antes de responder a essas questes, vamos iniciar o servidor com essas modificaes no sistema. Ao levantar a aplicao j nos deparamos com o seguinte erro:
WELD-001409 Ambiguous dependencies for type [DespesaDAO] with qualifiers [@Default] at injection point [[field] @Inject servico.impl.DespesaServiceNacional.despesaDao]. Possible dependencies [[Managed Bean [class dao.jdbc.JDBCDespesaDAO] with qualifiers [@Any @Default], Managed Bean [class dao.hibernate.HbnDespesaDAO] with qualifiers [@Any @Default]]]
Esse erro esta dizendo que existem duas implementaes para a dependncia DespesaDAO. Temos um caso de ambiguidade. Para resolver esse problema temos que escolher uma implementao. Devemos marcar todas as implementaes com a anotao @Alternative para especificar que ela uma possvel alternativa de dependncia.
clique no boto Add... para adicionar a classe eleita para a injeo. Escolha as classes novas classes que criamos, (DespesaServiceInternacional e HbnDespesaDAO). No esquea de salvar o arquivo aps a modificao.
@Alternative public class JDBCDespesaDAO implements DespesaDAO {...} Feito isso, devemos definir qual vai ser a implementao a ser injetada atravs do arquivo beans.xml.
<?xml version= "1.0" encoding= "UTF-8"?> <beans xmlns= "http://java.sun.com/xml/ns/javaee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation= "http://java.sun.com/xml/ns/javaee http://docs.jboss.org/cdi/beans_1_0.xsd"> <alternatives> <class>servico.impl.DespesaServiceInternacional</class> <class>dao.hibernate.HbnDespesaDAO</class> </alternatives> </beans>
Este artigo mostrou os principais conceitos de Injeo de Dependncias do JEE6, usando o JBoosAS6 e o Eclipse IDE. Foi feita uma modelagem e implementao de um sistema exemplo, onde so demonstrados os mecanismos presentes no artigo. Foi abordado pelo material a soluo de ambiguidade na injeo.