You are on page 1of 17

EJB 3.

0 Tutorial

Por Fabricio Braga contato@fabriciobraga.com.br
http://www.fabriciobraga.com.br

 usando JUnit. Como fazer a minha IDE processar corretamente as  annotations? Como fazer o deploy? Quais os melhores padrões para utilizar esta nova especificação? Aqui veremos passo­a­passo. as dúvidas que eu tive.fabriciobraga. Fabricio Braga http://www. a  criação dos componentes EJB e os testes. de verdade.0 na hora de configurar o ambiente.0 focando na parte  das annotations e das inúmeras facilidades que o uso do Hibernate trouxe para o tratamento da  camada de persistência. Eu senti alguma dificuldade quando comecei a desenvolver os componentes usando a especificação  EJB 3. Espero. sem nenhum “salto lógico”. que este tutorial ajude as pessoas e solucione facilmente para desenvolvedor  iniciante nessa nova especificação.O objetivo deste tutorial é mostrar de forma essencialmente prática.br . como fazer isso funcionar. A maioria dos tutoriais hoje descrevem as novas features da especificação EJB 3. a configuração do ambiente.com.

0 será preciso utilizar o JDK 1.jar”. Note que até a data em  que escrevi esse artigo. ainda havia sido lançado o release final da especificação 3.Parte 1 Configurando o ambiente Primeiro precisamos ter todas a ferramentas necessárias. então talvez  um simples duplo clique faça a instalação começar. aqui. O  wizzard vai descompactar o JBoss. Se não funcionar vá na linha de comando de  execute o comando: $java ­jar nome­do­pacote­jboss­que­voce­baixou Será aberto um Wizzard. então o JBoss  implementa uma versão beta desta especificação.com. http://www. provelmente o pacote que você baixou é um “.5 ou superior.fabriciobraga.0. por causa  das “annotations”. 1 ­ Instale o JDK 1. Baixe o JBoss Application Server aqui.5 aqui: Baixe a última versão estável do Eclipse.0. Baixe a versão do JBoss com a implementação da especificação EJB 3. Então vamos lá… Lembre­se de que para desenvolver EJB 3.br .5 2 ­ Descompacte o Eclipse em um diretório de sua preferência 3 ­ Execute a instalação do JBoss. baixe o JDK 1. Caso você ainda não o tenha. selecione a opção “ejb3″(conforme a figura abaixo). onde o JBoss pergunta qual o diretório de instalação e depois pergunta  quais a features que você quer instalar.0 para o diretório selecionado por  você. com as features do EJB 3.

