Você está na página 1de 17

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

Você também pode gostar