EJB 3.

0 Tutorial

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

O objetivo deste tutorial é mostrar de forma essencialmente prática, a configuração do ambiente, a  criação dos componentes EJB e os testes, usando JUnit. A maioria dos tutoriais hoje descrevem as novas features da especificação EJB 3.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.0 na hora de configurar o ambiente. 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, sem nenhum “salto lógico”, como fazer isso funcionar. Espero, de verdade, que este tutorial ajude as pessoas e solucione facilmente para desenvolvedor  iniciante nessa nova especificação, as dúvidas que eu tive.

Fabricio Braga

http://www.fabriciobraga.com.br

Parte 1

Configurando o ambiente
Primeiro precisamos ter todas a ferramentas necessárias. Então vamos lá… Lembre­se de que para desenvolver EJB 3.0 será preciso utilizar o JDK 1.5 ou superior, por causa  das “annotations”. Caso você ainda não o tenha, baixe o JDK 1.5 aqui:

Baixe a última versão estável do Eclipse, aqui. Baixe a versão do JBoss com a implementação da especificação EJB 3.0. Note que até a data em  que escrevi esse artigo, ainda havia sido lançado o release final da especificação 3.0, então o JBoss  implementa uma versão beta desta especificação. Baixe o JBoss Application Server aqui. 1 ­ Instale o JDK 1.5 2 ­ Descompacte o Eclipse em um diretório de sua preferência 3 ­ Execute a instalação do JBoss, provelmente o pacote que você baixou é um “.jar”, então talvez  um simples duplo clique faça a instalação começar. 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, onde o JBoss pergunta qual o diretório de instalação e depois pergunta  quais a features que você quer instalar, selecione a opção “ejb3″(conforme a figura abaixo). O  wizzard vai descompactar o JBoss, com as features do EJB 3.0 para o diretório selecionado por  você.

http://www.fabriciobraga.com.br

http://www.fabriciobraga.com.br

Parte 2

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

http://www.fabriciobraga.com.br

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

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

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

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

http://www.fabriciobraga.com.br

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

http://www.fabriciobraga.com.br

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

http://www.fabriciobraga.com.br

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

Agora adicionamos a target que vai copiar o arquivo para lá: <target name="deploy­ejb" depends="package­ejb­session">
http://www.fabriciobraga.com.br

<copy file="${session.jar.file}" todir="${deploy.home}" /> </target> Pronto, agora ao executarmos o Ant, marcamos apenas a target “deploy­ejb”, e o Ant fará tudo.   Bem facil, não? Apenas para recaptular, no final nosso arquivo do Ant ficou assim: <?xml version="1.0"?> <project name="EJBTutorial" basedir="." default="init"> <property name="src" value="src"/> <property name="bin" value="bin" /> <property name="lib" value="lib" /> <property name="session.jar.file" value="jar/business.ejb3"/> <property name="deploy.home" value="/home/fabricio/jboss­4.0.3SP1/server/dmgestao/deploy"/> <path id="classpath.base"> <fileset dir="${lib}"> <include name="*.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, clean, prepare"> <javac srcdir="${src}" destdir="${bin}" verbose="false"> <classpath refid="classpath.base" /> </javac> </target>

<!­­ Empacota os SessionBeans ­­> <target name="package­ejb­session" depends="compile"> <jar jarfile="${session.jar.file}"> <fileset dir="${bin}">
http://www.fabriciobraga.com.br

<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.jar.file}" todir="${deploy.home}" /> </target> </project> Execute o build.xml, apenas com a target “deploy­ejb” marcada, e observe o console do JBoss, você  deverá ver algo assim: 17:55:43,118 INFO  [JaccHelper] Initialising JACC Context for deployment: business.ejb3 17:55:43,165 INFO  [Ejb3AnnotationHandler] found EJB3:  ejbName=com.model.ejb.session.UsuarioServiceBean,  class=com.model.ejb.session.UsuarioServiceBean, type=STATELESS 17:55:43,225 INFO  [JaccHelper] com.model.ejb.session.UsuarioServiceBean has no  @SecurityDomain ­ skipping JACC configuration 17:55:43,226 INFO  [JaccHelper] JACC Policy Configuration for deployment has been put in  service 17:55:43,226 INFO  [Ejb3Deployment] EJB3 deployment time took: 108 17:55:43,235 INFO  [ProxyDeployer] no declared remote bindings for :  com.model.ejb.session.UsuarioServiceBean 17:55:43,236 INFO  [ProxyDeployer] there is remote interfaces for  com.model.ejb.session.UsuarioServiceBean 17:55:43,236 INFO  [ProxyDeployer] default remote binding has jndiName of  com.service.UsuarioService 17:55:43,344 INFO  [EJB3Deployer] Deployed: file:/home/fabricio/jboss­ 4.0.3SP1/server/ejbtutorial/deploy/business.ejb3 Isso significa que o deploy ocorreu sem problemas.

http://www.fabriciobraga.com.br

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

http://www.fabriciobraga.com.br

public class ServiceLocator { private HashMap homes = new HashMap(); private static ServiceLocator locator; private InitialContext initialContext; private ServiceLocator() { try { Hashtable t = new Hashtable(); t.put(Context.INITIAL_CONTEXT_FACTORY,                      "org.jnp.interfaces.NamingContextFactory"); t.put(Context.PROVIDER_URL, "localhost"); t.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); initialContext = new InitialContext(t); } catch (Exception exc) { exc.printStackTrace(); }

}

public static ServiceLocator getInstance() { if (locator == null) { locator = new ServiceLocator(); } return locator; } protected Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException( "Nao e possivel clonar o ServiceLocator!"); } public Object get(String jndiName) throws Exception { try { Object result = null; result = initialContext.lookup(jndiName); if(result==null) { if (result==null) { throw new NamingException(); } } return result; } catch (NamingException e) { e.printStackTrace(); } return null; }

}

http://www.fabriciobraga.com.br

Agora vamos criar uma classe teste, pa ra acessar o nosso objeto, crie um pacote chamado “com.testes” e nele uma classe chamada  “TestUsuario”: package com.testes; import com.service.ServiceLocator; import com.service.UsuarioService; public class TestUsuario { public static void main (String...args){ try{ UsuarioService usuario =  (UsuarioService)ServiceLocator.getInstance().get(UsuarioService.class.getName()); System.out.println(usuario.getMessage()); } catch (Exception e){ e.printStackTrace(); } } }

Vamos precisar adicionar ao build path do nosso projeto 2 arquivos jars, localizados no diretorio de  instalação do JBoss: jboss/client/jbossall­client.jar jboss/server/default/deploy/jboss­aop.deployer/jboss­aspect­library­jdk50.jar Feito isso, podemos executar nossa classe de teste e veremos a mensagem contida na implementação  do método do nosso componente. Fabricio Braga 

http://www.fabriciobraga.com.br

Sign up to vote on this title
UsefulNot useful