http://www.br .fabriciobraga.com.

 simples. clicando em “ok”. certo? Selecione a aba “source”. feche a janela.com. por  enquanto. a  “Default output folder”. Se  sim. na aba “Package Explorer”. imediatamente  abaixo da pasta do projeto. criaremos um diretório chamado “src”. Uma janela se abrirá.  Agora precisamos configurar os diretórios de fonte e de output do seu projeto. no menu do lado esquerdo selecione a opção “Java build path”. do lado esquerdo do seu Eclipse. Para este tutorial.model. e selecione “new” ­>  “package”.Parte 2 Agora é hora de começar a desenvolver! Abra o Eclipse e crie um projeto Java. ali embaixo. Criando nosso primeiro Session… Chega de enrolação agora.ejb.session” Crie uma classe nesse pacote. Um projeto novo apereceu agora. Provavelmente após fazer isso. clique em “Browse” e crie uma pasta chamada “bin”. Nela você escolhe os diretórios  de fonte e de output do seu projeto. foi automaticamente configurada para “SeuProjeto/bin”. que é o nosso diretório de fontes. e  na caixa de diálogo que se abre entre com o nome dele. Clique com o botão  direito em cima dele e selecione “Properties”. vamos escrever código! Crie um pacote para seus Sessions. “src”. Caso não seja esta a pasta. chamada “UsuarioServiceBean”: http://www. algumas  opções aparecerão do lado direito. não precisa setar mais nada. clicando com  o botão direito em cime do diretorio “src”.br . Você pode fazer isso no menu: “File” ­> “New Project…” e selecionando a opção “Java Project”. clique em “add folder…” do lado direito.fabriciobraga. vazio. Escolha um nome para o seu projeto e clique em “finish”. Crie um pacote com o nome “com.

 e vai indicar um erro ali. Inicialmente o Eclipse não vai reconhece­la. http://www.jar” que fica dentro diretório de instalação do JBoss: jboss/server/default/deploy/ejb3.  porque facilitará muito quando formos empacotar nossa aplicação com ajuda do ant. por  exemplo que você tenha um Tomcat. É considerado “local” tudo o que estiver na mesma VM (Virtual Machine).Stateless. e use o recurso “organize imports”  do Eclipse. Então suponha.ejb. import javax.. agora deixe­me dar uma breve explicação de um tópico muito importante. pode ser pelas teclas de atalho “Ctrl+Shift+O”. Mas eu pessolamente prefiro assim.session. Nossa classe agora ficará assim: package com.br . como alternativa você poderia  simplesmente adicionar um jar externo ao seu java build path. e depois em “properties”. que são as interfaces  locais e remotas do seu EJB. nela você vai adicionar o jar utilizando  “add jars” e selecionando o nosso “ejb3x. e é por  estas interfaces que o cliente acessa os métodos do seu componente.package com.. e evita  problemas com path se por acaso você levar seu projeto para outra máquina.ejb. } Aquela “annotation” em cima do nome da classe indica que trata­se de um SessionBean do tipo  Stateless.fabriciobraga. Agora faça o seguinte.  no menu ” Java build path”. resolveremos isso  adicionando ao path do seu projeto o “jar” com essa classe. onde o diretório do  JBoss pode ser diferente.com. Crie um diretório chamado “lib” imediatamente abaixo do diretório do seu projeto.deployer Note que a rigor não é necessário copiar esse jar para cá.ejb. com seus componentes EJB. Copie para  dentro deles o jar “ejb3x. na mesma máquina. @Stateless public class UsuarioServiceBean { } E não devem haver mais erros.session. selecione a aba “Libraries”. Ok. clique com botão direito em cima do seu projeto. Todo EJB pode ter interfaces do tipo “Local” ou “Remote”.model.jar”.model. com alguns Servlets rodando em uma aplicação na sua  máquina e um JBoss. que estava com erro. Volte à nossa classe “UsuarioServiceBean”. @Stateless public class UsuarioServiceBean { .

 foram  startados por VMs diferentes.service”. Crie um pacote chamado “com. @Remote public interface UsuarioService { } A anotation “@Remote” indica que trata­se de uma interface do tipo “Remote” para a classe que a  implementa. O que não ocorre por exemplo se os seus Servlets estiverem dentro do  JBoss (O JBoss possui um módulo do Tomcat dentro dele). por estarem separados.  Então certamente você não vai enviar para o seu cliente um pacote com seus Session Beans.Remote.  para que ele acesse seus métodos de negócio. import javax. certo?  Na prática o que você fará é disponibilizar um pacote para o cliente com suas interfaces remotas.service. com os métodos de negócio para que nossos  clientes possam acessar nosso SessionBean. uma das vantagens de usar componentes remotos é que você pode disponibiliza­los para seus  clientes sem que eles tenham acesso a implementação dos métodos e às suas regras de negócio. quando então ambos estarão na mesma  VM. e crie uma  interface chamada “UsuarioService”: package com.com.Remote.fabriciobraga.RemoteException.rmi.ejb. } http://www.ejb. Então vamos agora escrever uma interface remota. import javax. apenas. Detalhes da implementação são problema seu.service. import java. Vamos também adicionar um método a ela: package com. E porque você precisa de uma interface para os seus componentes? Bem. O que ocorre é que muito provavelmente estes dois containers.A pergunta é: o meu Servlet que está lá dentro do Tomcat vai acessar os meus componentes EJB de  maneira local ou remota? Provavelmente remota. não dele.br . @Remote public interface UsuarioService { public String getMessage() throws RemoteException.

import javax.  esse será o aqruivo de build do ant. @Stateless public class UsuarioServiceBean implements UsuarioService{ public String getMessage() throws RemoteException { return “don’t worry buddy it is just a test…”.ejb.xml” no diretório principal do nosso projeto.ejb. O próximo passo é configurar o ant para automatizarmos o processo de compilação. vamos fazer mais algums  modificações nele: package com. import java.session.br . o nosso UsuarioServiceBean deve implementar a interface.” indica que estamos no diretŕoio raiz do projeto. O atributo “basedir”: basedir=”." default="init"> <target name="init"> <echo>Iniciando build do EJB tutorial</echo> </target> </project> Iniciando build do EJB tutorial É muito importante que não haja nenhum espaço ou tabulação antes da primeira linha “” porque  isso gera um erro no processamento do arquivo pelo ant.model. Vamos editar o arquivo da seguinte forma: <?xml version="1.UsuarioService. Mas tenho  como objetivo neste tutorial simplificar o máximo possível. A partir disso. } } Repare que agora ele implementa a interface.Agora.rmi.Stateless. import com.fabriciobraga. teste e deploy  da nossa aplicação. então vamos deixar ele aqui mesmo. chamado normalmente de “META­INF”. e adicionamos um código bem simples ao método de  negócio. espaços ou tabulações serão  ignoradas.RemoteException.service.0"?> <project name="EJBTutorial" basedir=". http://www. Crie um arquivo chamado “build.com. apenas nessa primeira linha temos esta restrição. algumas pessoas (inclusive eu) preferem colocar o  arquivo build do ant em um diretório separado.

 que na verdade não faz muita coisa. Vamos fazer uma análise rápida delas: http://www.com.  apenas imprime na tela a mensagem “Iniciando build do EJB tutorial”. clean.Temos agora um arquivo de build do Ant bastante básico.0"?> <project name="EJBTutorial" basedir=".br . vamos setar algumas  propriedades dele começando pelos diretórios de fonte.base" /> </javac> </target> </project> Agora nosso arquivo ganhou alguma utilidade. entretanto o Ant é uma  bastante poderosa. output e lib da nossa aplicação e também  algumas “targets”: <?xml version="1. como limpar o diretório de output e compilar nossas classes.fabriciobraga.jar" /> </fileset> </path> <target name="init"> <echo>Iniciando build do EJB tutorial</echo> </target> <target name="clean" depends="init"> <delete dir="${bin}"> </delete> </target> <target name="prepare" depends="init"> <mkdir dir="${bin}" /> </target> <target name="compile" depends="init.  Adicionamos “targets” a ele que fazem  algum trabalho para nós. prepare"> <javac srcdir="${src}" destdir="${bin}" verbose="false"> <classpath refid="classpath.base"> <fileset dir="${lib}"> <include name="*. e vamos utilizar um pouco mais de recursos dele." default="init"> <property name="src" value="src"/> <property name="bin" value="bin" /> <property name="lib" value="lib" /> <path id="classpath. de fato.

 só  que mais adiante vamos adicionar mais variáveis e você perceberá de forma mais clara a verdadeira  vantagem de usarmos estas propriedades. clique com o botão direito no arquivo “build. <target name="compile" depends="init. <target name="clean" depends="init"> <delete dir="${bin}"> </delete> </target> Esta target existe apenas para garantir que antes de iniciar o processo de compilação estaremos  limpando tudo o que existe no diretório de output.br .  Nesse caso. clean.jar" /> </fileset> </path> Aqui setamos o classpath para a compilação.xml”. que facilitarão nossa vida porque  substituem os nomes de diretórios por variáveis. e algumas informações sobre o processamento deverão aparecer.  Perceba que aqui já fazemos uso da variável que setamos anteriormente. e  clique em “run”. Agora. a compilação das nossas classes. com o nosso diretório “lib” e todos os jars que  estiverem dentro dele.  Note que fazemos referência ao  classpath que setamos antes.base"> <fileset dir="${lib}"> <include name="*. no Eclipse. prepare"> <javac srcdir="${src}" destdir="${bin}" verbose="false"> <classpath refid="classpath. para que o compilador utilize as classes do nosso diretório “lib”.  ao final a mais importante é: “BUILD SUCCESSFUL” http://www. não  percebemos muita vantagem porque os diretórios são simples.<property name="src" value="src"/> <property name="bin" value="bin" /> <property name="lib" value="lib" /> Aqui o que fizemos foi setar algumas propriedades do Ant.fabriciobraga.base" /> </javac> </target> Aqui a mais importante delas. que podem ser referenciadas. Você verá o Ant sendo executado. e estão dentro do nosso projeto. <path id="classpath. selecione apenas a target “compile”. e depois no menu “Run  As…” ­> “Ant Build” Na janela de opções que se abre. desmarque todas as outras.com.

jar. Por definição." default="init"> <property name="src" value="src"/> <property name="bin" value="bin" /> <property name="lib" value="lib" /> <property name="session. que vai empacotar nossos Sessions nosso  arquivo agora ficará assim: <?xml version="1. prepare"> <javac srcdir="${src}" destdir="${bin}" verbose="false"> <classpath refid="classpath.xml do Ant.Parte 3 Agora que já temos nossa interface remota e nosso UsuarioServiceBean prontos.  podemos passar para a parte da implementação deles.  Nesse diretório  vamos colocar o pacote com os nossos EJBs.br .fabriciobraga. o pacote com os SessionBean tem a extensão “*. Crie um diretório chamado “jar” imediatamente abaixo do diretório do seu projeto. e também mais uma importante target.base"> <fileset dir="${lib}"> <include name="*.com. e compilando. é por nele que o JBoss vai  procurar seus Sessions.jar" /> </fileset> </path> <target name="init"> <echo>Iniciando build do EJB tutorial</echo> </target> <target name="clean" depends="init"> <delete dir="${bin}"> </delete> </target> <target name="prepare" depends="init"> <mkdir dir="${bin}" /> </target> <target name="compile" depends="init.ejb3"/> <path id="classpath. clean.base" /> </javac> </target> http://www. então para facilitar nossa vida vamos criar mais um propriedade no nosso  build.file" value="jar/business.0"?> <project name="EJBTutorial" basedir=".ejb3″.

br .home" value="/home/fabricio/jboss­ 4. como  datasources por exemplo. não precisa reiniciar o JBoss só para fazer  isso.0. e  desmarque todas as outras.<!­­ Empacota os SessionBeans ­­> <target name="package­ejb­session" depends="compile"> <jar jarfile="${session. basta copiar esse arquivo para o diretório “deploy” da sua aplicação no JBoss.jar.file}"> <fileset dir="${bin}"> <include name="com/**"/> </fileset> </jar> </target> </project> Perceba que agora nós temos uma nova propriedade.  Não é muito difícil de entender. Para fazer o deploy.ejb3″ dentro do diretório “jar”.  com o diretŕoio de deploy da minha aplicação: <property name="deploy.  ele  é provavelmente esse: jboss/server/default/deploy Você pode copia­lo para lá mesmo com JBoss já rodando. onde setamos o nome do nosso arquivo que vai  conter os Sessions e as interfaces.  Em geral para fazer simples deploys de seus pacotes de EJB ou WARs no JBoss você não  precisa reinicia­lo.xml”.fabriciobraga. e o diretório onde ele vai ficar. Mas eu como sou extremamente preguiçoso.  O diretório “ejbtutorial” que vem entre “server” e “deploy” é o diretório da configuração  para esta minha aplicação. você deve substitui­lo pelo seu diretório no seu  JBoss.  Talvez na sua máquina seja “default” ou outro que você possa ter  escolhido durante o wizard de instalação do Jboss. mas desta vez marque apenas a target “package­ejb­session”.3SP1/server/ejbtutorial/deploy"/> Atenção: O caminho do diretório é o da minha máquina. se tudo correr bem ele terá gerado um arquivo chamado  “business. então acrescento duas coisas muito simples ao meu “build. isso é necessário apenas quando alterar arquivos de configuração. Agora adicionamos a target que vai copiar o arquivo para lá: <target name="deploy­ejb" depends="package­ejb­session"> http://www. prefiro deixar o Ant fazer até mesmo esse deploy para  mim.com. Execute novamente o build do Ant.  Primeiro uma propriedade.  Ao final. O atributo: name=”com/**” Diz para o Ant que ele deve incluir todos os subdiretórios e arquivos abaixo do pacote “com” no  nosso pacote.

 marcamos apenas a target “deploy­ejb”.home" value="/home/fabricio/jboss­4. prepare"> <javac srcdir="${src}" destdir="${bin}" verbose="false"> <classpath refid="classpath.file}"> <fileset dir="${bin}"> http://www.fabriciobraga.jar.home}" /> </target> Pronto." default="init"> <property name="src" value="src"/> <property name="bin" value="bin" /> <property name="lib" value="lib" /> <property name="session.jar" /> </fileset> </path> <target name="init"> <echo>Iniciando build do EJB tutorial</echo> </target> <target name="clean" depends="init"> <delete dir="${bin}"> </delete> </target> <target name="prepare" depends="init"> <mkdir dir="${bin}" /> </target> <target name="compile" depends="init.jar. agora ao executarmos o Ant.br .base" /> </javac> </target> <!­­ Empacota os SessionBeans ­­> <target name="package­ejb­session" depends="compile"> <jar jarfile="${session.0"?> <project name="EJBTutorial" basedir=". não? Apenas para recaptular.file" value="jar/business.ejb3"/> <property name="deploy.file}" todir="${deploy.jar. e o Ant fará tudo.0.base"> <fileset dir="${lib}"> <include name="*. no final nosso arquivo do Ant ficou assim: <?xml version="1.<copy file="${session. clean.com.3SP1/server/dmgestao/deploy"/> <path id="classpath.   Bem facil.

344 INFO  [EJB3Deployer] Deployed: file:/home/fabricio/jboss­ 4.UsuarioService 17:55:43.226 INFO  [JaccHelper] JACC Policy Configuration for deployment has been put in  service 17:55:43.ejb.226 INFO  [Ejb3Deployment] EJB3 deployment time took: 108 17:55:43.model.0.225 INFO  [JaccHelper] com.ejb.home}" /> </target> </project> Execute o build.ejb.UsuarioServiceBean has no  @SecurityDomain ­ skipping JACC configuration 17:55:43.file}" todir="${deploy. apenas com a target “deploy­ejb” marcada.model.fabriciobraga.118 INFO  [JaccHelper] Initialising JACC Context for deployment: business.236 INFO  [ProxyDeployer] default remote binding has jndiName of  com.service.ejb.  class=com.session.3SP1/server/ejbtutorial/deploy/business.session. http://www.<include name="com/**"/> <exclude name="com/dmgestao/testes/**"/> <exclude name="com/dmgestao/model/ejb/entity/**"/> </fileset> </jar> </target> <target name="deploy­ejb" depends="package­ejb­session"> <copy file="${session.ejb3 Isso significa que o deploy ocorreu sem problemas.UsuarioServiceBean.session.jar.UsuarioServiceBean.model.br .xml.ejb3 17:55:43.235 INFO  [ProxyDeployer] no declared remote bindings for :  com.model.UsuarioServiceBean 17:55:43. e observe o console do JBoss.165 INFO  [Ejb3AnnotationHandler] found EJB3:  ejbName=com. você  deverá ver algo assim: 17:55:43.session.session.com.ejb. type=STATELESS 17:55:43.UsuarioServiceBean 17:55:43.236 INFO  [ProxyDeployer] there is remote interfaces for  com.model.

Criando um Client para o nosso Stateless  SessionBean Agora.service.  "org. t. vamos criar um “ServiceLocator”.jnp. import javax.naming. que fará esse trabalho para  nós.  O nosso cliente  precisará conectar­se ao serviço de nomes (JNDI) e encontrar o nosso componente.  Por isso concentramos o  processo de “procurar” o objeto no serviço de nomes em um Singleton.URL_PKG_PREFIXES.NamingContextFactory").  Vamos agora  escrever um cliente que possa acessar o componente e seus métodos de negócio. Para usarmos uma abordagem mais de acordo com o que acontece no mundo real durante o  desenvolviemnto de um sistema.naming:org.br .jboss.util. precisamos testa­lo e acessa­lo.INITIAL_CONTEXT_FACTORY.service”.NamingException.put(Context. "localhost"). } catch (Exception exc) { exc.  Imagine que toda vez que você for acessar um  componente EJB você faça assim: try { Hashtable t = new Hashtable().EJBHome.interfaces. com o nosso componente rodando no servidor. t.Context.lookup(UsuarioService.class.put(Context.put(Context.PROVIDER_URL. import java. import javax.interfaces").Hashtable. dentro do pacote “com. import javax. UsuarioService usuarioService = (UsuarioService)  initialContext.ejb. Crie uma classe chamada “ServiceLocator. } } É evidente que isso faria o nosso código ficar demasiadamente grande.HashMap. initialContext = new InitialContext(t). t.getName()).InitialContext.  Aqui o nosso  ServiceLocator: package com.jnp.util. http://www.naming. import java.      "org.printStackTrace(). ServiceLocator é uma pattern que nos poupa o trabalho de pegar o InitialContext toda vez que  quisermos uma interface para um objeto de negócio.com.naming. import javax.fabriciobraga.

t. } return locator.jnp. private static ServiceLocator locator.PROVIDER_URL. } } http://www. } catch (NamingException e) { e. "org. initialContext = new InitialContext(t). private InitialContext initialContext. private ServiceLocator() { try { Hashtable t = new Hashtable().lookup(jndiName).interfaces").printStackTrace(). } protected Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException( "Nao e possivel clonar o ServiceLocator!"). if(result==null) { if (result==null) { throw new NamingException().fabriciobraga.com.put(Context.jboss.jnp.put(Context. result = initialContext.NamingContextFactory").URL_PKG_PREFIXES.naming:org. } catch (Exception exc) { exc. } return null.public class ServiceLocator { private HashMap homes = new HashMap(). t.INITIAL_CONTEXT_FACTORY.br . } } return result.printStackTrace(). } } public static ServiceLocator getInstance() { if (locator == null) { locator = new ServiceLocator(). } public Object get(String jndiName) throws Exception { try { Object result = null.interfaces.put(Context. t. "localhost").                      "org.

println(usuario.jar Feito isso.deployer/jboss­aspect­library­jdk50.br .Agora vamos criar uma classe teste.printStackTrace().class..getInstance(). public class TestUsuario { public static void main (String.. } } } Vamos precisar adicionar ao build path do nosso projeto 2 arquivos jars.fabriciobraga.jar jboss/server/default/deploy/jboss­aop.testes.getName()). pa ra acessar o nosso objeto.com.getMessage()).UsuarioService.service. localizados no diretorio de  instalação do JBoss: jboss/client/jbossall­client.out. System.get(UsuarioService. import com. } catch (Exception e){ e. podemos executar nossa classe de teste e veremos a mensagem contida na implementação  do método do nosso componente. crie um pacote chamado “com.ServiceLocator. Fabricio Braga  http://www.args){ try{ UsuarioService usuario =  (UsuarioService)ServiceLocator.testes” e nele uma classe chamada  “TestUsuario”: package com.service. import com.