You are on page 1of 358

Curso J150

Curso J150

Curso J150
J2EE Java 2 platform Enterprise Edition
EJB
IDHP Instituto de Desenvolvimento Humano e Pesquisa LTDA.
Stio WEB: http://www.psique.org/cursos

24/04/04 01:42:30
jp@psique.org http://www.psique.org/cursos

Curso J150

Curso J150

Curso J150
J2EE Java 2 platform Enterprise Edition
EJB

Verso
Verso 1.0

Data

Autor

23/04/2004 J.Paulo Limberger

24/04/04 01:42:32
jp@psique.org http://www.psique.org/cursos

Alterao
Primeira Verso

Curso J150

Curso J150

ndice
Curso J150..........................................................................................1
J2EE Java 2 platform Enterprise Edition..............................1
EJB..........................................................................................1
Curso J150......................................................................................2
J2EE Java 2 platform Enterprise Edition..............................2
EJB..........................................................................................2
J2EE Viso Geral............................................................................14
Conceito........................................................................................14
J2EE Principais Tecnologias...................................................14
Objetivo de J2EE.......................................................................15
Mltiplas camadas................................................................16
Os componentes J2EE...............................................................16
Clientes J2EE........................................................................17
Arquitetura de componentes JavaBeans...............................18
Comunicao com o Servidor...............................................18
Componentes Web....................................................................18
Componentes de Negcios.......................................................19
Enterprise Information System Tier.........................................20
Continers J2EE...........................................................................20
Servios do Continer...............................................................21
Servios do continer Montagem...........................................21
Servios J2EE...........................................................................21
Tipos de continer....................................................................22
Empacotamento........................................................................22
Mdulo J2EE.............................................................................23
Mdulos tipos.........................................................................23
Mdulos tipos.........................................................................23
Web Services............................................................................24
Web Services Transporte.......................................................24
Papis de desenvolvimento.......................................................24
J2EE Product Provider..........................................................24
J2EE Tool Provider................................................................25
J2EE Application Component Provider.................................25
Enterprise Bean Developer...................................................25
Web Component Developer...................................................25
J2EE Application Client Developer.......................................26
Application Assembler..........................................................26
24/04/04 01:42:34
jp@psique.org http://www.psique.org/cursos

Curso J150

Curso J150

Application Deployer e Administrador..................................26


Servidor de Aplicaes.....................................................................28
JBOSS........................................................................................28
JBoss caractersticas.................................................................28
JBoss Instalao.....................................................................28
JBoss Ativao........................................................................29
JBoss Iniciando o servidor......................................................30
Alguns arquivos de configurao..............................................30
conf/jboss-service.xml...........................................................30
conf/jbossmq-state.xml.........................................................31
conf/jndi.properties...............................................................31
conf/log4j.xml........................................................................31
conf/login-config.xml.............................................................31
conf/server.policy..................................................................31
conf/standardjaws.xml..........................................................31
conf/standardjbosscmp-jdbc.xml...........................................31
conf/standardjboss.xml.........................................................32
deploy/http-invoker.sar.........................................................32
deploy/jbossweb-jetty.sar......................................................32
deploy/jmx-console.war.........................................................32
deploy/management/console-mgr.sar , web-console.war.....32
deploy/hsqldb-ds.xml............................................................33
deploy/transaction-service.xml.............................................33
JBoss deploy...........................................................................33
JBoss Tomcat..........................................................................33
JBoss JMX-Console.................................................................33
Laboratrio 15_01....................................................................35
JNDI .................................................................................................37
Os servidores de nomes................................................................37
JNDI Objetivo
..................................................................................................37
Objetos de Diretrios................................................................39
Atributos...................................................................................40
Atributo-identificador...............................................................40
Diretrio e Servio de Diretrio...............................................41
Buscas e Filtros........................................................................41
Binding......................................................................................41
Referncias e Endereos..........................................................41
Contexto....................................................................................42
Sistema de Nomes....................................................................42
24/04/04 01:42:36
jp@psique.org http://www.psique.org/cursos

Curso J150

Curso J150

Namespace...............................................................................42
Combinando Nomes e Servios de Diretrio...........................43
Aplicaes Java e Diretrios.....................................................43
O diretrio como um armazm de objetos................................43
JNDI Viso Geral....................................................................43
Benefcios de JNDI....................................................................43
Arquitetura...............................................................................44
Utilizao..................................................................................44
A API JNDI
..................................................................................................45
Context.....................................................................................45
Names.......................................................................................46
Composite.............................................................................47
Compound.............................................................................47
Bindings....................................................................................47
Reference..............................................................................48
A classe javax.naming.InitialContext........................................48
Ambiente - ENC........................................................................51
Criao de uma cpia do beans................................................53
Exceptions................................................................................54
Pacote: javax.naming.directory................................................54
O contexto do diretrio.............................................................54
Buscas.......................................................................................55
Laboratrio 20_01.....................................................................55
Laboratrio 20_02.....................................................................55
Laboratrio 20_03.....................................................................56
ANT Noes bsicas de utilizao.................................................57
ANT O que ...........................................................................57
ANT Projeto Apache...............................................................57
ANT Documentao................................................................57
ANT Execuo........................................................................57
ANT Execuo de tarefa.........................................................58
ANT - Instalao Ambiente
..................................................................................................58
ANT Laboratrio 22_01
..................................................................................................58
Laboratrio 22_02.....................................................................59
Tag <project>..............................................................................60
Tag <target> alvos.......................................................................60
Tarefas......................................................................................61
24/04/04 01:42:38
jp@psique.org http://www.psique.org/cursos

Curso J150

Curso J150

Propriedades................................................................................61
Laboratrio 22_03.....................................................................62
Propriedades externas..............................................................62
Laboratrio 22_04.....................................................................63
Propriedades no so redefinidas.........................................63
Laboratrio 22_05.....................................................................63
Laboratrio 22_06.....................................................................64
Outras pr-definidas.................................................................65
Laboratrio 22_07.....................................................................65
Laboratrio 22_08.....................................................................65
Java RMI...........................................................................................67
Invocao Remota de Mtodos.....................................................67
Marshalling e Unmarshalling...................................................67
Convenes de passagem de parmetros.................................68
Instabilidades de rede..............................................................68
A interface remota....................................................................68
A implementao do objeto remoto..........................................70
Stubs e Skeletons.....................................................................72
Bootstrapping e registro RMI...................................................74
URLs de RMI................................................................................75
Procurando um objeto remoto (lookup)........................................76
RMIC O compilador RMI............................................................77
Serializao de Objetos e passagem de parmetros....................77
Passagem por Valor..................................................................78
Serializao de Objetos............................................................78
Como os objetos so serializados.............................................78
Regras para serializao..........................................................79
O que deve ser Transient?........................................................79
Usos de serializao de objetos................................................80
Simulao de passagem por referncia com RMI....................81
Exportando Objetos Remotos...................................................82
Laboratrio 24_01....................................................................83
RMI, Corba e EJB.............................................................................84
RMI ou CORBA.........................................................................84
RMI e EJB.................................................................................84
Objetos EJB...............................................................................87
Objetos Home...........................................................................88
EJB Enterprise Java Beans.............................................................89
Tipos de Enterprise Bean.............................................................89
Como escrever um bean...............................................................89
24/04/04 01:42:40
jp@psique.org http://www.psique.org/cursos

Curso J150

Curso J150

Como escrever o bean Somador...................................................90


O descritor de distribuio Deployment Descriptor..................92
Criao de um arquivo de distribuio........................................93
Distribuio..................................................................................93
Partes do EJB................................................................................94
A interface home......................................................................94
A interface remote....................................................................96
A classe enterprise bean..............................................................98
O descritor de distribuio.......................................................98
Como escrever aplicativos clientes...........................................99
Um aplicativo cliente Java..............................................................100
Chamando o bean de uma pgina JSP....................................101
Session Bean Bean de sesso......................................................105
O que um session bean............................................................105
Session beans com estado e sem estado.................................106
Passivation e Activation de sessions beans com estado.........106
Session Bean Statefull............................................................107
Stateless Session Beans..........................................................108
Quando utilizar stateful session beans:..............................108
Quando utilizar stateless session beans:............................109
Como escrever um session bean.............................................109
A interface javax.ejb.SessionBean..............................................110
Um exemplo de session bean..................................................111
A interface javax.ejb.SessionContext e a interface
javax.ejb.EJBContext..............................................................112
Como usar um session bean statefull a partir de uma pgina
JSP ou Servlet ........................................................................113
O deployment descriptor........................................................114
Exemplo - Livraria................................................................118
O banco de dados.......................................................................121
O session bean de busca - Stateless....................................124
O session bean DetalhesDoLivro stateless...........................128
Teste parcial da aplicao......................................................131
Um session bean de um carrinho de compras Statefull........134
Agora a interface remote:.......................................................134
O aplicativo EJB descritor de distribuio..............................137
Criao do deployment descriptor..........................................138
Distribuio no JBoss..............................................................139
A poro WEB da aplicao:...................................................139
O servlet BuscaServlet .......................................................139
24/04/04 01:42:42
jp@psique.org http://www.psique.org/cursos

Curso J150

Curso J150

O servlet DetalhesDoLivroServlet.......................................143
O servlet adicionarNoCarrinhoServlet...............................146
A distribuio do aplicativo cliente........................................151
Entity Beans...................................................................................154
Armazenagem de dados..............................................................154
O que um Entity Bean?............................................................155
Qual a diferena de Entity Bean x Session Bean?...............156
A interface remote..................................................................157
A interface HOME...................................................................158
Mtodo create.....................................................................159
Mtodos finder....................................................................159
Mtodos Remove.................................................................161
A classe da chave primria.................................................161
Um entity bean....................................................................161
A interface javax.ejb.EntityBean.........................................162
Activation e Passivation......................................................164
Mtodos create Criando um entity...................................165
Encontrando um Entity...........................................................168
Removendo um Entity.............................................................168
Outros mtodos...................................................................170
A interface javax.ejb.EntityContext....................................171
Dois tipos de entity beans...................................................172
Entity Bean - BMP.........................................................................173
A interface remote..............................................................175
A interface Home................................................................176
A classe primary key...........................................................177
O entity bean..........................................................................178
Descritor de distribuio........................................................193
Aplicativo Cliente.......................................................................195
Entity Bean CMP...........................................................................199
Entity Beans CMP so subclasses...........................................200
Entity Beans CMP no tem campos declarados.....................200
Entity Beans CMP tem mtodos Get/Set Abstratos................200
Entity Beans tm um Schema abstrato de persistncia.........200
Entity Beans podem tem uma linguagem para queries.........201
Entity Beans podem ter mtodos ejbSelect()........................202
Diferenas entre CMP e BMP.....................................................203
A interface remote......................................................................203
A interface home.....................................................................204
A classe entity bean....................................................................205
24/04/04 01:42:44
jp@psique.org http://www.psique.org/cursos

Curso J150

Curso J150

O deployment descriptor........................................................209
Exemplo de aplicativo cliente.................................................211
Utilizando uma classe para a chave primria customizada....214
A linguagem de consulta EJB EJB-QL..........................................215
A sintaxe EJB -QL.......................................................................217
A clusula SELECT.................................................................217
A clusula FROM....................................................................219
A clusula WHERE.....................................................................221
Literal.....................................................................................223
Identificao varivel.............................................................223
Expresso de caminho............................................................223
Parmetros de entrada...........................................................223
Composio de expresso condicional...................................224
Operadores e precedncia de operador.................................224
Expresses between...............................................................225
Expresses in..........................................................................225
Expresses like.......................................................................225
Expresses de comparao null..............................................225
Expresses de comparao de coleo empty........................226
Expresses de membro de coleo.........................................226
Expresses funcionais............................................................226
EJB QL BNF............................................................................227
Servio de mensagem em Java.......................................................232
Por que usar MDB..................................................................232
Performance........................................................................232
Disponibilidade...................................................................232
Suporte para mltiplos transmissores e receptores...........233
Performance........................................................................233
Confiabilidade.....................................................................234
Suporte para mltiplos transmissores e receptores ..........234
Introduo ao envio de mensagem.........................................234
A API JMS................................................................................235
Os domnios de envio de mensagem API JMS.........................236
Publish/Subscribe (pub/sub)...................................................237
Point-to-Point (PTP)................................................................237
O objeto modelo JMS..............................................................238
ConnectionFactory..................................................................241
Destination..............................................................................242
Connections............................................................................243
Session....................................................................................244
24/04/04 01:42:46
jp@psique.org http://www.psique.org/cursos

Curso J150

Curso J150

MessageProducer...................................................................246
MessageConsumer..................................................................247
Message..................................................................................248
Como escrever um cliente JMS...............................................250
Exemplo de pub/sub................................................................256
JBoss Camadas de Invocao...............................................264
RMI IL.................................................................................264
OIL IL..................................................................................264
UIL IL..................................................................................265
UIL2 IL................................................................................265
JVM IL.................................................................................265
HTTP IL...............................................................................266
Configurao da IL.............................................................266
Beans Direcionados para Mensagem (MDB).................................267
O que um bean direcionado para mensagem .........................267
MDB no tem interfaces home ou remote..........................268
MDB tem um nico mtodo de negcio..................................268
MDB no tem nenhum valor de retorno.................................268
MDB no enviam exceptions de volta ao cliente....................268
MDBs so stateless.................................................................269
MDBs podem ser assinantes durveis ou no durveis..........269
A Application Programming Interface (API)...............................269
A interface javax.jms.MessageListener..................................270
A interface javax.ejb.MessageDrivenBean.............................270
A interface javax.ejb.MessageDrivenBean.............................270
Como acessar um message-driven bean.................................271
Como escrever um mensagem direcionada por bean ............272
A classe bean direcionado para mensagem............................272
O deployment descriptor............................................................277
Configurao do arquivo jboss.xml.........................................278
Empacotamento do MDB....................................................278
JCA Java Connector Architecture................................................280
Chamando Beans de outros Beans................................................284
Lookups JNDIs default............................................................284
Referncias EJB......................................................................285
Segurana......................................................................................289
Autenticao...............................................................................289
O que JAAS...........................................................................290
As principais classes de JAAS.............................................290
Subject e Principal..............................................................291
24/04/04 01:42:48
jp@psique.org http://www.psique.org/cursos

10

Curso J150

Curso J150

Autenticao de um Subject...............................................292
Autorizao.................................................................................296
Basic authentication. .........................................................297
Form-based authentication.................................................297
Digest authentication..........................................................298
Certificate authentication...................................................298
De forma programtica..........................................................298
De forma declarativa..............................................................298
Viso geral segurana declarativa.........................................298
Referncias de segurana.......................................................301
Identidade de Segurana........................................................303
Papis de segurana (Security roles).....................................304
Permisso para execuo de mtodos EJB.............................305
Segurana na WEB.................................................................309
Habilitando a Segurana Declarativa no JBoss......................311
Transaes.....................................................................................315
Definio de Transao..............................................................315
Atomicidade............................................................................315
Consistncia............................................................................315
Isolamento..............................................................................316
Durabilidade...........................................................................316
Locking pessimista e otimista.................................................317
Componentes de uma transao distribuda..........................318
O protocolo two-phase XA.......................................................319
Excees heursticas...............................................................319
Identificadores de transaes e ramificaes (branches)......320
Suporte a transaes de usurio............................................321
Controle explcito de transaes............................................321
Exemplo com JDBC:............................................................322
Exemplo com JTA:...............................................................322
Suporte a UserTransaction.................................................323
Mtodos de javax.transaction.UserTransaction:....................324
begin().................................................................................324
commit()..............................................................................324
getStatus()..........................................................................324
rollback().............................................................................324
setRollbackOnly()................................................................324
setTransactionTimeout(int).................................................324
Constantes..............................................................................325
STATUS_ACTIVE.................................................................325
24/04/04 01:42:49
jp@psique.org http://www.psique.org/cursos

11

Curso J150

Curso J150

STATUS_NO_TRANSACTION..............................................325
STATUS_MARKED_ROLLBACK...........................................325
STATUS_PREPARING.........................................................325
STATUS_PREPARED...........................................................325
STATUS_COMMITING........................................................325
STATUS_COMMITED..........................................................326
STATUS_ROLLING_BACK...................................................326
STATUS_ROLLEDBACK......................................................326
STATUS_UNKNOWN..........................................................326
Controle implcito de transaes............................................326
Required.............................................................................328
Supports..............................................................................328
RequiresNew.......................................................................328
NotSupported.....................................................................328
Mandatory...........................................................................328
Never..................................................................................329
Excees.................................................................................329
Session Synchronization.........................................................330
Anexo 1 Cluster no JBoss.............................................................332
O que um cluster?................................................................332
Caractersticas do Clustering JBoss.......................................332
Parties.................................................................................333
...............................................................................................333
Proxies espertos (Smart proxies)............................................334
Descoberta de ns 'Automgica'............................................335
Configurando o JBoss..............................................................335
HA-JNDI Servio de nomes e o JBoss clustering..............335
Configurao do HA-JNDI no JBoss........................................337
Anexo 2 Criando um session bean no WSAD da IBM...................339
Anexo 3 - Acesso a dados via DAO..................................................348
BusinessObject.......................................................................348
DataAccessObject...................................................................349
DataSource.............................................................................349
ValueObject ou TransferObject...............................................349
Estratgias..................................................................................350
Automatic DAO Code Generation Strategy.............................350
Factory for Data Objects Strategy..........................................350
Conseqncias............................................................................352
Possibilita Transparncia.......................................................352
Facilita Migrao....................................................................352
24/04/04 01:42:51
jp@psique.org http://www.psique.org/cursos

12

Curso J150

Curso J150

Reduz a complexidade de Cdigo nos Objetos de Negcio....353


Centraliza o acesso a dados em uma camada separada.........353
No til para CMP...............................................................353
Cria uma camada extra...........................................................353
Necessita de projeto de hierarquia de classes.......................353
Definies, acrnimos e abreviaes.............................................356

24/04/04 01:42:53
jp@psique.org http://www.psique.org/cursos

13

J2EE Viso Geral

Curso J150

J2EE Viso Geral


Conceito
J2EE Java 2 Platform Enterprise Edition. Um conjunto de
especificaes coordenadas e prticas que em conjunto habilitam
solues para desenvolvimento, instalao em servidor (deploying),
e gerenciamento de aplicaes multi-camadas baseadas em servidor
(server-centric).
Construda com o J2SE (Java 2 Platform Standard Edition) a
plataforma J2EE adiciona a capacidade necessria para prover uma
completa, estvel, segura e rpida plataforma java a nveis exigidos
por empresas. Ela adiciona valor pela significativa reduo de custo
e complexidade de desenvolvimento e deploying de solues multicamadas, resultando em servios que podem ser rapidamente
instalados e facilmente mantidos ou melhorados.

J2EE

Principais Tecnologias

RMI, RMI-IIOP, EJB


Java API for XML-Based RPC (JAX-RPC),
JavaServer Pages,
Java Servlets, Enterprise
JavaBeans components,
J2EE Connector Architecture,
J2EE Management Model,
J2EE Deployment API,
Java Management Extensions (JMX),

24/04/04 01:42:55
jp@psique.org http://www.psique.org/cursos

14

Curso J150

J2EE Authorization Contract for Containers,


Java API for XML Registries (JAXR)
J2EE Principais Tecnologias
Java Message Service (JMS),
Java Naming and Directory Interface (JNDI),
Java Transaction API (JTA),
CORBA, e
JDBC data access API.

Objetivo de J2EE
Principalmente:

Facilitar aplicaes transacionais distribudas.

Velocidade para disponibilizar aplicaes

Desenvolvimento baseado em componentes reusveis

Segurana

Flexibilidade no controle de transaes

Aplicaes Distribudas e em mltiplas camadas

A plataforma J2EE utiliza modelo multi-camadas para as


aplicaes. A lgica da aplicao dividida em componentes de
acordo com a funo.

24/04/04 01:42:57
jp@psique.org http://www.psique.org/cursos

15

Curso J150

J2 EE
J2 EE
Aplicao 1 Aplicao 2
Aplicao
clie nte

Pg inas
dinm icas

JSP
EJB

EJB

ban co

ban co

Ca m a d a d o
clien t e
Ca m a d a d a
Web
Ca m a d a d e
Neg cio

Mq u in a d o
clien te
Con t in er WEB
Con t in er J2EE
EIS - Geren ciad or es d e
Ban co d e Dad os / ERP/ Legad o

Mltiplas camadas

Os componentes da camada do cliente so executados na


mquina do cliente.
Os componentes da camada Web rodam no servidor J2EE
Os componentes da camada de negcio so executados no
servidor J2EE.
Os componentes da camada EIS (Enterprise Information System)
so executadas em um servidor EIS (SGBD, CICS, IMS...).

Os componentes J2EE

Aplicaes J2EE so construdas com componentes. Um


componente J2EE uma unidade de software que montado em
uma aplicao J2EE com suas classes e arquivos que se
comunicam com outros componentes. A especificao J2EE define
os seguintes componentes J2EE:

24/04/04 01:42:59
jp@psique.org http://www.psique.org/cursos

16

Curso J150

Aplicaes clientes (cliente)


Applets (cliente)
Enterprise JavaBeans (EJB) So componentes de negcio
(servidor)

Todos os componentes J2EE so escritos em JAVA e so compilados


da mesma maneira que qualquer programa da linguagem. A
diferena entre os componentes J2EE e os demais componentes Java
normais que os componentes J2EE so montados em aplicaes e
instalados em servidor de acordo com as especificaes J2EE onde
so executados e gerenciados por um servidor J2EE (servidor de
aplicaes).

Clientes J2EE
Clientes J2EE podem ser Web ou aplicaes (applets ou no).
Clientes Web J2EE

Um cliente WEB consiste de duas partes: pginas web dinmicas


contendo vrios tipos de linguagens de marcao (HTML, XML...),
que so geradas por componentes web e um navegador que trata
as pginas recebidas do servidor.
Clientes WEB so normalmente chamados de clientes magros
(thin client)

Clientes J2EE Applets

Uma pgina web recebida da camada web pode incluir uma


applet. A applet uma pequena aplicao cliente escrita em java
que executada na mquina virtual instalada no navegador do
cliente.
Uma aplicao cliente J2EE executada na mquina do cliente e
prov uma maneira para os usurios utilizarem tarefas que
requerem uma interface mais rica que a disponibilizada pelas
linguagens de marcao. Elas tipicamente tem uma interface
grfica (GUI) criada em Swing ou AWT .

24/04/04 01:43:06
jp@psique.org http://www.psique.org/cursos

17

Curso J150

Arquitetura de componentes JavaBeans


As camadas cliente e servidor podem tambm incluir componentes
baseados na arquitetura de JavaBeans para gerenciar os dados
entre a aplicao cliente ou applet e componentes que esto sendo
executados no servidor de aplicaes J2EE. Os JavaBeans no so
considerados componentes J2EE.

Comunicao com o Servidor


Abaixo os vrios elementos que fazem parte da camada cliente. O
cliente se comunica com a camada de negcios que est no servidor
de forma direta ou se for um cliente WEB atravs de JSPs e/ou
servlets em um continer WEB.
Cam ad a
clien
t es e r WEB,
Brow
pg inas WEB, Apple ts .

Ca m ad a
WEB

Ca m a d a
de
Neg cio s

Aplicao clie nte

Ser vid or J2EE

Componentes Web
Os componentes WEB de J2EE podem ser servlet ou JSP. Servlets
so Classes em Java que dinamicamente processam requisies e
constroem respostas (normalmente em XML e HTML). Pginas JSP
so como servlets mas admitem uma forma mais natural de criar
contedo esttico.
Pginas estticas (HTML) e applets so empacotadas com os
componentes WEB durante a montagem, mas no so consideradas
como componentes WEB pela especificao J2EE. Classes utilitrias

24/04/04 01:43:07
jp@psique.org http://www.psique.org/cursos

18

Curso J150

tambm podem ser empacotadas mas tambm no so


consideradas.

Componentes de Negcios
Regras de negcio so controladas por enterprise beans sendo
executadas na camada de negcio.
Sem J2EE a figura a seguinte:

Com J2EE a figura muda para a seguinte:

24/04/04 01:43:10
jp@psique.org http://www.psique.org/cursos

19

Curso J150

Note que no segundo caso, foi acrescentada uma camada de


negcios.

Enterprise Information System Tier


A camada de ENTERPRISE INFORMATION controlam as
informaes empresariais ou corporativas. Incluem os sistemas de
infraestrutura tais como os Enterprise Resource Planning (ERP),
processamento de transaes em mainframe, bancos de dados, e
outros sistemas de informaes legados. Componentes de
aplicaes J2EE podem necessitar acessar sistemas de informaes
empresariais para conectividade de bancos de dados, por exemplo.
ContinersJ2EE.

Continers J2EE
Por que utilizar um continer?
Normalmente, aplicaes clientes magras, so difceis de escrever
porque envolvem muitas linhas de cdigo para controlar transaes
e o estado, mltiplas threads, pools de recursos e outros detalhes
complexos de baixo nvel. Os componentes baseados na arquitetura
J2EE tornam as aplicaes J2EE fceis de escrever porque a lgica
24/04/04 01:43:11
jp@psique.org http://www.psique.org/cursos

20

Curso J150

de negcio est organizada em componentes reusveis e o continer


se encarrega dos detalhes de comunicao.

Servios do Continer
Continers so a interface entre um componente as funcionalidades
de baixo nvel especficas a uma plataforma que suportam os
componentes. Antes que um componente J2EE possa ser executado,
ele precisa ser montado (assembled) em uma aplicao J2EE e ser
implantado (deployed) no continer.

Servios do continer Montagem


O processo de montagem (ASSEMBLY) consiste em configurar cada
componente da aplicao J2EE e configurar a aplicao J2EE. Estas
configuraes incluem, servios (segurana, gerenciamento de
transaes, lookups JNDI Java Naming and Directory Interface,
etc).

Servios J2EE
Os continers J2EE disponibilizam um conjunto de servios para
facilitar a utilizao, so servios que sob a responsabilidade do
continer simplificam para o Desenvolvedor.
Modelo de segurana Quem pode acessar
Modelo de transaes Relaes entre mtodos que compem um
transao (para que sejam tratados como uma nica transao).
JNDI lookup Interface unificada para servios de nomes e
diretrios.
Modelo de Conectividade Remota - gerencia a comunicao de
baixo nvel entre clientes e EJBs. Depois que um EJB criado, um
cliente invoca um mtodo nele como se ele estivessem na mesma
24/04/04 01:43:13
jp@psique.org http://www.psique.org/cursos

21

Curso J150

mquina virtual.

Tipos de continer
O processo de deployment instala os componentes da aplicao
J2EE nos continers.

Empacotamento
Uma aplicao J2EE empacotada em um Enterprise Archive
(EAR). Um EAR um JAR com a extenso .ear. Um arquivo EAR
contem os mdulos J2EE. O uso de arquivos EAR e mdulos torna
possvel montar uma quantidade diferente de aplicaes J2EE
reutilizando componentes.

EAR
JAR

24/04/04 01:43:15
jp@psique.org http://www.psique.org/cursos

WAR

22

Curso J150

Mdulo J2EE
Um mdulo J2EE consiste em um ou mais componentes J2EE para o
mesmo tipo de continer e um descritor de implantao
(componente deployement descriptor).
O deployment descriptor um documento XML com a extenso .xml
que descreve as configuraes dos componentes. Um descritor de
um EJB declara os atributos de transaes e de segurana.
A vantagem utilizando a forma declarativa, que as configuraes
podem ser alteradas sem modificao do cdigo. Em tempo de
execuo o servidor J2EE l o descritor e reage de acordo com as
configuraes.

Mdulos tipos
Mdulos EJBs contm os arquivos .class dos EJBs e o EJB
deployment descriptor. So empacotados em arquivos com a
extenso .jar.
Mdulos WEB contm arquivos JSP, .class dos servlets, imagens e
HTMLs, alm do Web deployment descriptor. Os mdulos WEB so
empacotados em arquivos JAR com a extenso .war (Web Archive).

Mdulos tipos
Resource adapter modules, contm todas as interfaces Java, classes,
bibliotecas nativas e outras documentaes, implementa a
24/04/04 01:43:20
jp@psique.org http://www.psique.org/cursos

23

Curso J150

arquitetura de conectores (JCA = J2EE Connector Architecture)


para um EIS particular. Os mdulos so empacotados em arquivos
JAR com a extenso .rar (Resource adapter Archive).
Mdulos de aplicaes clientes contm arquivos .class e um
application client deployment descriptor. Normalmente so
empacotados com arquivo JAR com a extenso .jar.

Web Services
So servios baseados em Web que utilizam protocolos abertos e
baseados em XML. So fceis de escrever Web services e Clientes
com as APIs de XML de J2EE.
Tudo que se precisa passar os parmetros para chamadas de
mtodo e processar os dados retornados. Para web service do tipo
(document-oriented), enviar documentos contendo dado de um
servio. Nenhum tipo de programao de baixo nvel necessria.

Web Services Transporte


Normalmente as requisies dos clientes e respostas dos servios
so transitidas utilizando HTTP-SOAP (Simple Object Access
Protocol over HTTP) Outros protocolos so suportados, tais como
JMS e SMTP. Isto possibilita a conversa entre plataformas
diferentes (J2EE x .Net por exemplo).

Papis de desenvolvimento
A utilizao de mdulos reusveis tornam possvel dividir o
desenvolvimento da aplicao e o processo de implantao em
papis distintos.

J2EE Product Provider


So empresas que desenham e mantm disponvel para aquisio
plataforma J2EE, as APIs e outras funcionalidades definidas na
24/04/04 01:43:22
jp@psique.org http://www.psique.org/cursos

24

Curso J150

especificao J2EE. Normalmente so empresas que produzem e/ou


vendem sistemas operacionais, gerenciadores de bancos de dados e
servidores de aplicao, servidores WEB que implementam a
especificao J2EE.

J2EE Tool Provider


O Provedor de ferramentas quem oferece as ferramentas para
facilitar a montagem e manuteno de aplicaes J2EE, ferramentas
para modelagem de dados, ferramentas para montagem de
componentes. As ferramentas desenvolvidas pelo Tool Provider so
utilizadas pelos Component providers, assemblers e deployers.

J2EE Application Component Provider


O provedor de componentes de aplicao a pessoa que cria os
componentes Web, EJBs, applets e aplicaes clientes que sero
utilizados nas aplicaes J2EE.

Enterprise Bean Developer


Um desenvolvedor de EJB executa as seguintes tarefas para
entregar um jar com um EJB:

Cria e compila o cdigo fonte

Especifica o deployment descriptor

Empacota os arquivos .class e deployment descriptor em um


arquivo jar

Web Component Developer


O desenvolvedor de componentes WEB o responsvel pelo arquivo
WAR contendo os componentes WEB.

Escreve e compila os cdigos dos servlets

Escreve os JSPs e HTMLs

24/04/04 01:43:24
jp@psique.org http://www.psique.org/cursos

25

Curso J150

Especifique os descritores dos componentes web

Empacota os .class, .jsp e .html em um arquivo WAR.

J2EE Application Client Developer


Um desenvolvedor de aplicaes cliente executa as seguintes
tarefas para entregar um arquivo JAR contendo a aplicao J2EE
cliente:

Escreve e compila o cdigo fonte.

Especifica o deployment descriptor para o cliente

Empacota os arquivos .class e deployment descriptor em arquivos


JAR.

Application Assembler
o Montador de aplicaes, a empresa ou pessoa que recebe os
componentes JAR da aplicao do Component Provider e os monta
em um arquivo EAR. O assembler ou deploy pode editar o
deployment descriptor diretamente ou usar usar ferramentas que
manuseiam as TAGs XML dos descritores.

Monta os arquivos EJB JAR e WAR criados nas fases anteriores


em um EAR (Enterprise Archive).

Especificam o descritor para a aplicao

Verificam que o contedo do arquivo EAR esto bem formatados e


de acordo com as especificaes J2EE.

Application Deployer e Administrador


O Distribuidor e administrador a empresa ou pessoa que
configura e distribui as aplicaes J2EE, administra a infra24/04/04 01:43:26
jp@psique.org http://www.psique.org/cursos

26

Curso J150

estrutura de computao e rede onde as aplicaes J2EE so


executadas e vigia o ambiente. As tarefas incluem coisas como
configurar os controles de transao, atributos de segurana e
especificar as conexes a Bases de Dados.
Durante a configurao o distribuidor segue as instrues
fornecidas pelo provedor de componentes de aplicao para
resolver as dependncias, especificar as configuraes de
segurana e atributos de transaes. Durante a instalao, o
distribuidor move os componentes da aplicao para o servidor e
gera as classes e interfaces especficas do continer.
O distribuidor e administrador do sistema, executa as seguintes
tarefas para instalar e configurar uma aplicao J2EE:

Adiciona no servidor J2EE a aplicao J2EE (pacote EAR) criada


na fase anterior

Configura a aplicao J2EE para o ambiente operacional


modificando o deployment descriptor da aplicao J2EE.

Verifica que o contedo do EAR est bem formatado e compatvel


com as especificaes J2EE.

Instala o EAR da aplicao J2EE no servidor J2EE.

24/04/04 01:43:28
jp@psique.org http://www.psique.org/cursos

27

Curso J150

Servidor de Aplicaes
Para utilizar-mos J2EE, necessitamos de um continer J2EE. Para
este curso utilizaremos o JBOSS, por ser um dos mais utilizados no
mundo e por ter cdigo livre.

JBOSS
Utilizaremos o JBOSS verso 3.2.3, este software pode ser
encontrado no site:
http://www.jboss.org

O projeto do JBoss foi iniciado em 1.999 como um software de


cdigo aberto para ser continer EJB.
A partir da verso 2.x do JBoss, tornou-se um servidor completo
J2EE.
A verso 3.x a atual e foi desenhada para SOA (service oriented
architecture).

JBoss caractersticas
Design modular totalmente baseado em JMX (Java Management
eXtensions)
Tem hot-deploy
Suporta completamente J2EE 1.3 (EJB, JCA, JSP, JMX, HTTP etc)
Implementao completa de segurana e integrao com JAAS.
Executa clustering de qualquer objeto java (EJB, HTTP, POJO).
Infraestrutura para programao orientada a aspectos (AOP).

JBoss Instalao
Faa o download do pacote binrio do stio do JBoss
(http://www.jboss.org)
24/04/04 01:43:29
jp@psique.org http://www.psique.org/cursos

28

Servidor de Aplicaes

Curso J150

Descompacte o arquivo em um diretrio, utilizando winzip no


Windows ou unzip no linux. No interessa onde est o arquivo,
mas no interessante que existam espaos no nome pois em
algumas situaes nas JVMs da Sun isto tem sido a causa de erros
pelo incorreto tratamento dos espaos na URL.
Crie uma varivel de ambiente chamada JBOSS_HOME para
apontar para o diretrio onde o JBoss foi descompactado.

Acima a estrutura de diretrios do JBoss, os nomes em azul so


nomes de constantes que podem ser obtidas da classe:
org.jboss.system.server.ServerConfig. Os nomes que terminam com
URL podem especificar uma localidade remota expressa por uma
URL.

JBoss Ativao
Para ativar o JBoss, execute o script run.bat (windows) ou run.sh
(linux). Estes scripts esto no diretrio bin.

24/04/04 01:43:31
jp@psique.org http://www.psique.org/cursos

29

Servidor de Aplicaes

Curso J150

JBoss Iniciando o servidor


No nosso ambiente, existe um script para configurao do
ambiente.
windows

linux

cd \j150
setambiente.bat
run
cd ~/j150
. ./setambiente.sh
run.sh

O script setambiente, j configura as variveis necessrias e inclui o


diretrio bin no PATH, isto torna possvel executar o run em
qualquer lugar.
Executando simplesmente os script run, voc estar executando a
configurao default do JBoss. O JBoss vem pr configurado com 3
configuraes: minimal, default e all. Para executar o JBoss na
configurao all, digitar:
windows

run -c all

ou
linux

run.sh -c all

Alguns arquivos de configurao


conf/jboss-service.xml
O arquivo jboss-service.xml define os servios (MBeans) que sero
ativados.

24/04/04 01:43:33
jp@psique.org http://www.psique.org/cursos

30

Servidor de Aplicaes

Curso J150

conf/jbossmq-state.xml
O arquivo jbossmq-state.xml o arquivo de configurao para o
JBossMQ, nele so informados os mapeamentos de usurios e
arquivos.

conf/jndi.properties
O arquivo jndi.properties especifica as propriedades do Contexto
Inicial JNDI que ser utilizado pelo servidor JBoss quando for criado
um InitialContext sem especificao de argumentos no construtor.

conf/log4j.xml
O arquivo log4j.xml configura o framework log4j da Apache usado
pelo servidor.

conf/login-config.xml
O arquivo login-config.xml contm um exemplo de configurao
para autenticao do lado do servidor que utilizada utilizando
segurana baseada em JAAS.

conf/server.policy
o arquivo onde esto configuradas as permisses de Java2
security. O arquivo default simplesmente d todos os acessos a
todos os codebases.

conf/standardjaws.xml
Prov a configurao default para acesso ao antigo JBossCMP EJB
1.1 . A camada cmp foi reescrita no JBoss 3.0 para suportar EJB 2.0.

conf/standardjbosscmp-jdbc.xml
Este arquivo tem a configurao bsica para o JBoss 3.2 EJB 2.0
JBoss CMP.

24/04/04 01:43:35
jp@psique.org http://www.psique.org/cursos

31

Servidor de Aplicaes

Curso J150

conf/standardjboss.xml
O arquivo standardjboss.xml prov as configuraes default do
container.

deploy/http-invoker.sar
O arquivo http-invoker.sar contm o invoker que suporta RMI/HTTP.
E tambm configura os prxies de RMI/HTTP para os servios de
nome JNDI que permitem que o servio JNDI seja acessado por http.

deploy/jbossweb-jetty.sar
O diretrio jboss-web-jetty.sar um MBean desempacotado para a
configurao do engine de servlet Jetty. O SAR desempacotado
para facilitar a ediao dos descritores ( jbossweb-jetty.sar/METAINF/jboss-service.xml)

deploy/jmx-console.war
O diretorio jmx-console.war um aplicao web desempacotada
que prov adaptadores HTML para o JMX MBeanServer. O war
desempacotado para facilitar o acesso aos descritores jmxconsole.war/WEB-INF/*.xml.

deploy/management/console-mgr.sar , web-console.war
console-mgr.sar e web-console.war so uma aplicao web
experimental que prov um viso mais rica do gerenciamento do
servidor JMX. Voc pode acess-la pela URL
http://localhost:8080/web-console/.

24/04/04 01:43:37
jp@psique.org http://www.psique.org/cursos

32

Servidor de Aplicaes

Curso J150

deploy/hsqldb-ds.xml
o arquivo de configurao do banco de dados Hypersnic 1.7.1.
Serve para configurar o banco de dados utilizado e as fbricas de
conexo. Utiliza o formato de DataSource JCA.

deploy/transaction-service.xml
O arquivo transaction-service.xml configura os servios
relacionados com JTA

JBoss deploy
Como o servidor JBoss suport Hot-Deploy, basta copiar o arquivo
EAR para o diretrio:
${JBOSS_HOME}/server/default/deploy
A aplicao ser automaticamente instalada se o

arquivo EAR estiver bem formatado.

JBoss Tomcat
Esta verso do JBoss j vem integrada ao TOMCAT. Tomcat um
software de cdigo livre do projeto Apache, e o continer WEB
mais utilizado no mundo, alm de ser a implementao de
referncia para JSP e Servlets.

JBoss JMX-Console
Como j dito, o JBoss baseado em JMX. JMX um padro para
manuteno e monitoramento de componentes de hardware e
software de java. Um MBean, um objeto java que implementa o
padro de interface MBean e segue os patterns associados.
24/04/04 01:43:39
jp@psique.org http://www.psique.org/cursos

33

Servidor de Aplicaes

Curso J150

O objetivo das interfaces gerenciveis dos MBeans incluem o


seguinte:

Valores de atributos que podem ser acessados pelo nome

Operaes ou funes que podem ser invocadas

Notificaes ou eventos que podem ser emitidos

O construtor da classe dos MBeans.

JMX define 4 tipos de MBeans:

Standard MBeans Utilizam o estilo de nomeao de JavaBean e


definem estaticamente a interface de gerenciamento. So os mais
comuns.

Dynamic MBeans Precisam implementar a interface


javax.management.DynamicMBean e expe sua interface de
gerenciamento em tempo de execuo quando o componente
instanciado.

Open MBeans So uma extenso dos MBeans dinmicos. Open


MBeans adicionam ao dinmicos, auto-descrio, tipos de dados
amigveis para gerenciamento universal.

Model MBeans So tambm uma extenso dos MBeans


dinmicos. Precisam implementar
javax.management.model.mbean.ModelMBean. Os Model MBeans
simplificam a instrumentao de recursos tendo um
comportamento padro.

Os MBeans em execuo podem ser vistos pelo console. Para isto,


aps a ativao do JBoss, acesse via navegador a url:
http://localhost:8080/jmx-console

Dos servios disponveis, interessante o JNDI-View que serve para


inspecionarmos todos os NAMESPACES JNDI registrados no
servidor.
24/04/04 01:43:41
jp@psique.org http://www.psique.org/cursos

34

Servidor de Aplicaes

Curso J150

Clique no servio service=JNDI-View, procure a operao LIST e


seguida clique no boto INVOKE.

Laboratrio 15_01
Inicializar o JBoss, abra um console e digite:
windows

linux

cd \j150<enter>
setambiente<enter>
run<enter>
cd ~/j150<enter>
. ./setambiente.sh<enter>
run.sh<enter>

Aps muitos displays, se tudo estiver correto, ser apresentada a


mensagem:
15:57:33,134 INFO [Server] JBoss (MX MicroKernel) [3.2.3
(build: CVSTag=JBoss_3_2_3 date=200311301445)] Started in
1m:01s:76ms

Abra outro console e digite:


windows

linux

cd \j150 <enter>
setambiente <enter>
cd laboratorio\15_01 <enter>
cd ~/j150 <enter>
setambiente.sh <enter>
cd laboratorio/15_01 <enter>

Agora utilizaremos o ANT para compilar digitar:


ant <enter>

Se tudo ocorreu bem, o resultado ser: BUILD SUCESSFUL

24/04/04 01:43:43
jp@psique.org http://www.psique.org/cursos

35

Servidor de Aplicaes

Curso J150

Utilizaremos o ANT para o deploy, digitar:


ant deploy <enter>

Se tudo estiver de acordo o resultado ser:


BUILD SUCESSFUL
E na janela do JBOSS haver uma reao civilizada (sem
lanamento de exceptions), e no final se ler:
Para executar o servio, precisamos executar a aplicao cliente,
para isto digitamos
ant run.client <enter>

O resultado ser, na tela cliente:


[java] Peguei o contexto
[java] Tenho a referencia
[java] 3 + 10 = 13

Na tela do servidor:
16:25:07,667 INFO
16:25:07,725 INFO

[STDOUT] Passei pelo ContaBean


[STDOUT] vou somar 3 + 10 = 13

Pronto, executamos o nosso primeiro EJB!


O BeanCliente, atravs de JNDI, obtm uma interface HOME
(ContaHome).
Atravs da interface home, cria um objeto que implementa a
interface remote, este objeto ser tratado como se fosse um
objeto local, mas na realidade ele existe somente no servidor.

24/04/04 01:43:44
jp@psique.org http://www.psique.org/cursos

36

JNDI

Curso J150

JNDI
Java Naming and Directory Interface

Os servidores de nomes
Seu servidor J2EE deve ter implementaes de RMI-IIOP e de JNDI.
Normalmente no bom misturar estas implementaes (utilizar o
pacote RMI-IIOP da sun com a implementao de JNDI da BEA).
Para evitar problemas e facilitar a implementao melhor utilizar
uma nica soluo.
O acesso a um enterprise bean feito atravs de JNDI. Portanto,
importante entender a sua API.
JNDI significa Java Naming and Directory Interface, e uma API
para localizao de recursos em uma REDE por nome,
possibilitando a independncia da localizao fsica.

JNDI Objetivo
JNDI um servio de localizao. Serve para localizar servios na
rede.
O objetivo de um servio de nomes possibilitar a associao de um
nome a um recurso.
Objetiva principalmente:
Mapear um nome a um objeto. Isto chamado de binding.
Localizar um recurso a partir do nome. Esta a operao de
24/04/04 01:43:46
jp@psique.org http://www.psique.org/cursos

37

JNDI

Curso J150

lookup.
Um servio de nomes parecido com o de uma telefonista. Quando
voc quer pedir uma ligao para algum pelo telefone, e voc no
sabe o nmero do telefone da pessoa. Voc liga para o servio de
informaes de sua empresa telefnica, pede que o operador
procure (faa um lookup) a pessoa com a qual voc quer falar. Voc
diz telefonista o nome da pessoa, a telefonista procura o nmero
do telefone da pessoa que voc quer falar e pode discar o nmero
desta pessoa e conect-lo pessoa desejada. Com isto voc no
precisa saber o nmero do telefone, apenas com o nome voc
conseguiu a conexo desejada.
Vrios exemplos de servios de nomes so facilmente encontrados:
O DNS (Internet Domain Name System), mapeia um nome de
mquina (www.psique.org) a um endereo IP (200.155.13.13).
No file system de uma mquina, um nome de arquivo
(c:/bin/autoexec.bat) mapeado para um file handle que um
programa pode usar para acessar o contedo do arquivo.
Em geral, um servio de nomes pode ser utilizado para encontrar
qualquer tipo de objeto genrico, tais como, um handle para um
arquivo no seu hd ou uma impressora na rede.
Para procura um objeto em um sistema de nomes, voc tem que
fornecer o nome do objeto. O sistema de nomes determina a sintaxe
que o nome deve seguir. Este sintaxe algumas vezes chamado de
naming convention (conveno de nomes).

A conveno do DNS, chama por componentes no nome do DNS


ordenados da direita para a esquerda e delimitados por Ponto,
Quer dizer que pelo DNS, www.psique.org, identifica uma
entrada no DNS com o nome www (host) no servidor psique.org.

A conveno para LDAP (Lightweight Directory Access Protocol)


ordena os componentes da direita para a esquerda, delimitando

24/04/04 01:43:48
jp@psique.org http://www.psique.org/cursos

38

JNDI

Curso J150

por vrgula. Ento o nome LDAP (cn=Rolando Lero, o=Bb, c=br),


a entrada cn=Rolando Lero, relativa entrada o=Bb que
relativa entrada c=br. A regra do LDAP que cada componente
do nome precisa ser um par nome/valor com o nome e o valor
separado pelo sinal de =.
JNDI vem como parte de JDK 1.3 e posterior. JNDI oferece dois
servios: um servio de nomeao e um servio de diretrio.
Um servio de nomeao um recurso muito importante em
computao, pois ele encontra um objeto associado e determinado
nome. Um exemplo de um servio popular de nomeao o Internet
Domain Name system (DNS), que mapeia nomes de domnios (como
psique.org) com o endereo IP. No contexto de EJB, um servio de
nomeao encontra um enterprise bean para voc, se voc souber o
nome do bean.
Se um aplicativo cliente quiser chamar um enterprise bean, ele s
precisa fornecer o nome do bean. JNDI encontrar o bean para o
cliente. Assim, no surpresa porque um servio de nomeao
ocupa uma importante funo em EJB.

Objetos de Diretrios
Existe um tipo de objeto localizvel via JNDI que particularmente
importante: um objeto diretrio (ou uma entrada de diretrio).
Um objeto diretrio diferente dos demais objetos pois pode
armazenar atributos com os objetos do diretrio. Estes atributos
podem ser utilizados para uma quantidade muito grande de
propsitos.
Um servio de diretrio uma extenso de um servio de nomeao
para a manipulao de atributos. Um servio de diretrio associa
nomes com objetos e tambm permite queles objetos terem
atributos que descrevam os objetos. Esses objetos permite que voc
busque por um objeto sem conhecer o seu nome. Um exemplo de um
servio de diretrio o Lightweight Directory Access Protocol
(LDAP). Os servios de diretrio no so usados para acessar
24/04/04 01:43:50
jp@psique.org http://www.psique.org/cursos

39

JNDI

Curso J150

enterprise beans.
Com o que se parece um diretrio? O contedo do diretrio o
conjunto de objetos de diretrio conectados normalmente
representado por uma estrutura hierrquica de rvore. Por que
isto? Suponha que o root (n raiz) de sua rvore de diretrio
represente a empresa, um galho do raiz pode representar pessoas
da empresa, outro galho pode representar servios de rede. Cada
ramificao pode ter sub-rvores que decrescem em granularidade
mais e mais, at que se tenha um objeto nico (uma impressora,
uma pessoa).
Osdetalhesdecomoodiretrioestorganizadoconstamemmeta
dados.Osmetadadosdodiretriodefinemaestruturadeseu
diretrio.Osmetadadosdefinemoesquemaqueseusdadosesto
organizados.
Umdiretrionomuitodiferentedeumbancodedados.Umbanco
dedadospodearmazenardados,comodiretrios,Bancodedados
temfuncionalidadesparaalocalizaodedados,damesmaforma
quediretrios.Vocpodepensaremumdiretriocomoumbancode
dadoshierrquicosimplificado.Defato,muitosdiretriosso
implementadoscomumbancodedados.

Atributos
Um objeto de diretrio pode ter atributos. Por exemplo, uma
impressora pode ser representada por um objeto diretrio que tem
como atributos sua velocidade, sua resoluo, quantidade de cores,
etc. Um usurio pode ser representado por um objeto de diretrio
que tem um atributo, EMail, nmeros de telefone, endereo, etc.

Atributo-identificador
Um atributo tem um identificador de atributo e um conjunto de
valores de atributo. Um identificador de atributo identifica um
atributo independentemente de seu valor. Por exemplo, duas
diferentes contas em um computador podem ter um atributo
'EMAIL' . O atributo 'EMAIL' pode ser utilizado como identificador.
24/04/04 01:43:52
jp@psique.org http://www.psique.org/cursos

40

JNDI

Curso J150

Um valor cujo contedo identifica unicamente um recurso.

Diretrio e Servio de Diretrio


Um diretrio um conjunto conectado de objetos de diretrio. Um
servio de diretrios um servio que prov operaes para
criao, adio, remoo e modificao de atributos associados a
um objeto em um diretrio. O servio acessado atravs de sua
interface.

Buscas e Filtros
Vocpodebuscar(lookup)umobjetodeumdiretrioinformadoo
nomedoservio.Alternativamente,muitosdiretrios,comoos
baseadosemLDAP,suportambuscasbaseadasemumaexpresso
lgicanaqualvocespecificaosatributosqueoobjetoouqueos
objetosdevempossuir.Arequisiochamadasearchfilter.Este
estilodebuscatambmchamadodebuscareversa(reverselookup)
oubuscabaseadaemcontedo(contentbasedsearching).

Binding
A associao de um nome com um objeto chamada BINDING. Por
exemplo, um nome de arquivo atribudo ao arquivo. A entrada
DNS contm uma atribuio mquina que contm o endereo IP.
Um nome LDAP atribudo entrada LDAP do servidor.

Resumindo, a ligao:
NOME
RECURSO

Referncias e Endereos
Dependendo do servio de nomes, alguns objetos no podem ser
armazenados diretamente, isto , uma cpia do objeto no pode ser
colocada no servio de nomes. No lugar disto, uma referncia
24/04/04 01:43:54
jp@psique.org http://www.psique.org/cursos

41

JNDI

Curso J150

armazenada. Um ponteiro ou referencia ao objeto armazenada no


servio de nomes. Uma referncia uma informao sobre como
acessar o objeto. Isto normalmente uma representao mais
compacta do que incluir o prprio objeto. Pela referncia, pode-se
contactar o objeto e obter mais informaes diretamente do objeto.

Contexto
Um contexto um conjunto de atribuies (bindings) nome-objetos.
Cada contexto segue uma conveno de nomes). Um contexto
disponibiliza uma forma de resoluo (lookup) para obter um objeto
que prov operaes sobre como acessar os nomes e objetos,
atribuir um objeto a um nome (bind) e retirar a atribuio (unbind),
alm de possibilitar a listagem dos nomes e recursos. Um nome em
um contexto pode conter a ligao a outro contexto (chamado sub
contexto) que tem a mesma conveno de nomes.
Exemplo:
Um diretrio: ~/j150 contm um subdiretrio ambiente. O
subdiretrio ambiente um sub contexto do contexto ~/j150

Sistema de Nomes
Um sistema de nomes um conjunto de contextos que so
interligados e seguem as mesmas convenes.
Por exemplo, um sistema que implementa o sistema de nomes DNS,
um sistema que se comunica usando um sistema de nomes LDAP

Namespace
Um namespace (espao de nomes) um conjunto de nomes em um
sistema de nomes. Por exemplo, o file system do UNIX tem um namespace
consistindo de todos os nomes de arquivos e diretrios no file system. O
namespace do DNS contm nomes de domnio DNS e entradas. O
namespace de LDAP contem entradas de LDAP.
Em um file system do WINDOWS: Se os contextos e sub contextos so os

24/04/04 01:43:55
jp@psique.org http://www.psique.org/cursos

42

JNDI

Curso J150

diretrios a unidade (drive) pode ser o namespace.

Combinando Nomes e Servios de Diretrio


Diretrios pode organizar seu objetos em uma hierarquia. Por
exemplo, LDAP organiza todos os objetos em uma rvore chamada
Directory Information Tree (DIT). Na rvore, um objeto organizao
por exemplo, pode conter um grupo de objetos que podem por sua
vez conter pessoas.

Aplicaes Java e Diretrios


Servios de diretrios so componentes vitais para computao em
rede. usando um servio de diretrios, voc pode simplificar
aplicaes e a administrao destas aplicaes, centralizando a
armazenagem de informaes compartilhadas.

O diretrio como um armazm de objetos


Os diretrios podem ser utilizados como armazm de objetos, sendo
desta forma simples armazenar e recuperar dados de diretrios.

JNDI Viso Geral


A API JNDI (Java Naming and Directory Interface), prov
funcionalidades para que aplicaes escritas em Java utilizem
nomes e diretrios. definida de uma forma independente de
qualquer implementao de servio de diretrios. na realidade
assim como JDBC uma implementao do pattern BRIDGE para
diversos tipos de servios de diretrios.

Benefcios de JNDI

um sistema unificado para acessar qualquer tipo de servio de


diretrio

24/04/04 01:43:57
jp@psique.org http://www.psique.org/cursos

43

JNDI

Curso J150

JNDI uma API nica que acessa diferentes diretrios com


diferentes protocolos

JNDI isola a aplicao do protocolo utilizado

JNDI extensvel. Futuros provedores de diretrios podem


acrescentar seus servios de diretrios API JNDI sem afetar o
cdigo dos clientes.

Usando JNDI, voc pode ler e gravar objetos Java de diretrios.

Voc pode ligar diferentes tipos de diretrios (LDAP com NDS por
exemplo) visualizar esta combinao como se fosse um nico
diretrio. (NDS = Novell Directory Services).

JNDI suportado pela Sun, e uma extenso padro de Java.

Arquitetura

A arquitetura de JNDI consiste de uma API e uma SPI (service


provider interface). Aplicaes Java usam a API JNDI para acessar
vrios servios de nomes e diretrios. A SPI habilita que vrios
servios sejam plugados de forma transparente, possibilitando
que aplicaes java utilizem-nos atravs da API JNDI. No JBoss,
existe uma implementao que chamada de JBoss naming
baseada nas classes SPI. O cliente no precisa tomar
conhecimento da SPI, ele apenas se preocupa com a API.

Utilizao
Para utilizar JNDI, voc precisa ter as classes JNDI e um ou mais
provedores de servio. O Java 2SDK v1.3 inclui trs provedores de
servio:
LDAP
CORBA (Common Object Request Broker Architecture) Common
Object Services (COS) name service
24/04/04 01:43:59
jp@psique.org http://www.psique.org/cursos

44

JNDI

Curso J150

Java Remote Method Invocation (RMI) Registry


Outros podem ser encontrados em :
http://java.sun.com/products/jndi/serviceproviders.html

A API JNDI
A API JNDI dividida em 5 pacotes

javax.naming

javax.naming.directory

javax.naming.event

javax.naming.ldap

javax.naming.spi

javax.naming.Context

O pacote javax.naming contm classes e interfaces para acessar os


servios de nome.
Das cinco interfaces, dez classes e vrias excees definidas na API,
existe uma classe que deve ser conhecida: InitialContext e duas
interfaces: Context e Name. Ao escrever um aplicativo cliente que
use o servio de um enterprise bean, voc precisa entender bem
dois membros do pacote javax.naming: a interface Context e a
classe InitialContext.

Context
A interface Context representa um contexto de nomeao,
24/04/04 01:44:01
jp@psique.org http://www.psique.org/cursos

45

JNDI

Curso J150

consistindo em um conjunto de associaes nome-a-objeto. Essa


associao em termos de JNDI chamada de binding. A interface
Context importante, pois ela contm mtodos para examinar e
modificar as ligaes nome-a-objeto.

A interface javax.naming.Context, a principal interface para


procurar, ligar, desligar, renomear, criar e destruir sub
contextos.
A operao mais comum o lookup(). Informe ao lookup o nome
do objeto e o retorno ser a referncia para o objeto.
O mtodo lookup() retorna uma referncia a um objeto, dado o
nome do objeto. H duas sobrecargas desse mtodo. As assinaturas
de ambas as sobrecargas so:
public Object lookup(javax.naming.Name name) throws
javax.naming.NamingException
public Object lookup(String name) throws
javax.naming.NamingException

Exemplo:
Printer printer = (Printer)ctx.lookup(impressoraDois):
printer.print(report);

O mtodo lookup usado para obter uma referncia a um objeto


home do enterprise bean. A segunda sobrecarga do mtodo lookup
bem direta. Voc simplesmente passa a string com o nome do objeto
e obtm uma referncia ao objeto home do bean.
O mtodo lookup lana uma exceo do tipo
javax.naming.NamingException se a resoluo ao nome falhar.

Names
A noo de um nome fundamental para JNDI. O sistema de nomes
24/04/04 01:44:03
jp@psique.org http://www.psique.org/cursos

46

JNDI

Curso J150

determina qual a sintaxe que o nome deve seguir. A sintexe do


sistema de nomes permite que o usurio separe a string nas
representaes das partes do nome e em seus componentes. A
interface javax.naming.Name representa um nome genrico como
uma seqncia ordenada de componentes. Os componentes de um
nome so numerados. Os ndices de um nome com N componentes
vo de 0 a N-1. O mais significativo componente o ndice 0. Um
nome vazio no tem componentes. Existem dois tipos de nomes:
Composite e Compound.

Composite
So os nomes cujas partes na realidade so compostas por mais de
um namespace. Exemplo, um recurso de scp:
psique.org:/home/psique
(psique.org um namespace que identifica um host e /home/psique
outro namespace que identifica um diretrio de um file system).

Compound
So os nomes derivados de um namespace hierrquico. Exemplo
pode ser um caminho: \tmp\arquivo.txt

Bindings
Um bind a ligao de um nome a um recurso, podem ser
mostrados pelos mtodos:

listBindings() retorna um object enumeration de ligaes nomeobjeto. Cada ligao representada por um instncia da classe
javax.naming.Binding. Uma ligao uma tupla contendo o nome
do objeto atribudo, o nome da classe do objeto e o objeto.

list() similar a listBindings(), exceto que retorna uma


enumerao da classe javax.naming.NameClassPair que contm

24/04/04 01:44:05
jp@psique.org http://www.psique.org/cursos

47

JNDI

Curso J150

um nome de objeto e um nome de uma classe de objeto. til


para aplicaes como browsers que precisam descobrir
informaes sobre a relao dos objetos em um contexto mas no
precisam dos objetos. Apesar de listBindings() fornecer toda a
informao, uma operao potencialmente mais cara.

Reference
A classe javax.naming.Reference, utilizada para representar a
referncia a um objeto.

A classe javax.naming.InitialContext
Em JNDI, todas as operaes com nomes e diretrios so
executadas em relao a um contexto. No existe um contexto raiz
absoluto. Existe uma classe InitialContext que prov um ponto
inicial para as operaes de nomes e diretrios. Uma vez que se
obtenha um contexto inicial, ele ser utilizado para busca de outros
contextos e objetos.
Para um contexto, voc precisa definir uma srie de propriedades
para o ambiente do contexto. Por exemplo, uma resoluo de
nomeao pode ser restrita s a usurios autorizados. Neste caso,
voc cria um objeto java.util.Properties e usa o mtodo put para
acrescentar pares chave/valor, representando quaisquer
propriedades de nomes e valores necessrios.
Todas as operaes com nomes so feitas com uma implementao
da interface Context. Para obter uma instncia de context, existe a
classe concreta javax.naming.InitialContext (que implementa a
interface Context). Quando se cria um InitialContext, ele
inicializado com propriedades de ambiente. Considerar: a
ocorrncia de property passado como parmetro para o construtor,
parmetros para applet e propriedades do sistema. Em seguida
todos os arquivos jndi.properties encontrados no classpath.

24/04/04 01:44:07
jp@psique.org http://www.psique.org/cursos

48

JNDI

Curso J150

Exemplo de arquivo de propriedades jndi.properties

### Exemplo de arquivo de propriedades


java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

Ao acessar um enterprise bean voc precisa fornecer duas


propriedades. A primeira a propriedade de ambiente
java.naming.factory.initial. O valor dessa propriedade o nome de
classe totalmente qualificado que ser usado para criar o contexto
inicial.
A segunda propriedade java.naming.provider.url. Essa uma
propriedade de ambiente, cujo valor especifica informaes de
configurao para uso do servio de provedor.
Ambas as propriedades de nomes esto convenientemente contidas
em dois campos estticos na interface Context. So eles
Context.INITIAL_CONTEXT_FACTORY e Context.PROVIDER_URL,
respectivamente.
Com o objetivo de acessar um enterprise bean, preciso
acrescentar essas duas propriedades ao mtodo java.util.Properties
usando o seu mtodo put, como a seguir:
import java.util.Properties;
...
//Cria um objeto properties
Properties properties = new Properties();
// Adiciona duas propriedades
properties.put(Context.INITIAL_CONTEXT_FACTORY ,
org.jnp.interfaces.NamingContextFactory);
properties.put(Context.PROVIDER_URL, localhost:1099);

Porque essas propriedades so necessrias para criar o contexto

24/04/04 01:44:09
jp@psique.org http://www.psique.org/cursos

49

JNDI

Curso J150

inicial, o objeto Properties passado ao construtor da classe


InitialContext, como abaixo:

javax.naming.InitialContext jndiContext = new


javax.naming.InitialContext(properties);

Resumindo, obter uma referncia a um enterprise bean envolve as


seguintes etapas:
1 Criar um objeto java.util.Properties
2 Acrescentar as propriedades necessrias ao objeto
java.util.Properties para construir o contexto inicial.
3 - Construir um objeto javax.naming.InitialContext
4 Usar o mtodo lookup da interface javax.naming.Context para
obter uma referncia ao objeto home do bean, passando o nome do
bean.

import java.util.Properties;
import javax.naming.*;
...
//Cria um objeto properties
Properties properties = new Properties();
// Adiciona duas propriedades
properties.put(Context.INITIAL_CONTEXT_FACTORY ,
org.jnp.interfaces.NamingContextFactory);
properties.put(Context.PROVIDER_URL, localhost:1099);
try {
javax.naming.InitialContext jndiContext = new
javax.naming.InitialContext(properties);
// Pegar a referencia ao objeto:
Object ref = jndiContext.lookup(Somador);
}

24/04/04 01:44:10
jp@psique.org http://www.psique.org/cursos

50

JNDI

Curso J150

Ambiente - ENC
JNDI um aspecto fundamental da especificao J2EE. Um dos
principais usos o isolamento do cdigo dos componentes com o
ambiente onde o cdigo ser instalado (continer). O ambiente dos
componentes da aplicao algumas vezes chamado de Enterprise
Naming Context (ENC). responsabilidade do continer tornar o
ENC disponvel para o componente do continer na forma de um
contexto de JNDI. O ENC utilizado pelos participantes envolvidos
no ciclo de vida dos componentes J2EE das seguinte forma:
1. A lgica de negcio dos componentes deve ser codificada para
acessar informaes do ENC. O Component Provider usa os
descritores padres do componente para especificar as entradas
ENC necessrias. As entradas so declaraes das informaes e
recursos que o componente ir precisar no momento de execuo
2. O continer disponibiliza ferramentas que permitem mapear as
referncias ENC feitas pelo component developer para o
ambiente do continer.
3. O component deployer usa ferramentas para preparar o
componente para a instalao final.
4. O continer usa as informaes do pacote de deployment para
completar o ENC a runtime.
Exemplo de acesso ao ENC

// Obtendo os componentes ENC


Context ctx = new InitialContext();
Context compEnv = (Context) iniCtx.lookup(java:comp/env);

O ENC um namespace isolado, apenas para leitura que os


componentes da aplicao pode utilizar para ficarem independentes
do ambiente onde sero instalados. O ENC isolado dos outro
componentes pois cada um define seu prprio ENC.
Todos os contextos do namespace java:, so visveis somente na
mquina virtual.
24/04/04 01:44:12
jp@psique.org http://www.psique.org/cursos

51

JNDI

Curso J150

A especificao J2EE recomenda que todos os recursos devem ser


organizados em sub contextos do ambiente da aplicao, usando
diferentes sub contextos para cada tipo de recurso gerenciado.

DataSource de JDBC devem ser declaradas em


java:comp/env/jdbc

JMS deve estar em java:comp/env/jms

JavaMail no subcontexto java:/comp/env/mail

URL deve estar em java:comp/env/url

Exemplo de um WEB.XML

<web>
...
<servlet>
...
</servlet>
...
<!-- JDBC DataSource (java:comp/env/jdbc) -->
<resource-ref>
<description> Default DS </description>
<res-ref-name>jdbc/DefaultDS</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
...
</web>

Exemplo de acesso:

Context ctx = new InitialContext();


javax.sql.DataSource ds = (javax.sql.DataSource) ctx.lookup
24/04/04 01:44:14
jp@psique.org http://www.psique.org/cursos

52

JNDI

Curso J150

(java:comp/env/jdbc/DefaultDS);

Criao de uma cpia do beans


Usando JNDI voc conseguiu obter uma referncia ao objeto home
do bean. A prxima etapa criar uma cpia do bean no servidor.
Isso feito usando o mtodo create da interface home.
Porm, a referncia que voc obteve no objeto home do bean um
objeto RMI do tipo java.lang.Object. Para chamar o mtodo create
do objeto home, primeiro preciso criar um cast no objedct para a
interface home:
SomadorHome home = (SomadorHome) ref;

Neste exemplo, ref a referncia obtida da busca do nome pelo


mtodo lookup.
Para ficar de acordo com RMI-IIOP, voc precisa usar um outro
mtodo para a transformao anterior. Precisamos utilizar o mtodo
esttico narrow da classe javax.rmi.PortableRemoteObject. Esse
mtodo usado para garantir que o objeto de um tipo de interface
remota ou abstrata possa ser classificado para o tipo desejado. A
assinatura desse mtodo :
public static Object narrow(Object narrowFrom, Class narrowTo)
throws ClassCastException

Aqui, narrowFrom o objeto a verificar e narrowTo o tipo


desejado. Se narrowFrom no puder ser convertido para narroTo, o
mtodo lanar uma ClassCastException.
SomadorHome home =
(SomadorHome) PortableRemoteObject.narrow(
ref ,
SomadorHome.class);

24/04/04 01:44:16
jp@psique.org http://www.psique.org/cursos

53

JNDI

Curso J150

Tendo um objeto home, ento voc pode chamar o mtodo create da


interface home para criar o bean:
Somador somador = home.create();

Depois, voc livre para chamar quaisquer mtodos expostos pela


interface Somador. No nosso exemplo d para executar:
int i = somador.soma(1,2);

Exceptions
A API JNDI define um hierarquia de exceptions que podem ser
lanadas nas operaes com nomes e diretrios. A classe raz
javax.naming.NamingException.

Pacote: javax.naming.directory
Estende o pacote javax.naming, adicionando funcionalidades para
acessar os servios de diretrios. Este pacote deixa aplicaes
recuperarem atributos associados com objetos armazenados em
diretrios e a buscar objetos usando atributos.

O contexto do diretrio
A interface javax.naming.directory.DirContext representa o
contexto de um diretrio. E define mtodos para examinar e
alterar atributos associados a um objeto diretrio.
Utilize: getAttributes() para recuperar os atributos e
modifyAttributes() para modific-los.
Cada contexto de diretrio um contexto. Um objeto diretrio de
uma pessoa podem conter atributos sobre a pessoa bem como
prover um contexto de nomes objetos da pessoa, tais como, as
impressoras e arquivos da pessoa, parentes da pessoa,
subordinados pessoa, etc...

24/04/04 01:44:18
jp@psique.org http://www.psique.org/cursos

54

JNDI

Curso J150

Buscas
Os contexto de diretrio contm mtodos para efetuar buscas
baseadas no contexto, atravs do mtodo search().
Para obter uma referncia a um recurso precisamos das seguintes
etapas:

Criar um objeto java.util.Properties

Acrescentar as propriedades necessrias ao objeto


java.util.Properties para construir o contexto inicial

Construir um objeto javax.naming.InitialContext

Usar o mtodo lookup() da interface javax.naming.Context para


obter uma referncia ao objeto.

Laboratrio 20_01
Abrir um console e digitar:
windows

linux

cd \j150
setambiente
cd laboratorios\20_01
cd ~/j150
setambiente.sh
cd laboratorios/20_01

Este exemplo utiliza JNDI para acessar o filesystem da mquina. O


resultado de lookup() um objeto java.io.File. Usa uma API da SUN
(veja no diretrio lib)

Laboratrio 20_02
Abrir um console e digitar:
windows
linux

24/04/04 01:44:20
jp@psique.org http://www.psique.org/cursos

cd \j150\laboratorios\20_02
cd ~/j150/laboratorios/20_02

55

JNDI

Curso J150

Este exemplo utiliza JNDI provido pelo Jboss (jnp = JBoss Naming
Provider).

Laboratrio 20_03
Abrir um console e digitar:
windows
linux

cd \j150\laboratorios\20_03
cd ~/j150/laboratorios/20_03

Este exemplo utiliza JNDI provido pelo Jboss.


Abra um navegador em:
http://localhost:8080/web-console
Selecione System/JMX Beans/JBoss/JNDI View
Carregando o servio, clique no boto Invoke da operao list
Examine o resultado.

24/04/04 01:44:21
jp@psique.org http://www.psique.org/cursos

56

ANT Noes bsicas de


utilizao

Curso J150

ANT Noes bsicas de


utilizao
ANT O que
O ANT uma ferramenta do projeto Apache, feita em JAVA que
serve para automatizar a construo, instalao e deploy (upload
para o servidor) de aplicaes.
Tem duas grandes vantagens sobre as outra ferramentes: multi
plataforma, baseada em XML

ANT Projeto Apache


ANT cdigo livre, distribudo sob a licena Apache 2.0.
Stio do ANT:
http://ant.apache.org

ANT Documentao
A documentao do ANT muito bem feita e completa, est
instalada no sub-diretrio docs do ANT_HOME (local onde o ANT foi
instalado).

ANT Execuo
Para executar o ANT:
Se a instalao estiver de acordo, basta digitar:
ant <enter>

24/04/04 01:44:23
jp@psique.org http://www.psique.org/cursos

57

ANT Noes bsicas de


utilizao

Curso J150

no diretrio onde houver um arquivo build.xml para executar a


tarefa padro (default)

ANT Execuo de tarefa


Para executar uma tarefa diferente da padro, basta informar o
nome da tarefa a executar.
ant tarefa <enter>

ANT - Instalao Ambiente


Para executar o ANT, so necessrias a configurao de algumas
variveis de ambiente:

ANT_HOME deve apontar para o diretrio onde o ANT foi


instalado

JAVA_HOME deve apontar para o diretrio onde o JAVA (J2SE


SDK) est instalado.

PATH deve conter o caminho para o subdiretrio bin de


ANT_HOME:

windows: PATH=%PATH%;%ANT_HOME%\bin
linux: PATH=${PATH};${ANT_HOME}/bin

ANT Laboratrio 22_01


- Abra um AVISO DE COMANDO ou um SHELL.
V para o diretrio do curso:
windows:
linux:

cd \j150 <enter>
cd ~/j150 <enter>

24/04/04 01:44:25
jp@psique.org http://www.psique.org/cursos

58

ANT Noes bsicas de


utilizao

Curso J150

Configure o ambiente:
windows:
linux:

setambiente <enter>
. ./setambiente.sh <enter>

V para o diretrio do laboratrio:


windows:
linux:

cd laboratorios\22_01 <enter>
cd laboratorios/22_01 <enter>

Execute
ant

<enter>

ant

alternativo

Analise o resultado
Execute outro alvo
<enter>

Veja o build.xml
windows
linux

type build.xml <enter>


cat build.xml <enter>

Listar os alvos do build.xml


ant -projecthelp <enter>

Foi constatado:
Cada alvo uma TAG <target name=alvo> no build.xml.
A tag padro informada como o atributo default da tag project.
Este atributo indica qual o alvo que ser executado quando no
informado alvo ao se executar o ant.

Laboratrio 22_02
V para o diretrio do laboratrio:
windows:

cd ..\22_02 <enter>

24/04/04 01:44:27
jp@psique.org http://www.psique.org/cursos

59

ANT Noes bsicas de


utilizao

linux:

Curso J150

cd ../22_02 <enter>

Execute:
ant <enter>
ant alternativo <enter>

As dependncias entre alvos so informadas pelo atributo depends


da TAG target.

Tag <project>
A tag <project> tem trs atributos e o elemento principal de um
build.xml.
Os atributos so:

name: o Nome do projeto Opcional.

default: a tarefa (task) padro a ser executada, quando outra no


for especificada como parmetro. - Obrigatrio.

basedir: o diretrio que ser utilizado como corrente para o


clculo dos caminhos (paths). Se no informado, o diretrio base
ser o Pai do em que est localizado o build.xml, ou, se
informada uma propriedade basedir no build.xml Opcional.

Tag <target> alvos


Um alvo pode depender de outros alvos. Voc pode ter um alvo para
compilar, e outro para criar um pacote para distribuio. A
dependncia pode ser informada via depends:
<target
<target
<target
<target

name=alvoa/>
name=alvob depends=alvoa/>
name=alvoc depends=alvob/>
name=alvod depends=alvoc,alvob,alvoa/>

24/04/04 01:44:29
jp@psique.org http://www.psique.org/cursos

60

ANT Noes bsicas de


utilizao

Curso J150

No caso da execuo do alvod, a ordem no ser a de ocorrncia no


atributo depends, mas como alvoc depende de alvob que depende de
alvoa, primeiro ser executado alvoa, depois alvob e depois alvoc
para finalmente ser executado alvod.

Tarefas
As tarefas so includas no corpo da tag TARGET, e sero aes
executadas quando o corpo for executada. Nos laboratrios
anteriores, existia apenas uma tarefa em cada alvo. A tarefa <echo
message=valor/> simplesmente imprime a mensagem informada
no atributo message na sada.
Tarefas podem ter mltiplos atributos. O valor de um atributo pode
conter referncias a uma propriedade. Estas referncias sero
resolvidas antes que a tarefa seja executada.
<nome atributo1=valor1 atributo2=${propriedade} ... />

nome o nome da tarefa,

atributo1 o nome do atributo

valor1 o valor do atributo.

${propriedade} uma propriedade, que aps resolvida ser o


valor do atributo2.

Propriedades
Um projeto pode ter um conjunto de propriedades. As propriedades
podem ser configuradas no prprio build.xml atravs da tarefa
<property>, ou podem ser configuradas fora do ANT por arquivos
de properties.
Uma propriedade pode ser usada no valor de um atributo de uma
24/04/04 01:44:31
jp@psique.org http://www.psique.org/cursos

61

ANT Noes bsicas de


utilizao

Curso J150

tarefa:
<property name=msg value=Oi mundo/>
<echo message=${msg}/>

Laboratrio 22_03
V para o diretrio do laboratrio:
windows:
linux:
Execute:

cd ..\22_03 <enter>
cd ../22_03 <enter>
ant <enter>

Foi utilizada uma propriedade para setar o atributo message do


echo!!!

Propriedades externas
possvel incluir um arquivo de propriedades (properties), em um
build.
O arquivo conter pares nome=valor :
propriedade1=valor
propriedade2=valor
O arquivo de propriedades includo atravs do atributo file da tag
<properties>.
<properties file=nomedoarquivo.properties/>
No arquivo de propriedades, podem existir comentrios,
utilizando-se o smbolo # (sustenido, velho ou escopa)

24/04/04 01:44:33
jp@psique.org http://www.psique.org/cursos

62

ANT Noes bsicas de


utilizao

Curso J150

Laboratrio 22_04
V para o diretrio do laboratrio:
windows:
linux:
Execute:

cd ..\22_04 <enter>
cd ../22_04 <enter>
ant <enter>

Foi utilizada uma propriedade lida do arquivo build.properties para


configurar o atributo message do echo!!!

Propriedades no so redefinidas

Aps a definio de uma propriedade, ela no ser mais redefinida,


aps a definio a propriedade permanece constante.

Laboratrio 22_05
V para o diretrio do laboratrio:
windows:
linux:

cd ..\22_05 <enter>
cd ../22_05 <enter>

Execute:
ant <enter>

A primeira definio da propriedade foi a utilizada na tarefa!!!


Ambiente
As variveis de ambiente podem ser definidas como propriedades do
ant, atravs do atributo environment da tag property:
<property environment="env"/>

24/04/04 01:44:35
jp@psique.org http://www.psique.org/cursos

63

ANT Noes bsicas de


utilizao

Curso J150

Laboratrio 22_06
V para o diretrio do laboratrio:
windows:
linux:

cd ..\22_06 <enter>
cd ../22_06 <enter>

Execute:
ant <enter>

Veja algumas variveis de ambiente!!!


Propriedades pr-definidas:
${java.version}

Verso Java

${java.class.path}

Classpath

${os.name}

Nome Sist.Operacional

${os.arch}

Arquitetura Sist.Operacional

${file.separator}

Separador de arquivo (/ no linux)

$path.separator

Separador PATH (: no linux)

$line.separator

(\n no linux)

$user.name

Conta do usurio logado

$user.home

Diretrio home do usurio

$user.dir

Diretrio corrente do usurio

So vlidas todas as propriedades do mtodo getProperties() da


classe System (veja o Javadoc da API para a lista completa).

24/04/04 01:44:36
jp@psique.org http://www.psique.org/cursos

64

ANT Noes bsicas de


utilizao

Curso J150

Outras pr-definidas
O ant, adiciona algumas propriedades alm das de
System.getProperties():
${basedir}

O caminho absoluto do projeto

${ant.file}

O caminho absoluto ao build.xml

${ant.version}

A verso do Ant

${ant.project.name}

O nome do projeto informado na tag


<project>

${ant.java.version}

verso da JVM: atualmente pode ser:


1.1, 1.2, 1.3 e 1.4.

Laboratrio 22_07
V para o diretrio do laboratrio:
windows:
linux:

cd ..\22_07 <enter>
cd ../22_07 <enter>

Execute:
ant <enter>
windows:
linux :

type build.xml
cat build.xml

Veja algumas variveis pr-existentes!!!

Laboratrio 22_08

24/04/04 01:44:38
jp@psique.org http://www.psique.org/cursos

65

ANT Noes bsicas de


utilizao

Curso J150

V para o diretrio do laboratrio:


windows:
linux:

cd ..\22_08 <enter>
cd ../22_08 <enter>

Execute:

windows:
linux :

ant -projecthelp <enter>


ant <enter>
type build.xml
cat build.xml

Este build mais complexo, ele cria diretrios, compila e empacota


uma pequena aplicao. Veja os comentrios no build.xml.
Esta foi uma rpida passada sobre a estrutura de um build.xml. Os
build.xml utilizados neste curso, na medida do possvel estaro bem
comentados, dvidas podero ser tiradas no help do ant:
Com o ambiente do curso configurado digite:
no windows
no linux

help_ant <enter>
help_ant.sh <enter>

Existem muitas tarefas prontas para serem utilizadas com o ANT,


desde transferncias via FTP at execuo de queries em SQL.

24/04/04 01:44:40
jp@psique.org http://www.psique.org/cursos

66

Java RMI

Curso J150

Java RMI
Java RMI sobre IIOP (Java Remote Method invocation sobre
InternetInter-ORB Protocol) o protocolo utilizado em J2EE para
executar de forma simples acessos via rede. RMI-IIOP admite que
voc distribua objetos em Java, habilitando objetos a se
comunicarem em Mquinas Virtuais distintas e em dispositivos
fsicos distintos.
RMI-IIOP no a nica possibilidade para executar mtodos
remotamente em Java. Pode-se utilizar tambm RMI. RMI a forma
original para execuo remota em java. RMI do J2SE e encontrase no pacote java.rmi. RMI-IIOP uma verso especial de RMI que
compatvel com CORBA e usa os pacotes java.rmi e javax.rmi.
RMI tem algumas caractersticas bem interessantes no disponveis
em RMI-IIOP, tais como garbage collection distribuda, ativao de
objetos e download de class files. Mas EJB e J2EE prevem a
utilizao de RMI-IIOP.

Invocao Remota de Mtodos


Uma RPC (remote procedure call chamada remota de mtodos)
ocorre quando um processo em uma mquina executa, ou chama,
um processo em outra mquina. RPC habilita que vrios
procedimentos existentes em mltiplas mquinas conversem entre
si. So uma forma simples de comunicao inter-processos e intermquinas.

Marshalling e Unmarshalling
RMIs (bem como RPCs em geral) permitem a passagem de
parmetros, que podem ser os tipos primitivos e objetos Java, sobre
a rede. Mas e se a mquina destino tiver uma representao de
24/04/04 01:44:42
jp@psique.org http://www.psique.org/cursos

67

Java RMI

Curso J150

dados diferente da de origem? Como ficamos se uma mquina


internamente tem um padro binrio para representao de
nmeros big endian (mais significativo no final, 1 = 0100x), outra
mquina little endian(menos significativo no final, 1 = 0001x)?? O
que acontece se voc envia a referncia a um objeto pela rede? Um
ponteiro no pode ser utilizado na outra mquina, ele aponta para
um objeto de memria da mquina original. Marshalling e
unmarshalling o processo de empacotamento de parmetros de
forma que eles sejam utilizveis na mquina que est sendo
invocada remotamente e o desempacotamento destes parmetros
quando a mensagem chegar no destino. RMI-IIOP cuida disto para
voc, voc vai fazer a chamada de maneira transparente.

Convenes de passagem de parmetros


Existem duas formas de passagem de parmetros, por valor e por
referncia. Quando voc passa por valor, voc passa uma cpia dos
dados para o procedimento que est sendo invocado. Qualquer
mudana que ocorra nos dados no destino no afetar os dados na
origem. Passando por referncia, no feita a cpia, enviado o
endereo do dado, e qualquer alterao do dado no mtodo
invocado causar a alterao do dado original. RMI sobre IIOP
suporta os dois mtodos de passagem.

Instabilidades de rede
Quando estamos dentro de uma mesma JVM, se a JVM quebrar toda
a aplicao quebra junto, ou seja, todos os processos quebram. Em
aplicaes distribudas, se uma JVM estiver trabalhando com outra
e somente uma quebrar poderemos ter problemas. Qualquer cdigo
executado remotamente deve ter formas de ser notificado caso
ocorram problemas de rede, na mquina de destino ou na JVM de
destino. RMI-IIOP cuida destes detalhes.

A interface remota
Ao trabalharmos com RMI-IIOP utilizamos uma prtica muito
24/04/04 01:44:44
jp@psique.org http://www.psique.org/cursos

68

Java RMI

Curso J150

recomendada em POO que a separao entre interface e


implementao.
A interface define quais informaes de um objeto sero expostas,
tais como os nomes de seus mtodos e quais os parmetros
necessrios. O cliente trabalha com a interface. A interface
mascara a implementao do ponto de vista do cliente, ento o
cliente enxerga somente o que foi exposto.
Separando interface de implementao voc pode alterar a lgica
do objeto sem ter que mudar o cdigo no lado do cliente. Por
exemplo, em JDBC utilizamos interfaces para acesso aos dados,
basta carregar um driver de outro banco de dados para que a
implementao seja completamente diferente, mas como as
interfaces so as mesmas nosso cdigo que utiliza o JDBC no
precisa ser alterado.
RMI-IIOP utiliza muito este conceito. Todo cdigo de rede ser
escrito para interfaces, no para a implementao. Na realidade
voc obrigado a fazer isto em RMI-IIOP, voc no tem escolha.
impossvel fazer uma invocao remota diretamente ao objeto
implementado.
Ento utilizando RMI-IIOP, voc precisa ter uma interface comum,
chamada remote interface (interface remota). Esta interface remota
deve estender a interface java.rmi.Remote. Nesta interface devem
existir todos os mtodos que voc deseja expor aos clientes.
Exemplo: Suponha que voc quer expor um mtodo gerador().
gerador() retorna um nmero a cada vez que chamado.

import java.rmi.Remote;
import java.rmi.RemoteException;

24/04/04 01:44:45
jp@psique.org http://www.psique.org/cursos

69

Java RMI

Curso J150

public interface iGeradorDeChave extends Remote {


public long gerador() throws RemoteException;
}

O cdigo do cliente que quiser chamar o objeto remoto precisa


trabalhar com a interface iGeradorDeChave. Todo mtodo remoto
precisa lanar java.rmi.RemoteException, pois problemas de
comunicao sempre podem ocorrer.

A implementao do objeto remoto


Objetos remotos so implementaes de objetos que podem ser
chamados por outra JVM. Eles implementam a interface remota
onde esto os mtodos que podem ser invocados pelo cliente.
A localizao fsica do objeto remoto e do cliente que o invoca no
importante. Por exemplo, possvel que um cliente invoque um
objeto que se encontra na mesma mquina virtual. Para o objeto
remoto no interessa se o cliente est na mesma mquina ou no.
Para tornar o objeto remoto disponvel para ser chamado no lado do
cliente, sua classe remota precisa:
Estender a classe javax.rmi.PortableRemoteObject. um classe da
qual voc pode derivar seus objetos remotos. Quando o objeto
remoto for construdo, ele automaticamente chama o objeto
construtor do PortableRemoteObject que torna o objeto disponvel
para chamadas remotas.
No estender javax.rmi.PortableRemoteObject. voc pode querer
que a de seu objeto remoto deve herde as implementaes de
outra classe. neste caso, porque java no implementa herana
mltipla voc no pode herdar de duas classes ao mesmo tempo. Se
voc fizer isto, voc precisa manualmente exportar seu objeto para

24/04/04 01:44:47
jp@psique.org http://www.psique.org/cursos

70

Java RMI

Curso J150

que seja disponibilizado para ser invocado por mquinas remotas.


Para exportar o seu objeto faa uma chamada a
javax.rmi.PortableRemoteObject.exportObject().
Abaixo a criao de um objeto remoto que implementa a interface
acima:

import java.rmi.RemoteException;
import javax.rmi.PortableRemoteObject;
public class GeradorDeChave extends PortableRemoteObject
implements iGeradorDeChave {
public GeradorDeChave throws Exception , RemoteException {
// Como esta classe estende PortableRemoteObject,
// O construtor da super classe faz o que precisamos
// que a chamada ao objeto remoto.
super();
}
public synchronized long gerador() throws RemoteException {
return i++;
}
private static long i = System.currenttimeMillis();
}

No construtor de seu objeto remoto a super classe torna seu objeto


disponvel remotamente. Isto torna seu objeto disponvel em uma
porta aleatria (porto na realidade, a palavra port incorretamente
traduzida para portugus como porta). Depois da execuo do
construtor o objeto estar disponvel a todas as mquinas virtuais
que quiserem invoc-lo. At que algum chame o mtodo
(unexportObject()).

24/04/04 01:44:49
jp@psique.org http://www.psique.org/cursos

71

Java RMI

Curso J150

Stubs e Skeletons
Agora que ns vimos o cdigo do servidor, vamos dar uma olhada na
arquitetura de rede por trs de RMI-IIOP. Utilizando RMI-IIOP
temos a iluso de acessar o mtodo de forma transparente atravs
da rede. Voc pode invocar mtodos de um objeto remoto como
invocaria qualquer outro de qualquer objeto Java. De fato, RMI-IIOP
mascara completamente onde est o objeto que est sendo
invocado. Isto chamado transparncia local/remota.
Mas a transparncia local/remota no uma coisa to simples como
parece. Para mascarar o fato de que voc est invocando um objeto
residente em outra mquina, RMI precisa simular um objeto local
que voc ir invocar. Este objeto local chamado de stub e
responsvel por aceitar chamados a mtodos locais e delegar a
chamadas a mtodos para as implementaes reais, que podem
estar localizadas em qualquer lugar da rede. Voc pode pensar em
um stub como se fosse um local para se colocar um objeto que sabe
como procurar pela rede o objeto real. Porque voc invoca um
mtodo na mquina local (o stub), todas tarefas complicadas ficam
ocultas do cliente.
Stubs so apenas metade do cenrio. Ns desejamos que os objetos
remotos os objetos que esto sendo invocados na mquina remota
tambm no se preocupem com os detalhes de comunicao via
rede. Assim como o cliente invoca um STUB que local ao cliente,
o objeto remoto precisam aceitar chamadas de um SKELETON que
um objeto local ao objeto remoto (fica na mesma JVM que o objeto
remoto). Skeletons so responsveis por receber chamadas pela
rede e delegar estas chamadas para a implementao de um objeto
remoto.

24/04/04 01:44:51
jp@psique.org http://www.psique.org/cursos

72

Java RMI

Curso J150

Cliente

Objeto Remoto

Remote
Interface

Stub

Skeleton

REDE

Mquina do Servidor
Mquina do Cliente

Uma das responsabilidades mais interessantes dos Stubs e dos


Skeletons Marshalling e Unmarshalling dos parmetros. RMI
baseia-se em uma tecnologia chamada object serialization para
ajud-lo nisto.

24/04/04 01:44:53
jp@psique.org http://www.psique.org/cursos

73

Java RMI

Curso J150

Bootstrapping e registro RMI

Para que um cliente e um servidor comece a conversar, eles


precisam estar conectados. O estabelecimento desta conexo
chamado bootstrapping.
RMI disponibiliza uma entidade chamada de RMI Registry para isto.
Quando voc quiser tornar um objeto remoto acessvel, voc o
cadastra no registro. Voc d um nome para fazer este registro.
Ento o Registro (registry) ir rotear todas as requisies que
chegarem para o seu objeto. Voc pode pensar no RMI Registry
como se fosse uma hashtable gigante que mapeia nomes a objetos.
O RMI Registry efetua esta tarefa se posicionando em um port
(porto ou parta) conhecido em uma mquina conhecida esperando
por conexes. Quando um cliente remoto quer acessar um objeto
registrado, o cliente encaminha a requisio pela rede ao Registro
(host e porta definido). O registro l o request, procura o nome do
objeto remoto requisitado e retorna ao cliente o stub para o objeto
remoto.
Podemos ter vrios RMI registries em uma mquina, mas apenas
um Registry para uma JVM, e um nico registry por port. Existem
milhares de portas disponveis, o que pode ser um problema. Se
voc no especificar qual port ser utilizada, RMI ir utilizar o porto
1099 por default. Lembre-se que ambos cliente e servidor
precisam acessar o mesmo porto no mesmo servidor.
Existem duas maneira de iniciar um RMI Registry. Voc pode lanlo como um programa stand-alone:

24/04/04 01:44:55
jp@psique.org http://www.psique.org/cursos

74

Java RMI

Curso J150

Basta digitar no prompt


rmiregistry

um programa que se encontra no diretrio ${JAVA_HOME}/bin.


Tambm possvel inicializ-lo de dentro de um programa,
acessando a classe java.rmi.Registry class.

URLs de RMI
Um URL (Unified Ressource Locator) uma string em Java que
utilizada para localizar um objeto remoto em outra Mquina Virtual.
Parece com as URLs que acessamos para acessar um stio na
internet (http://java.sun.com). A conveno para a URL :
1. A URL precisa comear com o texto rmi://
2. Voc precisa ento especificar qual a mquina de destino onde
a JVM est localizada por exemplo:
rmi://paizao.limberger.2y.net. Se voc no especificar a mquina
de destino o default ser localhost.
3. No final, o nome do objeto remoto do qual voc quer a referncia
remota. Por exemplo, se o objeto remoto foi chamado de
meuObjeto, voc pode referenci-lo de qualquer mquina no
mundo com a URL:
rmi://paizao.limberger.2y.net/meuObjeto

24/04/04 01:44:56
jp@psique.org http://www.psique.org/cursos

75

Java RMI

Curso J150

Cliente

Cliente

Localizao
via RMI

Stub
Quando o
cliente
conseguir o
STUB

Rede

Registro
RMI

Objetos
Remotos

Rede

Skeleton

Objeto
Remoto

Procurando um objeto remoto


(lookup)
At agora vimos:

Um RMI Registry um objeto remoto utilizado por clientes para


executar o bootstrapping, ou seja para o estabelecimento da
conexo com o objeto remoto. Objetos remotos so registrados no
RMI registry ao qual os clientes se conectam.

URLs de RMI so usadas para identificar qual a localizao dos


objetos na rede.

A codificao da URL de rmi interessante para identificar os


objetos pela rede. Mas fixar as URLs no cdigo tornam o cdigo
pouco portvel, engessa a rede. Ento para facilitar esta busca de
24/04/04 01:44:58
jp@psique.org http://www.psique.org/cursos

76

Java RMI

Curso J150

objetos distribudos pela rede, utilizamos JNDI Java Naming and


Directory Interface. Isto permite que o cdigo do cliente no
necessite especificar as localizaes de cada objeto pela rede.
Quando um cliente quer uma referncia a um objeto remoto, ele o
procura atravs de java.rmi.Naming que responsvel por conectar
aos registros RMI (rmi registries) com o propsito de encontrar
objetos remotos.
Como j vimos no captulo sobre RMI, o mtodo lookup() de
java.rmi.Naming o responsvel por esta tarefa. Ele pega uma URL
RMI, conecta ao RMI registry na JVM de destino e retorna um
objeto do tipo java.lang.Object que representa o objeto remoto. O
objeto retornado o stub e pode ser feito um cast para a interface
remota do objeto.

RMIC O compilador RMI


Os stubs e skeletons que foram citados antes, tentam fazer as
chamadas remotas parecerem locais. Stubs e skeletons precisam
implementar a interface remota do objeto. Por causa disto, no
existem dois stubs ou skeletons iguais, e eles precisam ser gerados
para cada classe de objeto remoto que voc criar. No pacote JSDK
padro, existe um compilador para rmi chamado rmic. Ele pega a
sua implementao de objeto remoto (a classe que implementa sua
interface remota), e cria um stub e um skeleton para o objeto
remoto. O stub imita cada mtodo exposto pelo objeto remoto,
copiando exatamente a mesma assinatura do mtodo, ento clientes
pode chamar o stub localmente como se estivessem chamando o
objeto destino.

Serializao de Objetos e passagem


de parmetros

24/04/04 01:45:01
jp@psique.org http://www.psique.org/cursos

77

Java RMI

Curso J150

Passagem por Valor


Quando invocamos um mtodo utilizando RMI, todos os parmetros
ao mtodo remoto so passados por valor. Isto significa que todos os
parmetros recebidos no mtodo a ser executado so na realidade
cpias dos dados dos parmetros originais.
Passar objetos por valores no o padro em Java, que
normalmente passa a referncia do objeto nas chamadas (mas a
referncia passada por valor, ou seja, passado um cpia da
referncia Mas no uma cpia do objeto).
Existe um grande problema ao passar dados por valor. Se voc
tentar passar um objeto pela rede e este objeto contiver referncias
a outros objetos, como estas referncias sero resolvidas na
mquina de destino? Os objetos existem somente na origem!

Serializao de Objetos
Java introduziu um conceito de serializao de objetos para
contornar este problema. Serializao a converso de um objeto
java em uma representao binria do objeto. Uma vez que o objeto
foi transformado para a forma binria (um pacote de bytes), este
pacote pode ser gravado no disco, transmitido pela rede. Quando
voc quiser transformar o pacote de bytes de volta forma de
objeto, voc ter que executar a desserializao do pacote.
A linguagem Java cuida dos detalhes de baixo nvel para a
serializao de desserializao do objeto. Na maioria dos casos, no
precisamos nos preocupar com isto. Para dizermos ao java que um
objeto pode ser serializado, basta implementarmos uma interface
chamada java.lang.Serializable. Esta interface no define nenhum
mtodo, somente marca o objeto como serializvel.

Como os objetos so serializados


Uma vez que o objeto implementa java.lang.Serializable, ele pode
ser serializado em um fluxo de dados (stream). O processo de
serializao feito automaticamente pelo Java. Voc pode
24/04/04 01:45:04
jp@psique.org http://www.psique.org/cursos

78

Java RMI

Curso J150

customizar isto implementando o mtodo writeObject() no seu


objeto. Isto pode ser til, se voc quiser comprimir os dados de seu
objeto antes que ele seja transformado em um pacote de bytes.
A desserializao automtica tambm na maioria dos casos. Se
voc quiser, pode implementar uma forma customizada tambm
para a desserializao criando um mtodo chamado readObject().

Regras para serializao


Serializao em java tem as seguintes regras para armazenamento
de variveis membros em objetos serializados:
Qualquer tipo primitivo (int, char, boolean...) automaticamente
serializado com o objeto.
Objetos java podem ser includos no pacote de bits serializados ou
no; a escolha sua.
Objetos marcados com a palavra chave transient no sero
serializados
Qualquer outro objeto no marcado como transient precisa
implementar a interface java.lang.Serializable. Estes objetos
sero convertidos em um pacote de bytes junto com o que os
inclui. Se seus objetos java no so marcados com transient e
no implementam java.lang.Serializable, ser lanada uma
exceo do tipo NotSerializableException quando houver uma
solicitao para ser serializado (chamada ao mtodo
writeObject()).
Quando voc serializar um objeto, voc tambm serializa todos os
sub objetos no transientes, isto feito recursivamente at que todo
o conjunto esteja serializado. Esta recurso automtica, voc
simplesmente precisa ter certeza que todos os membros dos objetos
implementam a interface java.lang.Serializable ou que sejam
marcados como transient.

O que deve ser Transient?


Como saber quais membros e variveis devem ser marcados como
transient e quais no? Algumas boas razes para marcar objetos
como transient so:
24/04/04 01:45:05
jp@psique.org http://www.psique.org/cursos

79

Java RMI

Curso J150

O objeto muito grande. Objetos grande podem no ser bons


para a serializao j que o pacote de bytes gerado ser muito
grande, o que pode consumir muito recurso. Objetos grandes se
marcados como transient economizam espao para gravao em
disco e banda de rede para o transporte.
Objetos que representam recursos que no podem ser
reconstrudos na mquina de destino: Conexes com banco de
dados, sockets.
Os objetos que representam informaes secretas, s quais voc
no deseja passar como uma stream serializada.

Lembre-se sempre que a serializao de objetos no feita sem


custo uma operao pesada para objetos grandes. Tenha certeza
de voc levar isto em conta quando desenhar sua aplicao de
objetos distribudos.

Usos de serializao de objetos


A serializao de objetos um mecanismo utilizado para passar
parmetros por valor utilizando RMI. Quando voc passar um
argumento usando RMI, RMI verifica se o seu objeto serializvel.
Se for, ele ser serializado e enviado pela rede. O recebedor recebe
o objeto e o desserializa tornado-o disponvel para o uso. Quando o
objeto desserialiazado, todas as suas referncias a outros objetos
so automaticamente reconstrudas porque os objetos referenciados
tambm so parte do pacote de bits utilizado para a desserializao.
No existe perigo em uma referncia tornar-se invlida aps uma
invocao porque as referncias so dinamicamente reconstrudas
em tempo real.
A serializao de objetos auxilia o processo de RMI de marshalling
(empacotamento) dos parmetros e de unmarshalling
(desempacotamento) dos parmetros. Mas serializao tem vrias
outras utilidades tambm. Por exemplo, objetos serializados
possibilitam voc armazenar o estado de um objeto. Basta serializlo e grav-lo no disco como um pacote de bytes. uma maneira fcil
e rpida de persistncia.

24/04/04 01:45:07
jp@psique.org http://www.psique.org/cursos

80

Java RMI

Curso J150

Simulao de passagem por referncia com


RMI
A passagem por valor, pode ser facilmente implementada com
serializao, como vimos. Isto nem sempre desejvel pois o
volume objetos pode ser grandes, entupindo a rede.
Para melhorar a eficincia, seria interessante que os objetos
pudessem ser passados por referncia. RMI simula a passagem por
referncia, o que significa que os argumentos no so copiados. No
lugar disso, o mtodo remoto trabalha com o objeto original.
Se voc deseja usar um parmetro por referncia, o parmetro
precisa ser um objeto remoto isto um objeto que possvel ser
chamado remotamente. Vamos considerar o cenrio onde a mquina
remota recebe uma referncia a este objeto remoto, mas como um
parmetro para um de seus mtodos. A mquina remota pode ento
invocar a operao em seu objeto remoto, esta operao ir ocorrer
no local da mquina, e no no host remoto. O que na prtica uma
invocao de mtodo atravs da rede.
Mas o que passado quando um objeto remoto passado por
referncia como parmetro? O objetivo no copiar o objeto remoto
pela rede. A mquina remota precisa do objeto para executar a
operao. A resposta passar todas as referncias a objetos
remotos como um STUBs. Os stubs so referncia a objetos remotos
via rede.
Como em java no distribudo voc tem referencias a objetos, em
RMI voc tem uma referncia remota a um objeto. Objetos do tipo
java.rmi.RemoteStub so manifestaes destas referncias remotas.
Eles so exatamente os mesmos stubs descritos anteriormente que
so gerados pela ferramenta rmic.
Java RMI simula a passagem por referencia apenas se os
parmetros (objetos) que esto sendo passados so tambm objetos
remotos e so executveis do host remoto. Neste caso, o stub para o
objeto remoto passado no lugar do objeto serializado.
Porque os stubs RMI so serializveis, eles so passados pela rede
24/04/04 01:45:09
jp@psique.org http://www.psique.org/cursos

81

Java RMI

Curso J150

como um pacote de bits. Isto a explicao para quando foi dito


antes que todos os parmetros em Java RMI so passados por valor.
Ento Java RMI apenas simula a passagem por referncia passando
um stub serializado no lugar do objeto original. Transformando seus
parmetros em objetos remotos, voc pode efetivamente evitar a
passagem de grandes objetos pela rede.
Resumindo:
Todos os tipos primitivos so passados por valor quando um
mtodo chamado remotamente. Isto significa que cpias dos
parmetros so feitas. Qualquer mudana nos dados na mquina
remota no afetar os dados originais.
Se voc quiser passar um objeto pela rede por valor, ele precisa
implementar a interface java.lang.Serializable. Qualquer coisa
referenciada por este objeto precisa seguir as regras de
serializao. Qualquer mudana no objeto remoto no altera os
dados originais.
Se voc quiser passar um objeto pela rede por referncia, precisa
ser um objeto remoto e precisa implementar java.rmi.Remote. Um
stub para o objeto remoto ser serializado e passado para a
mquina remota. A mquina remota pode ento usar o stub para
invocar mtodos no objeto remoto. Existe apenas uma nica cpia
dos dados, o que significa que todas as mquinas alteram os
mesmos dados.

Exportando Objetos Remotos


Para tornar seus objetos, objetos remotos disponveis para serem
invocados por mquinas remotas, suas classes remotas tem que
executar um dos passos seguintes:
Estender java.rmi.server.UnicastRemoteObject.

UnicastRemoteObject uma classe bsica da qual voc pode


derivar seus objetos remotos. Quando seus objetos remotos forem
construdos, eles automaticamente chama o construtor de
UnicastRemoteObject, que ter tornar seu objeto disponvel para
chamadas remotas.

24/04/04 01:45:11
jp@psique.org http://www.psique.org/cursos

82

Java RMI

Curso J150

No estender java.rmi.server.UnicastRemoteObject.

Se voc precisar que um objeto estenda alguma classe, significa que


voc no poder estender UnicastRemoteObject, Logo voc ter que
manualmente exportar seus objetos para torn-los disponveis
mquinas remotas. Para exportar seus objetos, voc precisara fazer
uma chamada a java.rmi.server.UnicastRemoteObject.exportObject
().

Laboratrio 24_01
Exemplo RMI
para Compilar:
set classpath=.
javac org/psique/SampleServer.java
javac org/psique/SampleServerImpl.java
rmic org.psique.SampleServerImpl
javac org/psique/SampleClient.java

Para Executar:
Executar o servidor:
rmiregistry &

java

-Djava.security.policy=policy.all org.psique.SampleServerImpl

java -Djava.security.policy=policy.all org.psique.SampleClient

Podem ser necessrio informar CODEBASE se o servidor


(rmiregistry) no tiver no classpath os STUBS.
-Djava.rmi.server.codebase=file://localhost/f:/j150/laboratorios/24_01/

24/04/04 01:45:13
jp@psique.org http://www.psique.org/cursos

83

RMI, Corba e EJB

Curso J150

RMI, Corba e EJB


Vejamos agora onde est a relao entre RMI, CORBA e EJB.

RMI ou CORBA
Historicamente, desenvolvedores tem decidido entre utilizar RMI
ou CORBA para implementar distribuio de servios.
Quando se combina RMI com alguma outra API os benefcios do
Corba no so to expressivos. Usar JNDI no lugar do naming
system de Corba. A API Java Transaction e Java Transaction Service
pode ser utilizada para controle de transaes, e faz o mesmo
trabalho que o Object Transaction Service de Corba. possvel
alguma interao entre linguagens combinando RMI com JNDI.
Tambm possvel executar operaes com banco de dados
relacionais com chamadas RMI/JDBC.
Corba por outro lado, est ficando mais fcil de ser utilizado.
CORBA prov um conjunto de funcionalidades, que no passado eram
muito difceis de aprender. Definition Language (IDL). Agora
existem ferramentas para automaticamente gerar a IDL para voc.
Existe um produto da sun para ler a definio de uma interface
remota e gerar a idl automaticamente. E com a proposta dos novos
componentes de CORBA, vai ser possvel prover inmeros servios
de CORBA automaticamente, sendo disponibilizada um arquitetura
bastante variada de componentes no servidor.
Por estas raes, a Sun avaliza as duas solues RMI e CORBA. No
existe nenhuma tecnologia vencedora. Como ambas so tecnologias
maduras, voc ver muitos servios CORBA refletidos na plataforma
J2EE. A vantagem que J2EE a tecnologia do momento.

RMI e EJB
RMI uma parte essencial de EJB. Em EJB, muitos objetos
distribudos utilizam RMI como a API standard para networking.
24/04/04 01:45:15
jp@psique.org http://www.psique.org/cursos

84

RMI, Corba e EJB

24/04/04 01:45:17
jp@psique.org http://www.psique.org/cursos

Curso J150

85

RMI, Corba e EJB

Curso J150

A Sun junto com a IBM e outros, mais recentemente desenvolveram


uma verso de RMI mais portvel, pois pode usar o padro da OMG
que o Internet Inter-ORB Protocol (IIOP) como protocolo de
comunicao. IIOP um protocolo muito robusto e possibilita a
integrao com sistemas que utilizamo CORBA (Common Object
Request Broker Architecture).
A combinao com CORBA permite integrao com outras
linguagens tais como C++ e COBOL. CORBA e EJB esto muito
prximos. Muitos dos conceitos de J2EE vieram de CORBA.
CORBA (Common Object Request Broquer Architecture) um
padro para escrever sistemas distribudos. O padro neutro em
relao linguagem, plataforma e vendedor. Foi criada pela OMG
(Object Mangement Group) em um consrcio de empresas em 1989.
Razes para conhecer Corba:
Integrao com sistemas legados
Desenvolvimento avanado de middleware
Corba e EJB esto conectados.
Java RMI se comunica usando (JRMP) Java remote Method Protocol
como padro de comunicao. O mundo CORBA no usa JRMP.
Produtos Corba usam um protocolo diferente chamado IIOP
(Internet Inter-ORB Protocol). IIOP um padro da internet para
CORBA. IIOP, assim como JRMP, utilizado como pano de fundo
para a comunicao entre objetos distribudos.

24/04/04 01:45:18
jp@psique.org http://www.psique.org/cursos

86

RMI, Corba e EJB

Curso J150

Objetos EJB
Em EJB, seus enterprise beans precisam ser disponibilizados a
clientes remotos. Isto pode ser feito utilizando Java RMI.
Note que enterprise beans no so objetos remotos de fato. Isto
seus beans no estendem UnicastRemoteObject. No lugar, seus
beans so empacotados em uma concha que fala RMI chamado de
EJB object. Um EJB object um objeto remoto que o cliente pode
invocar. Quando um cliente chama um EJB object, este objeto
delega a chamada remoto para o bean.
Para desenvolver um bean, voc precisa escrever a interface de seu
EJB object. Esta interface chamada de interface remota, e utiliza
exatamente o mesmo conceito das interfaces remotas que vnhamos
vendo at agora. Esta interface remota duplica a assinatura de cada
mtodo que o bean tem.
Sobre as interfaces remotas de EJB:

Uma interface remota de EJB deriva (indiretamente) de


java.rmi.Remote

Cada mtodo na interface remota do EJB precisa lanar uma


exceo do tipo java.rmi.RemoteException

Cada mtodo da interface remota precisa ter parmetros vlidos


para Java RMI. Isto significa que seus parmetros tem que ser de
tipos primitivos, serializveis ou objetos remotos.

O EJB object implementa a interface remote. Mas voc no precisa


escrever o EJB object. Ele automaticamente gerado para voc pelo
continer EJB. Isto explica porque o EJB object precisa conter lgica
proprietria para interagir com o conteiner, utilizar transaes e
implementar tolerncia a falhas, e outras operaes que envolvem o
conteiner. Voc pode pensar no EJB object como sendo parte do
conteiner. O EJB object usado por seus clientes pode ser um EJB
object ou um RemoteStub para um EJB object que est localizado
em qualquer lugar da rede. O cdigo do seu cliente no se importa
24/04/04 01:45:20
jp@psique.org http://www.psique.org/cursos

87

RMI, Corba e EJB

Curso J150

com isto porque est invocando a interface do EJB object, que


implementada pelo objeto e pelo stub.

Objetos Home
Em EJB, um objeto home uma fbrica (factory) para criar EJB
objects. Voc procura pelo HomeObject usando JNDI, Uma vez
tendo o home object, voc o chama utilizando RMI.
A interface home do objeto (chamada home interface) tambm
uma interface remota, e segue as regras de Java RMI. Ela precisa
lanar remote exceptions, implementar java.rmi.Remote e aceita
parmetros serializveis. Como com EJB objects, um home object
proprietrio de cada continer. A implementao concreta do objeto
home gerada pelo continer EJB.
Clientes dos home objects sempre utilizam a interface home para
interagir com estes objetos proprietrios, da mesma forma que
clientes de EJB objects sempre negociam com as interfaces remote.
E como nos EJB objects uma referencia para um home object pode
ser o atual home object ou um RemoteStub para o home object real
localizado em alguma outra localidade na rede.

24/04/04 01:45:22
jp@psique.org http://www.psique.org/cursos

88

RMI, Corba e EJB

Curso J150

EJB Enterprise Java


Beans
So componentes escritos em Java, que existem em um continer
J2EE no servidor, destinados a manter as regras de negcio de uma
aplicao.

Tipos de Enterprise Bean


Existem trs tipos de EJB, que so: Session Beans, Entity Beans e
Message Driven Beans.
Um session bean representa uma tarefa para o cliente, a
implementao de uma regra de negcio.
Um entity bean representa uma entidade no banco de dados ou
outro meio de persistncia.
Message Driven Beans (MDBs) servem como ouvinte (listener) para
a API Java Message Service, que possibilita o processamento de
mensagem assncrona.

Como escrever um bean


Desenvolver e distribuir um aplicativo EJB requer os seguintes
passos:
1. escrever o bean.
2. escrever o descritor de distribuio (deployment descriptor)
24/04/04 01:45:24
jp@psique.org http://www.psique.org/cursos

89

EJB Enterprise Java Beans

Curso J150

3. criar um arquivo de distribuio


4. distribuir o bean
5. escrever um aplicativo cliente para testar o bean.
O exemplo a seguir monta um aplicativo EJB consistindo de apenas
um enterprise bean que pode fazer acrscimos de dois inteiros.
Depois de compilar o bean com sucesso, voc escrever o descritor
de distribuio e distribuir o bean. Finalmente, voc criar um
servlet que servir como o cliente do nosso aplicativo EJB.

Como escrever o bean Somador


Voc precisa escrever trs arquivos Java, todos os quais fazendo
parte do pacote org.psique.ejb. Portanto, a primeira coisa a fazer
criar a estrutura de diretrios apropriada:
classes
org
psique
ejb
META-INF

Os trs arquivos java estaro no diretrio classes/org/psique/ejb,


24/04/04 01:45:26
jp@psique.org http://www.psique.org/cursos

90

EJB Enterprise Java Beans

Curso J150

eles sero:
SomadorHome.java
Somador.java
SomadorBean.java
SomadorHome e Somador so as interfaces home e remota do ejb.
SomadorBean o EJB.
A interface SomadorHome

package org.psique.ejb;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
public interface SomadorHome extends EJBHome {
Somador create() throws RemoteException, CreateException;
}

A interface Somador:

package org.psique.ejb;
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
public interface Somador extends EJBObject {
public int soma(int a, int b) throws RemoteException;
}

24/04/04 01:45:28
jp@psique.org http://www.psique.org/cursos

91

EJB Enterprise Java Beans

Curso J150

A classe SomadorBean:
package org.psique.ejb;
import java.rmi.RemoteException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
public class SomadorBean implements SessionBean {
public int soma(int a, int b) {
System.out.println(Somador somando a + b = +
a + + + b + = + (a+b));
return (a+b);
}
public void ejbCreate() {
}
public void ejbRemove() {
}
public void ejbActivate() {
}
public void ejbPassivate() {
}
public void setSessionContext(SessionContext sc) {
}
}

O descritor de distribuio
Deployment Descriptor
Um aplicativo EJB precisa ter um deployment descriptor que
descreva cada enterprise bean naquele aplicativo. O arquivo
descritor de distribuio chamado ejx-jar.xml. neste arquivo
que os componentes so colocados juntos.
Deployment Descriptor
<?xml version=1.0 encoding=ISO-8859-1?>
24/04/04 01:45:30
jp@psique.org http://www.psique.org/cursos

92

EJB Enterprise Java Beans

Curso J150

<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD


Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejbjar_2_0.dtd">
<ejb-jar>
<description>Descrio da aplicao</description>
<display-name>Aplicao somadora</display-name>
<enterprise-beans>
<session>
<ejb-name>Somador</ejb-name>
<home>org.psique.ejb.SomadorHome</home>
<remote>org.psique.ejb.Somador</remote>
<ejb-class>org.psique.ejb.SomadorBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Bean</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>

Criao de um arquivo de
distribuio
Depois de terminar de desenvolver o seu enterprise bean, voc
precisa empacotar todos os arquivos de classe em um arquivo .jar.
os arquivos de classe so dados na estrutura de diretrio exibida na
figura 28.3. o diretrio ejb contm trs arquivos: Somador.class,
SomadorHome.class e SomadorBean.class. O diretrio META-INF
deve conter o arquivo ejb-jar.xml. o descritor de distribuio.
1. Mude o diretrio para o diretrio superior ao META-INF.
2. Digite o comando:
jar cfv somador.jar org/psique/ejb/* META-INF/ejb-jar.xml

Distribuio
Copie e arquivo somador.jar no diretrio de distribuio do jboss:

24/04/04 01:45:32
jp@psique.org http://www.psique.org/cursos

93

EJB Enterprise Java Beans

Curso J150

${JBOSS_HOME}/server/default/deploy
O console do JBOSS deve reagir informando nos displays que a
aplicao foi bem instalada.
Para utilizar o EJB precisamos de um cliente.

Partes do EJB
O EJB no uma nica classe, na realidade, existem sempre duas
interfaces que acompanham o BEAN. Essas duas interfaces so
chamadas de interface home e interface remote. Elas existem para
permitir a comunicao entre um cliente e um enterprise bean. O
enterprise bean contm a implementao das regras de negcio.
Claro que um enterprise bean tambm pode ter outras classes. As
duas interfaces e uma classe concreta o mnimo que pode existir.
A interface home e a interface remote so importantes pois elas so
a porta para um enterprise bean em um aplicativo cliente.
A especificao EJB declara que um enterprise bean e seus
componentes de apoio so escritos, implementando ou ampliando
membros do pacote javax.ejb.

A interface home
A interface home realiza as operaes de ciclo de vida: criando,
encontrando e removendo o enterprise bean. Uma interface home
precisa estender a interface EJBHome no pacote javax.ejb. A
interface javax.ejb.EJBHome dada como a seguir:

package javax.ejb;
public interface EJBHome extends java.rmi.Remote {
EJBMetaData getEJBMetaData()
24/04/04 01:45:34
jp@psique.org http://www.psique.org/cursos

94

EJB Enterprise Java Beans

Curso J150

throws java.rmi.RemoteException;
HomeHandle getHomeHandle()
throws java.rmi.RemoteException;
void remove(Handle handle)
throws java.rmi.RemoteException,
javax.ejb.RemoveException;
void remove(Object primaryKey)
throws java.rmi.RemoteException,
java.ejb.RemoveException;
}

Viu como a interface EJBHome derivada da interface


java.rmi.Remote? Esse o primeiro sinal que voc viu neste
captulo, que EJB depende de RMI.
A prpria interface java.rmi.Remote usada para identificar
interfaces cujos mtodos podem ser chamados de uma mquina
virtual no local. Qualquer objeto remoto precisa implementar essa
interface, direta ou indiretamente.
Uma home interface pode definir mtodos para criar, encontrar e
remover o enterprise bean. Os mtodos create e find so
acrescentados definio de home interface; os mtodos de
remoo so herdados da interface javax.ejb.EJBHome. Por exemplo
a interface home de Somador, define um mtodo create sem
argumento em seu corpo, usando o seguinte cdigo:

24/04/04 01:45:36
jp@psique.org http://www.psique.org/cursos

95

EJB Enterprise Java Beans

Curso J150

package org.psique.ejb;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
public interface SomadorHome extends EJBHome {
Somador create() throws RemoteException, CreateException;
}

Uma interface home pode definir vrias sobrecargas dos mtodos


create e find. Os mtodos create e find tambm podem lanar
excees opcionais, se necessrio. O nome de um mtodo find
sempre comea com find, so conhecidos como finders.
Ambos os mtodos, create e find, so opcionais. Nem todos os beans
precisam deles. Por exemplo, um bean de sesso (session bean)
pode definir um ou mais mtodos create, mas um entity bean no .

A interface remote
A interface remote duplica todos os mtodos de negcio do EJB que
esto disponveis ao cliente. Isto ocorre porque o cliente no pode
acessar diretamente o bean.
Uma interface remote precisa estender a interface EJBObject no
pacote javax.ejb. javax.ejb.EJBObject assim definida:

package javax.ejb;
public interface EJBObject extends java.rmi.Remote
public abstract EJBHome getEJBHome()
throws java.rmi.RemoteException;

24/04/04 01:45:38
jp@psique.org http://www.psique.org/cursos

96

EJB Enterprise Java Beans

Curso J150

public abstract Object getPrimaryKey()


throws java.rmi.RemoteException;
public abstract void remove()
throws java.rmi.RemoteException,
javax.ejb.RemoveException
public abstract Handle getHandle()
throws java.rmi.RemoteException;
public abstract Boolean isIdentical(EJBObject obj)
throws java.rmi.RemoteException;
}

Agluns mtodos de EJBObject interessantes:


getEJBHome() - Serve para recuperar uma referencia ao home
object.
getPrimaryKey() - Retorna a chave primria (s para entity beans)
remove() - Destroi o EJB object. (para entitys, tambm deleta os
dados fisicamente da camada de persistncia)
getHandle() - Retorna um handle para o EJB object. Um handle
uma referncia persistente ao EBJ object que o cliente pode
armazenar. Depois, o cliente pode utilizar o handle para readquirir
o EJB object e comear a utiliz-lo novamente.
isIdentical() - Testa se dois EJB objects so idnticos.
Como a interface javax.ejb.EJBHome, essa interface estende a
interface java.rmi.Remote.
No exemplo SomadorBean, a interface remota chamada Somador.
Como voc pode ver, ela copia o mtodo som da implementao do
bean. Voc pode notar tambm que o EJB no implementa a
interface, o LINK feito pelo deployment descriptor.

24/04/04 01:45:40
jp@psique.org http://www.psique.org/cursos

97

EJB Enterprise Java Beans

Curso J150

package org.psique.ejb;
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
public interface Somador extends EJBObject {
public int soma(int a, int b) throws RemoteException;
}

A classe enterprise bean


Essa classe oferece as implementaes dos mtodos de ciclo de vida
na interface home, assim como a lgica comercial definida na
interface remote.
Uma classe enterprise bean ou um session bean, uma entidade
bean, ou um bean direcionaod para mensagem. Em outras palavras,
um session bean implementa a interface javax.ejb.SessionBean um
entity bean implementa a interface javax.ejb.EntityBean. Portanto,
uma classe enterprise bean tambm precisa oferecer a
implementao dos mtodos de retorno de chamada do continer
EJB, definidos na interface javax.ejb.SessionBean ou
javax.ejb.EntityBean.
Os mtodos create e find de ciclo de vida na interface home
correspondem aos mtodos ejbCreate, ejbPostCreate e ejbFind, na
classe bean.

O descritor de distribuio
Um aplicativo EJB precisa de um descritor de distribuio que
especifique meta informaes ao continer EJB. O deployment
descriptor um arquivo XML chamado ejb-jar.xml e precisa estar
localizado no diretrio META-INF, sob o diretrio principal do
24/04/04 01:45:42
jp@psique.org http://www.psique.org/cursos

98

EJB Enterprise Java Beans

Curso J150

aplicativo.
Algumas informaes especificas do descritor de distribuio:

O nome do enterprise beans

O tipo do bean

O nome totalmente qualificado da interface home

O nome totalmente qualificado da interface remote

O descritor de distribuio pode definir mais de um bean.

Como escrever aplicativos clientes


Um enterprise bean um componente do lado servidor que fica
ocioso no servidor, aguardando pro uma chamada de clientes. s
vezes, escrever um EJB cliente pode ser difcil. Porm, sem um
cliente, voc no pode testar seus enterprises beans. Portanto,
entender como o cliente obtm acesso e chama o seu bean uma
parte importante do aplicativo EJB.
Um cliente EJB no chama mtodos, diretamente, na classe
enterprise bean. De fato, um cliente s pode ver as interfaces home
e remote do bean.
Os aplicativos clientes acessam o enterprise bean atravs de JNDI
(Java Naming and Directory Interface). Portanto, muito til
entender JNDI ao escrever aplicativos clientes eficazes.

24/04/04 01:45:43
jp@psique.org http://www.psique.org/cursos

99

EJB Enterprise Java Beans

Curso J150

Um aplicativo cliente
Java
A seguir, juntando tudo que foi visto anteriormente, uma classe
chamada BeanCliente que executa o servio do EJB.

import
import
import
import
import

javax.naming.*;
javax.rmi.PortableRemoteObject;
java.util.Properties;
org.psique.ejb.Somador;
org.psique.ejb.SomadorHome;

public class BeanCliente {


public static void main(String[] args) {
// preparando o properties para construir o
// objeto InitialContext
Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
properties.put(Context.PROVIDER_URL, "localhost:1099");
try {
// Obter o contexto inicial
InitialContext jndiContext = new InitialContext
(properties);
System.out.println("Tenho o contexto");
// Pegar uma referncia ao Bean
Object ref = jndiContext.lookup("Somador");
System.out.println("Tenho a referncia");
// Pega uma referncia interface Home do
// EJB
SomadorHome home = (SomadorHome)
24/04/04 01:45:45
jp@psique.org http://www.psique.org/cursos

100

Um aplicativo cliente Java

Curso J150

PortableRemoteObject.narrow (ref, SomadorHome.class);


// Cria um objeto que implementa a interface
// Somador
Somador somador = home.create();
System.out.println ("2 + 5 = " + somador.soma(2, 5));
}
catch(Exception e) {
System.out.println(e.toString());
}
}
}

Imagina-se que o aplicativo cliente executar no mesmo computador


que o continer, por isto a URL do PROVIDER_URL est
localhost:1099, caso esteja em mquina diferente basta alterar de
localhost para a mquina onde est o continer.
Para executar a classe cliente, os seguintes arquivos no classpath:

ejb.jar
jboss-client.jar
jnp-client.jar

Chamando o bean de uma pgina JSP


Chamar o EJB a partir de um servlet ou jsp igual a cham-lo de
outro cliente. Entretanto, importante copiar todos os arquivos de
biblioteca necessrios no diretrio lib, sob Tomcat, so necessrios
os seguintes arquivos do diretrio home de JBoss:

ejb.jar

jboss-client.jar

24/04/04 01:45:47
jp@psique.org http://www.psique.org/cursos

101

Um aplicativo cliente Java

Curso J150

jnp-client.jar

Finalmente, copie Somador.jar para o diretrio lib em dentro do


WEB-INF. Alternativamente, distribua os arquivos de classe no
diretrio WEB-INF/classes/org/psique/ejb, sob o diretrio do
aplicativo ou no arquivo WAR.
Exemplo de pgina JSP:
<%@ page import="javax.naming.*"%>
<%@ page import="javax.rmi.PortableRemoteObject"%>
<%@ page import="java.util.Properties"%>
<%@ page import="org.psique.ejb.Somador"%>
<%@ page import="org.psique.ejb.SomadorHome"%>
<%
// preparing a Properties object for constructing
// an initial context
Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
properties.put(Context.PROVIDER_URL, "localhost:1099");
try {
// Peguei o contexto inicial
InitialContext jndiContext = new InitialContext
(properties);
System.out.println("Peguei o contexto");
// Peguei a referencia ao Bean
Object ref = jndiContext.lookup("Somador");
System.out.println("Tenho a referencia");
// Peguei a referencia interface home do bean
SomadorHome home = (SomadorHome)
PortableRemoteObject.narrow (ref, SomadorHome.class);
// Criando um objeto Somador da Interface Home
Somador somador = home.create();
out.println ("2 + 5 = " + somador.soma(2, 5));
}
catch(Exception e) {
24/04/04 01:45:49
jp@psique.org http://www.psique.org/cursos

102

Um aplicativo cliente Java

Curso J150

System.out.println(e.toString());
}
%>

24/04/04 01:45:51
jp@psique.org http://www.psique.org/cursos

103

Um aplicativo cliente Java

Curso J150

Mastering EJB 2

24/04/04 01:45:53
jp@psique.org http://www.psique.org/cursos

104

Session Bean Bean de sesso

Curso J150

Session Bean Bean de


sesso
Agora veremos mais detalhadamente o EJB session bean e uma
aplicao cliente para utilizar o session bean.

O que um session bean


Um session bean um EJB que implementa lgica de negcio. Por
exemplo, um session bean pode fazer clculos, processar pedidos,
criptografar, decodificar dados, conectar-se com um banco de
dados, buscar dados em um banco de dados e assim por diante.
Em um aplicativo EJB, onde o cliente um aplicativo web, a lgica
de negcio pode estar no prprio aplicativo web em servlets ou em
pginas web. Usar o session bean como componente que encapsula
a lgica de negcio torna os componentes reutilizveis por outros
tipos de clientes e permite que eles aproveitem os benefcios
oferecidos pelo continer de EJB.
Os sessions beans tem este nome porque vivem enquanto a sesso
do cliente us-lo. Um session bean criado quando um cliente
requer o seu servio. Quando o cliente termina com o bean e
desconecta, o session bean precisa ser destrudo pelo continer EJB.
Porque o objeto de criao uma operao cara, um session bean
realmente pode no ser destrudo pelo continer depois de o bean
servir a um cliente. Ao contrrio, o continer pode colocar o bean
em um pool, para ser rapidamente disponibilizado a outro cliente
que o o solicitar mais tarde. Porm, essa no uma preocupao do
desenvolvedor de aplicativo cliente; o continer EJB gerencia o ciclo
24/04/04 01:45:55
jp@psique.org http://www.psique.org/cursos

105

Session Bean Bean de sesso

Curso J150

de vida de um session bean.


Aviso
Semelhante a outros enterprise beans, um mtodo de um
session bean no copiado ou chamado diretamente pelo
cliente. Um cliente se comunica com o session bean atravs
das interfaces home e remote. Os session beans no tm
persistncia. Quando o servio quebra, os session beans
desaparecem como todos os outros dados no persistentes.

Session beans com estado e sem estado


Voc trabalhar com dois tipos de session beans, stateless (sem
estado) e statefull (com estado). Uma cpia de um session bean
statefull est associada a um nico cliente. O continer EJB sempre
usa a mesma cpia do session bean com estado para servir a um
cliente. Um session bean statefull retm os dados relativos ao
cliente, que so recuperados a partir do banco de dados, ou
informaes fornecidas pelo cliente. Uma sesso do cliente termina
quando o cliente especifica que ele no precisa mais da sesso, ou
depois de passar o tempo pr-determinado, desde que o cliente
chamou o ltimo mtodo. Um session bean com estado similar ao
objeto javax.servlet.http.HttpSession em um aplicativo servlet ou
JSP.

Passivation e Activation de sessions beans


com estado
Conforme mencionado, o continer EJB mantm um pool de session
beans sem posio e com posio. Isto porque a criao de um
objeto caro e o pool torna possvel a reutilizao dos objetos.
Embora o continer EJB possa colocar facilmente um session bean
sem posio em um pool e peg-lo de volta quando o bean for
necessrio, colocar no pool um session bean com estado no to

24/04/04 01:45:56
jp@psique.org http://www.psique.org/cursos

106

Session Bean Bean de sesso

Curso J150

simples. Isto porque o session bean com estado retm os dados


especficos do cliente.
Suponha que um session bean com estado esteja servindo a um
cliente e demore um pouco para o cliente voltar. Se o continer EJB
no tiver muitos clientes na ocasio, o session bean com posio
pode aguardar at que o cliente volte. No entanto, se a demanda
estiver alta, o continer EJB pode ter mais clientes do que a
quantidade de session beans com estado. Um session bean com
estado parado, ocioso, aguardando pela volta do cliente, pode ter
que ser chamado para servir a outro cliente. mas, e quanto ao
estado do cliente anterior? No d para descartar o estado pois o
cliente pode retornar. Ao mesmo tempo ficar ocioso um
desperdcio de recursos.
O continer EJB soluciona este problema apresentado dois processo,
chamados passivao e ativao. Em passivao, a posio de
conversao de um session bean com estado que fique ocioso
aguardando pela volta de seu cliente transferida para a
armazenagem secundria, tal como um espao no disco rgido.
A ativao o inverso da passivao. O processo de ativao
carrega o estado do bean de um cliente a partir do disco para que a
sesso continue. Note que o continer EJB no precisa usar a
mesma cpia do session bean pois o que interessa o estado.

Session Bean Statefull


O continer EJB designa um identificador nico para cada objeto
session bean statefull na criao do bean. Diferente de uma sesso
em um aplicativo servlet/JSP, entretanto, os identificadores de
sesso em um aplicativo EJB no so expostos ao cliente. O cliente
no tem como obter um identificador de sesso. Um cliente pode
determinar se duas referncias de session bean se referem mesma
cpia, usando o mtodo isIdentical da interface ejb.EJBObject. A
assinatura desse mtodo :

24/04/04 01:45:58
jp@psique.org http://www.psique.org/cursos

107

Session Bean Bean de sesso

Curso J150

public boolean isIdentical(javax.ejb.EJBObject object) throws


java.rmi.RemoteException

No session bean statefull o estado da conversao (conversational


state) com o cliente deve ser mantido. Se o cliente remover o bean
ou terminar a sesso, o estado desaparece.

Stateless Session Beans


Um session bean sem posio ou sem estado, no mantm o estado
da conversao entre cliente e servidor. Quando um cliente chama
um mtodo de um session bean stateless, as propriedades de
instncia do bean podem conter um estado, mas apenas durante a
invocao. Quando o mtodo termina o estado no guardado.
Como o bean no possui estado, o bean pode ser utilizado
indistintamente por qualquer cliente.
Os stateless session beans so bem mais leves dos que os statefull
por isto devem ser sempre utilizados quando possvel.

Quando utilizar stateful session beans:

o estado do bean representa a interao entre o bean e um cliente


especfico.

O bean precisa guardar informaes sobre o cliente entre


diversas invocaes de mtodos

O bean um mediador entre o cliente e outro componente da


aplicao, preservando uma viso simplificada para cliente.

O bean est sendo utilizado para gerenciar e controlar o fluxo de

24/04/04 01:46:00
jp@psique.org http://www.psique.org/cursos

108

Session Bean Bean de sesso

Curso J150

vrios EJBs.

Quando utilizar stateless session beans:

O estado do bean no tem dado algum especfico do cliente.

Na invocao de um simples mtodo, o bean executa uma tarefa


genrica para todos os clientes.

O bean busca algum dado no banco de dados que utilizado pelos


clientes.

Como escrever um session bean


Revendo rapidamente o processo de escrita de um session bean,
voc precisa escrever pelo menos trs classes para o session bean
funcionar alm do deployment descriptor.

A interface home

A interface remote

A implementao concreta que o session bean

Uma cpia da interface home chamada de objeto home e uma


cpia da interface remote conhecida como um objeto remote.
A razo pela qual voc precisa de uma interface home e uma
interface remote para cada session bean que o cliente no cria
diretamente o bean, nem um cliente chama diretamente um mtodo
24/04/04 01:46:02
jp@psique.org http://www.psique.org/cursos

109

Session Bean Bean de sesso

Curso J150

de session bean (mesmo porque o objeto real existe no continer e


no na mesma mquina virtual do cliente).
Um objeto home exigido para o cliente criar uma cpia de session
bean. Quando um aplicativo cliente EJB cria uma cpia de um
session bean, chamando um dos mtodos create do objeto home, ele
se refere ao procedimento em que o continer EJB aloca uma cpia
do session bean solicitado para o cliente. Se um continer
realmente cria uma nova cpia de session bean ou apenas pega uma
do pool no problema para o aplicativo cliente.
Um objeto remote retorna quando um aplicativo EJB cliente chama
o mtodo create do objeto home. O objeto remote necessrio, pois
ele a representao remota do session bean. Lembre-se que o
aplicativo cliente no tem acesso direto ao session bean. Quando
voc obtm um objeto remote, pode chamar qualquer mtodo
exposto pelo session bean. Portanto uma interface remota precisa
copiar todos os mtodos do session bean que devem estar
disponveis ao cliente EJB.

A interface javax.ejb.SessionBean
Um session bean precisa estender a interface
javax.ejb.SessionBean. Essa interface estende a interface
javax.ejb.EnterpriseBean e oferece quatro mtodos que so
chamados pelo continer EJB.
Estes mtodos so:

ejbActivate: O continer EJB chama este mtodo quando a cpia


do session bean recuperado do pool para servir a um cliente,
cujo estado de conversao foi armazenado em um dispositivo de

24/04/04 01:46:03
jp@psique.org http://www.psique.org/cursos

110

Session Bean Bean de sesso

Curso J150

armazenagem secundrio no processo de passivao. Voc deve


escrever um cdigo neste mtodo que readquirir recursos que
tenham sido liberados na passivao. A assinatura deste mtodo
:

public void ejbActivate() throws javax.ejb.EJBException,


java.rmi.RemoteException;

ejbPassivate: O continer EJB chama esse mtodo quando a


cpia do session bean est para ser passivado. Voc deve
codificar nele, o cdigo que permita a gravao do estado e
liberao de recursos.

public void ejbPassivate() throws javax.ejb.EJBExcpetion,


java.rmi.RemoteException;

ejbRemote: Esse mtodo chamado quando um cliente chama


um mtodo remove ou quando o continer EJB resolve encerrar o
objeto sesso depois do tempo de encerramento configurado. A
assinatura deste mtodo :

public void ejbRemote() throws javax.ejb.EJBException,


java.rmi.RemoteException

setSessionContext: O continer EJB chama este mtodo depois


da cpia ter sido criada, passando um objeto
javax.ejb.SessionContext. Se voc precisar usar o objeto
SessionContext em um estgio posterior, voc dever guardar
uma referncia deste objeto.

public void setSessionContext(SessionContext context) throws


javax.ejb.EJBException, java.rmi.RemoteException;

Um exemplo de session bean


Um session bean implementa a interface javax.ejb.SessionBean.
preciso fornecer implementao para todos os mtodos daquela
interface, e mais os mtodos que implementam a lgica de negcio.
24/04/04 01:46:05
jp@psique.org http://www.psique.org/cursos

111

Session Bean Bean de sesso

Curso J150

import java.rmi.RemoteException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
public class MeuSessionBean implements SessionBean {
public void ejbCreate() {
}
public void ejbRemove() {
}
public void ejbActivate() {
}
public void ejbPassivate() {
}
public void setSessionContext(SessionContext sc) {
}
// implemente aqui os mtodos de negcio
}

A interface javax.ejb.SessionContext e a
interface javax.ejb.EJBContext
Conforme mencionado anteriormente, o continer EJB passa um
objeto javax.ejb.SessionContext ao mtodo setSessionContext da
interface javax.ejb.SessionBean. A interface SessionContext estende
a interface javax.ejb.EJBContext, que oferece mtodos teis para
obter informaes sobre o aplicativo cliente chamador, o objeto
home bean, o ambiente e outras coisas interessantes.
A definio da interface javax.ejb.EJBContext :

public interface javax.ejb.EJBObject extends java.rmi.Remote {


public javax.ejb.EJBHome getEJBHome()
24/04/04 01:46:07
jp@psique.org http://www.psique.org/cursos

112

Session Bean Bean de sesso

Curso J150

throws java.rmi.RemoteException;
public java.lang.Object getPrimaryKey()
throws java.rmi.RemoteException;
public void remove()
throws java.rmi.RemoteException,
javax.ejb.RemoveException;
public javax.ejb.Handle getHandle()
throws java.rmi.RemoteException;
public Boolena isIdentical(javax.ejb.EJBObject objetct)
throws java.rmi.RemoteException;
}

A definio da interface javax.ejb.SessionContext como a seguir:

public interface javax.ejb.SessionContext


extends javax.ejb.EJBContext {
public javax.ejb.EJBLocalObject get EJBLocalObject()
throws IllegalStateException;
public javax.ejb.EJBObject getEJBObject()
throws IllegalStateException;
}

Como usar um session bean statefull a


partir de uma pgina JSP ou Servlet
Um cliente no web de um session bean com estado no deve ter
problemas em reter a referncia ao bean durante o perodo de vida
da sesso. Um cliente web um caso diferente, j que o protocolo
HTTP stateless, existe uma dificuldade natural na manuteno da
24/04/04 01:46:08
jp@psique.org http://www.psique.org/cursos

113

Session Bean Bean de sesso

Curso J150

sesso. Uma forma interessante de guardar a sesso em um


aplicativo EJB no JSP ou servlet utilizar um objeto
javax.servlet.http.HttpSession. Voc pode guardar a sesso para um
session bean statefull assim:
1. da primeira vez que voc obtiver uma referncia ao session bean
statefull, armazene-a como um atributo do objeto
javax.servlet.http.HttpSession, como a seguir:
HttpSession session = request.getSession(true);
session.setAttribute(carrinho , carrinhoBean);

Este cdigo obtm um objeto HttpSession do objeto request e


depois acrescenta a referncia ao objeto carrinhoBean no objeto
session.
2. da prxima vez que voc precisar do session bean, basta
recuperar a referncia do objeto guardado no HttpSession
HttpSession session = request.getSession(true);
Carrinho carrinhoBean = (Carrinho) session.getAttribute
(carrinho);

O deployment descriptor
Cada aplicativo EJB precisa de um deployment descriptor, que um
documento XML de nome ejb-jar.xml O elemento raiz do descritor
<ejb-jar> e ele contm um n chamado <enterprise-beans>. Cada
session bean , ento, registrado sob esse elemento e chamado de
um elemento <session>. Portanto um elemento <session> descreve
um session bean.
Definio de session na DTD (http://java.sun.com/dtd/ejbjar_2_0.dtd):

24/04/04 01:46:10
jp@psique.org http://www.psique.org/cursos

114

Session Bean Bean de sesso

Curso J150

<!-The session element declares an session bean. The declaration consists


of:
- an optional descricao
- an optional display name
- an optional small icon file name
- an optional large icon file name
- a name assigned to the enterprise bean
in the deployment descriptor
- the names of the session bean's remote home and
remote interfaces, if any
- the names of the session bean's local home and
local interfaces, if any
- the session bean's implementation class
- the session bean's state management type
- the session bean's transaction management type
- an optional declaration of the bean's environment entries
- an optional declaration of the bean's EJB references
- an optional declaration of the bean's local EJB references
- an optional declaration of the security role references
- an optional declaration of the security identity to be
used for the execution of the bean's methods
- an optional declaration of the bean's resource manager
connection factory references
- an optional declaration of the bean's resource environment
references.
The elements that are optional are "optional" in the sense that they
are omitted when if lists represented by them are empty.
Either both the local-home and the local elements or both the
home and the remote elements must be specified for the session bean.
Used in: enterprise-beans
-->

<!ELEMENT session (description?, display-name?, small-icon?,


large-icon?, ejb-name, home?, remote?, local-home?, local?,
ejb-class, session-type, transaction-type, env-entry*, ejb-ref*,
ejb-local-ref*, security-role-ref*, security-identity?, resource-ref*,
resource-env-ref*)>

Na definio acima, o ponto de interrogao indica um elemento


opcional, o asterisco indica que o elemento anterior pode ser
repetido uma ou vrias vezes.

description A descrio do bean.

display-name Nome curto a ser exibido por ferramentas usadas


para editar o deployment descriptor.

small-icon Nome de uma imagem de 16x16 pontos em formato


gif ou jpg. O nome do arquivo o caminho relativo dentro do
arquivo ejb-jar.

large-icon Idem ao anterior, para imagem de 32x32 pontos.

24/04/04 01:46:12
jp@psique.org http://www.psique.org/cursos

115

Session Bean Bean de sesso

Curso J150

ejb-name O nome identificando o session bean. O nome tem


que ser nico no ejb-jar.

home Nome qualificado da interface home

remote Nome qualificado da interface remote

local-home Nome qualificado para a interface local home

local - Nome qualificado para a interface local do bean.

ejb-class - O nome totalmente qualificado para a classe do ejb.

session-type. O tipo de session bean. O valor pode ser Stateless


ou Statefull

transaction-type. O tipo de transao. Os valores possveis so:


Bean ou Container.

env-entry O nome da entrada de ambiente do bean.

ejb-ref A declarao de uma referncia a um home de bean

ejb-local-ref A declarao de uma referncia a um ponto inicial


local do bean.

security-role-ref - A declarao de uma referncia de funo de


segurana no cdigo do bean.

security-identity Se a identidade de segurana do chamador


deve ser usada para a execuo dos mtodos do bean ou uma
identidade executar como especfica deve ser usada.

resource-ref A declarao da referncia de um bean para um


recurso externo.

resource-env-ref A declarao de uma referncia do bean para


um objeto administrado, associado a um recurso no ambiente do
bean.

24/04/04 01:46:14
jp@psique.org http://www.psique.org/cursos

116

Session Bean Bean de sesso

Curso J150

Exemplo de um deployment descriptor:


<?xml version=1.0 encoding=UTF-8?>
<ejb-jar>
<descricao>Exemplo de aplicao</descricao>
<display-name>Exemplo</display-name>
<enterprise-bean>
<session>
<ejb-name>Busca</ejb-name>
<home>org.psique.livraria.ejb.BuscaHome</home>
<remote>org.psique.livraria.ejb.Busca</remote>
<ejb-class>org.psique.livraria.ejb.BuscaBean</ejbclass>
<session-type>Stateless</session-type>
<transaction-type>Bean</transaction-type>
</session>
</enterprise-bean>
</ejb-jar>

24/04/04 01:46:15
jp@psique.org http://www.psique.org/cursos

117

Session Bean Bean de sesso

Curso J150

Exemplo - Livraria
O aplicativo a seguir, chamado livraria. um aplicativo somente
para demonstrao.
O aplicativo usa quatro servlets na interface com o usurio. Os
quatro servlets representam as quatro pginas da interface de
usurio: uma pgina de Busca, uma pgina de detalhes do Livro,
uma pgina de adicionar cesta e uma pgina de verificar cesta.
Funcionalidades do projeto

Um usurio da web busca um livro pelo ttulo, fornecendo uma


palavra chave na pgina Search. Todos os livros cujo ttulo
contm a palavra-chave so listados. Cada ttulo, autor, editora e
livro so exibidos.

A pgina search

24/04/04 01:46:17
jp@psique.org http://www.psique.org/cursos

118

Session Bean Bean de sesso

A Pgina search depois de feita uma busca

Detalhes do livros

24/04/04 01:46:19
jp@psique.org http://www.psique.org/cursos

Curso J150

119

Session Bean Bean de sesso

Curso J150

Comprar nos detalhes do livro (adicionar no carrinho)

24/04/04 01:46:21
jp@psique.org http://www.psique.org/cursos

120

Session Bean Bean de sesso

Curso J150

Adicionar na cesta volta pgina de busca, onde o usurio pode


continuar comprando.

A pgina verificar carrinho de compra.

O banco de dados
A tabela a ser utilizada ter o seguinte formato:
create table livros (
codLivro int primary key,
titulo varchar(50),
autor varchar(50),
editora varchar(50),
preco double);

O objetivo foi criar uma tabela bem simples, somente para


demonstrao.
Exemplo de cdigo para a criao da tabela

24/04/04 01:46:23
jp@psique.org http://www.psique.org/cursos

121

Session Bean Bean de sesso

Curso J150

/*
* Created on 08/04/2004
*
* Para este codigo funcionar, o HSQLDB deve estar no modo
TCP/IP
*
* Alterar arquivo: ${JBOSS_HOME}/
server/default/deploy/hsqldb-ds.xml
*
*/
package bd;
import
import
import
import
import

java.sql.Connection;
java.sql.DriverManager;
java.sql.ResultSet;
java.sql.SQLException;
java.sql.Statement;

/**
* @author F4955639
*
* To change the template for this generated type comment go
to
* Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code
and Comments
*/
public class BancoDeDados {
public static void main(String [] s) {
try {
try {
// Dentro do continer poderia ser:
// DataSource datasource = (DataSource) ctx.lookup
("java:/DefaultDS");
//
Connection conexao = datasource.getConnection();
Class.forName("org.hsqldb.jdbcDriver");
Connection conexao =
DriverManager.getConnection
("jdbc:hsqldb:hsql://localhost:1701","sa","");
Statement st = conexao.createStatement();

//st.execute("drop table livros");


24/04/04 01:46:24
jp@psique.org http://www.psique.org/cursos

122

Session Bean Bean de sesso

Curso J150

st.execute("create table livros ( "+


"codLivro int primary key, "+
"titulo varchar(50), "+
"autor varchar(50), "+
"editora varchar(50), "+
"preco double); ");
System.out.println("Tabela Criada");
st.executeUpdate("insert into livros (codLivro ,
titulo , autor , editora
+ , preco ) values ( 1 , 'RAPUNZEL' , 'Maria Joo' ,
'Amrica' , 10.10 ) ");
st.executeUpdate("insert into livros (codLivro ,
titulo , autor , editora
+ , preco ) values ( 2 , 'ILHA PERDIDA' , 'Joao Maria' ,
'Africa' , 20.10 ) ");
st.executeUpdate("insert into livros (codLivro , titulo ,
autor , editora
,
preco ) values ( 3 , '1300 KILOMETROS' , 'Rolando
Vespcio' , 'Amrica' ,
+ 30.00 ) ");
st.executeUpdate("insert into livros (codLivro , titulo ,
autor , editora
+ , preco ) values ( 4 , 'MARCHA AO SOL' , 'Armando
Lero' , 'Africa' , 10.10 ) ");
st.executeUpdate("insert into livros (codLivro , titulo ,
autor , editora
+ , preco ) values ( 5 , 'LUA REDONDA' , 'Jurasica' ,
'Amrica' , 15.90 ) ");
System.out.println("Registros inseridos");
ResultSet rs = st.executeQuery("select * from
livros");
while(rs.next()) {
System.out.print( "cod:" + rs.getString
(1));
System.out.print( "\t titulo:" +
rs.getString(2));
System.out.print( "\t autor:" +
rs.getString(3));
System.out.print( "\t editora:" +
rs.getString(4));
System.out.println( "\t preco:" +
24/04/04 01:46:26
jp@psique.org http://www.psique.org/cursos

123

Session Bean Bean de sesso

Curso J150

rs.getString(5));
}

conexao.close();

catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();

}
} catch(Throwable t) {
t.printStackTrace();
}
}
}

O aplicativo de exemplo consiste em dois session beans stateless e


um session bean statefull.

O session bean de busca - Stateless


O primeiro session, chamado Busca, encontra todos os livros cujos
ttulos combinam com a palavra-chave de busca. A interface home
para o session bean:

package org.psique.livraria.ejb;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
24/04/04 01:46:28
jp@psique.org http://www.psique.org/cursos

124

Session Bean Bean de sesso

Curso J150

public interface BuscaHome extends EJBHome {


Busca create() throws RemoteException, CreateException;
}

A interface Remote:

package org.psique.livraria.ejb;
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
import java.util.ArrayList;
public interface Busca extends EJBObject {
public ArrayList search(String palavra) throws
RemoteException;
}

A partir da interface remote voc sabe que s h um mtodo


exposto ao cliente: busca. Esse mtodo aceita uma string
representando a palavra-chave de busca e retorna um ArrayList
contendo todos os livros que combinam com a string de busca.
Cada livro no ArrayList representado em um array de string.

package org.psique.livraria.ejb;
import
import
import
import

java.sql.Connection;
java.sql.ResultSet;
java.sql.SQLException;
java.sql.Statement;

import java.util.ArrayList;

24/04/04 01:46:30
jp@psique.org http://www.psique.org/cursos

125

Session Bean Bean de sesso

import
import
import
import

Curso J150

javax.ejb.SessionBean;
javax.ejb.SessionContext;
javax.naming.InitialContext;
javax.sql.DataSource;

public class BuscaBean implements SessionBean {

private Connection getConnection() {


Connection connection = null;
try {
//
Class.forName("org.hsqldb.jdbcDriver");
//
connection = DriverManager.getConnection
(jdbc:hsqldb:hsql://localhost:1701","sa","");
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup
("java:/DefaultDS");
connection = ds.getConnection();
}
catch (Exception e) {
}
return connection;
}
public ArrayList search(String palavra) {
ArrayList retval = new ArrayList(50);
Connection con = null;
try {
System.out.println("Busca ");
con = getConnection();
Statement statement = con.createStatement();
String sql = "SELECT codLivro , titulo , autor ,
editora , preco " +
" FROM livros " +
" WHERE titulo LIKE '%" + palavra + "%'";
System.out.println("Vou executar a query " +sql);
ResultSet rs = statement.executeQuery(sql);
System.out.println("Varrendo os resultados");
while (rs.next()) {
System.out.println("achei!");
24/04/04 01:46:31
jp@psique.org http://www.psique.org/cursos

126

Session Bean Bean de sesso

Curso J150

String[] row = new String[5];


row[0] = rs.getString(1);
row[1] = rs.getString(2);
row[2] = rs.getString(3);
row[3] = rs.getString(4);
row[4] = rs.getString(5);
retval.add(row);
System.out.println("Inserindo:" + row[1]);
}
rs.close();
statement.close();
con.close();
}
catch (Exception e) {
e.printStackTrace();
if(con != null) {
try {
con.close();
} catch (SQLException e1) {

}
}
return retval;
}
public void ejbCreate() {
}
public void ejbRemove() {
}
public void ejbActivate() {
}
public void ejbPassivate() {
}
public void setSessionContext(SessionContext sc) {
}
}

24/04/04 01:46:33
jp@psique.org http://www.psique.org/cursos

127

Session Bean Bean de sesso

Curso J150

O session bean DetalhesDoLivro stateless


O segundo session bean tambm sem posio e chamado
DetalhesDoLivro. A funo retornar os detalhes de um livro, dado
o identificador de um livro. Esse bean chamado a partir de um
servlet, assim, a partir de outro bean, representando um cliente
remote e um cliente local. Neste exemplo, v-se a diferena no
cdigo para um cliente remoto ou local.
A interface Home do bean DetalhesDoLivro

package

org.psique.livraria.ejb;

import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
public interface DetalhesDoLivroHome extends EJBHome {
DetalhesDoLivro create() throws RemoteException,
CreateException;
}

A interface Remote do bean DetalhesDoLivro:


package

org.psique.livraria.ejb;

import javax.ejb.EJBObject;
import java.rmi.RemoteException;
public interface DetalhesDoLivro extends EJBObject {
public String[] getDetalhesDoLivro(String codLivro) throws
RemoteException;
}

Novamente, apenas um mtodo exposto ao seu cliente: o mtodo


getDetalhesDoLivro. Esse mtodo aceita uma string representando
24/04/04 01:46:35
jp@psique.org http://www.psique.org/cursos

128

Session Bean Bean de sesso

Curso J150

o identificador do livro e retorna um array de string contendo o id


do livro, o ttulo, o autor, a editora e o preo. A Listagem abaixo
relaciona a implementao da classe bean DetalhesDoLivro.

package

org.psique.livraria.ejb;

import
import
import
import

java.sql.Connection;
java.sql.ResultSet;
java.sql.SQLException;
java.sql.Statement;

import
import
import
import

javax.ejb.SessionBean;
javax.ejb.SessionContext;
javax.naming.InitialContext;
javax.sql.DataSource;

public class DetalhesDoLivroBean implements SessionBean {


private Connection getConnection() {
Connection connection = null;
try {
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup
("java:/DefaultDS");
connection = ds.getConnection();
}
catch (Exception e) {
}
return connection;
}
public String[] getDetalhesDoLivro(String codLivro) {
String[] row = null;
Connection con = null;
try {
con = getConnection();
Statement statement = con.createStatement();
String sql = "SELECT codLivro, titulo, autor, editora,
24/04/04 01:46:37
jp@psique.org http://www.psique.org/cursos

129

Session Bean Bean de sesso

Curso J150

preco" +
" FROM Livros" +
" WHERE CodLivro=" + codLivro;
System.out.println("Exec query" + codLivro);
ResultSet rs = statement.executeQuery(sql);
if (rs.next()) {
System.out.println("Localizei");
row = new String[5];
row[0] = rs.getString("codLivro");
row[1] = rs.getString("titulo");
row[2] = rs.getString("autor");
row[3] = rs.getString("editora");
row[4] = rs.getString("preco");
}
rs.close();
statement.close();
con.close();
}
catch (Exception e) {
e.printStackTrace();
if(con!=null)
try {
con.close();
} catch (SQLException e1) {}
}
return row;
}
public void ejbCreate() {
}
public void ejbRemove() {
}
public void ejbActivate() {
}
public void ejbPassivate() {
}
public void setSessionContext(SessionContext sc) {
}
}
24/04/04 01:46:39
jp@psique.org http://www.psique.org/cursos

130

Session Bean Bean de sesso

Curso J150

Teste parcial da aplicao


Para o teste necessrio criar um pacote WAR (livaria.war) com o
descritor web.xml no diretrio WEB-INF e para empacotar o JAR
dos EJBs (livraria.jar) e o WAR, faz-se necessria a criao de um
arquivo EAR (livraria.ear) que possui o descritor application.xml e
os arquivo WAR e JAR.
O web.xml deve estar dentro do diretrio WEB-INF do arquivo
livraria.war:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web
Application 2.3//EN" "http://java.sun.com/dtd/webapp_2_3.dtd">
<web-app id="WebApp">
<display-name>Livraria</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>

application.xml deve ser colocado no diretrio META-INF do


livraria.ear.

24/04/04 01:46:40
jp@psique.org http://www.psique.org/cursos

131

Session Bean Bean de sesso

Curso J150

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE application PUBLIC "-//Sun Microsystems, Inc.//DTD
J2EE Application 1.3//EN"
"http://java.sun.com/dtd/application_1_3.dtd">
<application id="Application_ID">
<display-name>Livraria</display-name>
<module>
<ejb>livraria-EJB.jar</ejb>
</module>
<module>
<web>
<web-uri>livraria-WAR.war</web-uri>
<context-root>/livraria</context-root>
</web>
</module>
</application>

Um jsp para testar, busca.jsp deve ser colocado no raiz do War.


<%@ page import="javax.naming.*"%>
<%@ page import="javax.rmi.PortableRemoteObject"%>
<%@ page import="java.util.Properties"%>
<%@ page import="java.util.ArrayList"%>
<%@ page import="java.util.Iterator"%>
<%@ page import="org.psique.livraria.ejb.Busca"%>
<%@ page import="org.psique.livraria.ejb.BuscaHome"%>
<html>
<body>
<h3>Execuo de um EJB para Buscar um livro</h3>
<%
if(request.getParameter("busca")!=null) {
String nome = (String) request.getParameter("busca");

try {
Context context = new InitialContext();
System.out.println("Peguei o contexto");
Object ref = context.lookup("Busca");
System.out.println("Tenho a referencia");

24/04/04 01:46:42
jp@psique.org http://www.psique.org/cursos

132

Session Bean Bean de sesso

Curso J150

// Peguei a referencia interface home do bean


BuscaHome home = (BuscaHome)
PortableRemoteObject.narrow (ref, BuscaHome.class);
System.out.println("Criando o EJB Busca");
// Criando um objeto Somador da Interface Home
Busca busca = home.create();
System.out.println("Criei o EJB Busca");
ArrayList a = busca.search(nome);
System.out.println("Executei o search");
Iterator i = a.iterator();
while(i.hasNext()) {
String [] s = (String []) i.next();
for(int n = 0;n<s.length;n++) {
out.print( s[n] );
if(n<s.length-1)
out.print(" - " );
else
out.println("<br/>");
}
}
}
catch(Exception e) {
System.out.println(e.toString());
}
}
%>
<hr>
<form method="post">
Busca: <input type="text" name="busca"/><br/>
<input type="submit"/>
</form>
</body>
</html>

Agora que foi testado... Continuamos com as funcionalidades:

24/04/04 01:46:44
jp@psique.org http://www.psique.org/cursos

133

Session Bean Bean de sesso

Curso J150

Um session bean de um carrinho de


compras Statefull
Um session bean Carrinho com estado, pois necessrio que o
carrinho de compras armazene o estado para cada usurio. Voc
pode adicionar um tem ao bean Carrinho e recuperar o bean para
verificar o que dentro. A interface home e a interface remote para
esse bean:

package

org.psique.livraria.ejb;

import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
public interface CarrinhoHome extends EJBHome {
Carrinho create() throws RemoteException, CreateException;
}

Agora a interface remote:

package

org.psique.livraria.ejb;

import javax.ejb.EJBObject;
import java.rmi.RemoteException;
import java.util.List;
public interface Carrinho extends EJBObject {
public List getCarrinho() throws RemoteException;
public void addCarrinho(String codLivro, String quantidade)
24/04/04 01:46:46
jp@psique.org http://www.psique.org/cursos

134

Session Bean Bean de sesso

Curso J150

throws RemoteException;
}

O mtodo addCarrinho aceita dois argumentos: codLivro,


selecionado pelo usurio, e a quantidade de cpias que o usurio
gostaria de comprar. O mtodo addCarrinho no retorna valor.
O segundo mtodo, getCarrinho, retorna o carrinho de compras na
forma de um ArrayList. Note que voc no passa um identificador
de usurio ou outros sinais ao mtodo para obter o carrinho de
compras atuais, pois a posio de conversao de cada usurio
retida por esse bean com posio.
A classe bean para o bean Carrinho:

package org.psique.livraria.ejb;
import java.util.ArrayList;
import java.util.List;
import
import
import
import

javax.ejb.SessionBean;
javax.ejb.SessionContext;
javax.naming.Context;
javax.naming.InitialContext;

/**
* @author jp
*
* 11/04/2004 16:25:12
*
*
*/
public class CarrinhoBean implements SessionBean {

24/04/04 01:46:47
jp@psique.org http://www.psique.org/cursos

135

Session Bean Bean de sesso

Curso J150

private List carrinho = null;


public void addCarrinho(String codLivro, String
quantidade) {
String[] row = new String[6];
row[0] = codLivro;
row[1] = quantidade;
try {
Context jndiContext = new InitialContext();
Object ref = jndiContext.lookup("Detalhes");
System.out.println(
"Tenho a referncia para DetalhesDoLivro");
// no necessrio usar
javax.rmi.PortableRemoteObject
// porque um cliente local
DetalhesDoLivroHome home =
(DetalhesDoLivroHome) ref;
System.out.println("Tenho o home de
DetalhesDoLivro");
DetalhesDoLivro detalhesDoLivro = home.create
();
System.out.println("Tenho detalhes do Livro");
String[] detalhes =
detalhesDoLivro.getDetalhesDoLivro(codLivro);
row[2] = detalhes[1]; // Ttulo
row[3] = detalhes[2]; // Autor
row[4] = detalhes[3]; // Editora
row[5] = detalhes[4]; // Preo
} catch (Exception e) {
System.out.println(e.toString());
}
carrinho.add(row);
}
public List getCarrinho() {
return carrinho;
}
public void ejbCreate() {
// Na criao do bean, deve ser criado um no List
para armazenagem dos dados
carrinho = new ArrayList();
24/04/04 01:46:49
jp@psique.org http://www.psique.org/cursos

136

Session Bean Bean de sesso

Curso J150

}
public void ejbRemove() {
}
public void ejbActivate() {
}
public void ejbPassivate() {
}
public void setSessionContext(SessionContext sc) {
}
}

O aplicativo EJB descritor de distribuio


Abaixo o deployment descriptor da aplicao:

<?xml version="1.0" encoding="ISO-8859-1"?>


<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD
Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejbjar_2_0.dtd">
<ejb-jar >
<descricao>Livraria</descricao>
<display-name>Livraria</display-name>
<enterprise-beans>
<session >
<description><![CDATA[Busca]]></description>
<display-name>Busca</display-name>
<ejb-name>Busca</ejb-name>
<home>org.psique.livraria.ejb.BuscaHome</home>
<remote>org.psique.livraria.ejb.Busca</remote>
<ejb-class>org.psique.livraria.ejb.BuscaBean</ejbclass>

24/04/04 01:46:51
jp@psique.org http://www.psique.org/cursos

137

Session Bean Bean de sesso

Curso J150

<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
<session >
<description><![CDATA[DetalhesDoLivro]]
></description>
<display-name>Detalhes</display-name>
<ejb-name>Detalhes</ejb-name>
<home>org.psique.livraria.ejb.DetalhesDoLivroHome</ho
me>
<remote>org.psique.livraria.ejb.DetalhesDoLivro</remo
te>
<ejbclass>org.psique.livraria.ejb.DetalhesDoLivroBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
<session>
<ejb-name>Carrinho</ejb-name>
<home>org.psique.livraria.ejb.CarrinhoHome</home>
<remote>org.psique.livraria.ejb.Carrinho</remote>
<ejb-class>org.psique.livraria.ejb.CarrinhoBean</ejbclass>
<session-type>Stateful</session-type>
<transaction-type>Bean</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>

Criao do deployment descriptor


Depois de ter compilado todos os beans e interfaces e colocado o
deployment descriptor no diretrio META-INF, necessrio gerar
um arquivo de distribuio para o EJB.
jar cvf livraria.jar org/psique/livraria/ejb/* META-INF/ejbjar.xml
24/04/04 01:46:53
jp@psique.org http://www.psique.org/cursos

138

Session Bean Bean de sesso

Curso J150

Distribuio no JBoss
Para distribuir no JBoss, basta copiar no diretrio de deploy.

A poro WEB da aplicao:


Juntos, os quatro servlets BuscaServlets, DetalhesDoLivroServlet,
AdicionarNoCarrinhoServlet e VerificarCarrinhoServlet
representam um aplicativo cliente web que usa os session beans.

O servlet BuscaServlet
O BuscaServlet exibe a pgina de busca. A pgina de busca a
pgina principal, assim como a primeira pgina que o usurio ver.
A pgina dividida em trs partes:

Formulrio de busca

A tabela de resultado da busca

O link para o VerificarCarrinhoServlet

Abaixo o Cdigo do BuscaServlet:


package org.psique.livraria.servlet;
import
import
import
import

java.io.IOException;
java.io.PrintWriter;
java.util.List;
java.util.Properties;

import
import
import
import
import

javax.naming.Context;
javax.naming.InitialContext;
javax.rmi.PortableRemoteObject;
javax.servlet.ServletException;
javax.servlet.http.HttpServlet;

24/04/04 01:46:54
jp@psique.org http://www.psique.org/cursos

139

Session Bean Bean de sesso

Curso J150

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.psique.livraria.ejb.Busca;
import org.psique.livraria.ejb.BuscaHome;
public class BuscaServlet extends HttpServlet {
private String palavra;
/**Processando a requisio HTTP */
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
displayPage(request, response);
}
/**Processando a requisio Post HTTP */
public void doPost(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
palavra = request.getParameter("palavra");
displayPage(request, response);
}
private void displayPage(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
/* Alm do cabealho e do rodap, ,
existem 4 partes nesta pgina:
1. O Ttulo
2. O formulrio de busca
3. A tabela de resultados
4. O link para o Verificar o Carrinho
*/
response.setContentType("text/html");
PrintWriter out = response.getWriter();
// header
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>Bem-vindo livraria</TITLE>");
24/04/04 01:46:56
jp@psique.org http://www.psique.org/cursos

140

Session Bean Bean de sesso

Curso J150

out.println("</HEAD>");
out.println("<BODY>");
out.println("<CENTER>");
// Ttulo
out.println("<H2>Bem vindo livraria</H2>");
// Formulrio de busca
out.println("<BR>");
out.println("<FORM METHOD=POST>");
out.println("Ttulo: <INPUT TYPE=TEXT
NAME=palavra>");
out.println("<INPUT TYPE=SUBMIT VALUE=Busca");
out.println("</FORM>");
out.println("<HR>");
// Resultado da busca
out.println("<BR>");
out.println("<H3>Resultados da Busca</H3>");
out.println("<BR>");
mostrarResultadoDeBusca(out);
out.println("<HR>");
// Link para verificar o carrinho
out.println("<BR>");
out.println(
"<A HREF=\VerificarCarrinhoServlet\>Verificar o carrinho de
compras</A>");
// rodap
out.println("</CENTER>");
out.println("</BODY>");
out.println("</HTML>");

}
// Mostrando o resultado
private void mostrarResultadoDeBusca(PrintWriter out) {
if (palavra != null && !palavra.trim().equals(""))
{
// palavra correta, mostrando o resultado
aqui.

24/04/04 01:46:58
jp@psique.org http://www.psique.org/cursos

141

Session Bean Bean de sesso

Curso J150

Properties properties = new Properties();


properties.put(
Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory"
);
properties.put(Context.PROVIDER_URL,
"localhost:1099");
try {
// Pegando o contexto
Context jndiContext = new InitialContext
(properties);
// Pegando a referncia ao home do Bean
Object ref = jndiContext.lookup("Busca");
BuscaHome home =
(BuscaHome)
PortableRemoteObject.narrow(
ref,
BuscaHome.class);
// Obtm uma referencia para um objeto

Busca

a partir do Home
Busca buscaBean = home.create();
List lista = buscaBean.search(palavra);
int n = lista.size();
out.println("<TABLE BORDER=1>");
out.println("<TR>");
out.println("<TH WIDTH=350>Ttulo</TH>");
out.println("<TH WIDTH=150>Autor</TH>");
out.println("<TH
WIDTH=150>Editora</TH>");
out.println("<TH WIDTH=50>&nbsp</TH>");
out.println("</TR>");
for (int i = 0; i < n; i++) {
String[] s = (String[]) lista.get
(i);
out.println("<TR>");
out.println("<TD>" + s[1] +
"</TD>");
out.println("<TD>" + s[2] +
"</TD>");
out.println("<TD>" + s[3] +
24/04/04 01:46:59
jp@psique.org http://www.psique.org/cursos

142

Session Bean Bean de sesso

Curso J150

"</TD>");
out.println(
"<TD><A HREF=\DetalhesDoLivroServlet?codLivro="
+ s[0]
+
"\>Detalhes</A></TD>");
out.println("</TR>");
}
out.println("</TABLE>");
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
}

O servlet DetalhesDoLivroServlet
O servlet DetalhesDoLivroServlet abaixo:

package org.psique.livraria.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;
import
import
import
import
import
import
import

javax.naming.Context;
javax.naming.InitialContext;
javax.rmi.PortableRemoteObject;
javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

import org.psique.livraria.ejb.DetalhesDoLivro;
import org.psique.livraria.ejb.DetalhesDoLivroHome;

24/04/04 01:47:01
jp@psique.org http://www.psique.org/cursos

143

Session Bean Bean de sesso

Curso J150

public class DetalhesDoLivroServlet extends HttpServlet {


/**Processando a requisio HTTP do tipo Get*/
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
String codLivro = request.getParameter("codLivro");
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>Detalhes do livro</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
out.println("<CENTER>");
Properties properties = new Properties();
properties.put(
Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
properties.put(Context.PROVIDER_URL,
"localhost:1099");
try {
// Pegando um contexto de nomes
Context jndiContext = new InitialContext
(properties);
// Pegando uma referncia ao Bean
Object ref = jndiContext.lookup("Detalhes");
// Arrumando a referncia para a interface
home
DetalhesDoLivroHome home =
(DetalhesDoLivroHome)
PortableRemoteObject.narrow(
ref,
DetalhesDoLivroHome.class);
// Criando uma instncia de DetalhesDoLivro a
partir do home
DetalhesDoLivro detalhesDoLivroBean =
home.create();
String[] row =
24/04/04 01:47:03
jp@psique.org http://www.psique.org/cursos

144

Session Bean Bean de sesso

Curso J150

detalhesDoLivroBean.getDetalhesDoLivro(codLivro);
out.println("<H3>Detalhes do Livro</H3>");
out.println("<BR>");
out.println("<TABLE BORDER=0>");
out.println("<TR>");
out.println("<TD><B>Ttulo:</B></TD>");
out.println("<TD>" + row[1] + "</TD>");
out.println("</TR>");
out.println("<TR>");
out.println("<TD><B>Autor:</B></TD>");
out.println("<TD>" + row[2] + "</TD>");
out.println("</TR>");
out.println("<TR>");
out.println("<TD><B>Editora:</B></TD>");
out.println("<TD>" + row[3] + "</TD>");
out.println("</TR>");
out.println("<TR>");
out.println("<TD><B>Preco:</B></TD>");
out.println("<TD>$" + row[4] + "</TD>");
out.println("</TR>");
out.println("</TABLE>");
out.println("<BR>");
out.println("<BR>");
out.println("<HR>");
out.println("<BR>");
out.println("<BR>");
out.println("<B>Colocar este livro no
carrinho</B>");
out.println("<BR>");
out.println(
"<FORM METHOD=POST ACTION=\AdicionarNoCarrinhoServlet\>");
out.println(
"<INPUT TYPE=HIDDEN Name=codLivro VALUE=" +
row[0] + ">");
out.println("Quero adquirir ");
out.println(

"<INPUT TYPE=TEXT SIZE=1 Name=quantidade VALUE=1> copia(s)


deste livro");
out.println("&nbsp;&nbsp;");
out.println("<INPUT TYPE=SUBMIT
VALUE=Comprar>");
out.println("</FORM>");
out.println("<BR>");
out.println("<HR>");

24/04/04 01:47:05
jp@psique.org http://www.psique.org/cursos

145

Session Bean Bean de sesso

Curso J150

} catch (Exception e) {
System.out.println(e.toString());
}
out.println("</CENTER>");
out.println("</BODY>");
out.println("</HTML>");
}
}

O servlet adicionarNoCarrinhoServlet
O session bean carrinho .

package org.psique.livraria.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;
import
import
import
import
import
import
import
import

javax.naming.Context;
javax.naming.InitialContext;
javax.rmi.PortableRemoteObject;
javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;

import org.psique.livraria.ejb.Carrinho;
import org.psique.livraria.ejb.CarrinhoHome;
public class AdicionarNoCarrinhoServlet extends HttpServlet {
/**Processar a requisio Post http*/
public void doPost(
24/04/04 01:47:06
jp@psique.org http://www.psique.org/cursos

146

Session Bean Bean de sesso

Curso J150

HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
// cabecalho
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>Adicionar no
Carrinho</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
out.println("<CENTER>");
String codLivro = request.getParameter("codLivro");
String quantidade = request.getParameter
("quantidade");
if (codLivro != null
&& quantidade != null
&& !codLivro.trim().equals("")
&& !quantidade.trim().equals("")) {
try {
HttpSession session =

request.getSession(true);
Carrinho carrinho =
(Carrinho) session.getAttribute
("carrinho");
if (carrinho == null) { // uma sesso
nova
Properties properties = new
Properties();
properties.put(
Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory"
);
properties.put(Context.PROVIDER_URL,
"localhost:1099");
// Pegando o contexto
Context jndiContext = new InitialContext
(properties);
// Pegar a referencia ao Bean
Object ref = jndiContext.lookup
24/04/04 01:47:08
jp@psique.org http://www.psique.org/cursos

147

Session Bean Bean de sesso

Curso J150

("Carrinho");
CarrinhoHome home =
(CarrinhoHome)
PortableRemoteObject.narrow(
ref,
CarrinhoHome.class);
// Criando o bean!!!
carrinho = home.create();
}
carrinho.addCarrinho(codLivro,
quantidade);
session.setAttribute("carrinho",
carrinho);
out.println(
"<B>O livro foi adicionado no carrinho</B>");
} catch (Exception e) {
out.println(e.toString());
}
}
out.println("<BR>");
out.println("<BR>");
out.println(
"<A HREF=\BuscaServlet\>"
+ "Voltar para a pagina de busca</A>");
out.println("</CENTER>");
out.println("</BODY>");
out.println("</HTML>");
}
}

O servlet VerificarCarrinhoServlet

package org.psique.livraria.servlet;

24/04/04 01:47:10
jp@psique.org http://www.psique.org/cursos

148

Session Bean Bean de sesso

Curso J150

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import
import
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;

import org.psique.livraria.ejb.Carrinho;
public class VerificarCarrinhoServlet extends HttpServlet {
/**Processar os request GET HTTP

*/

public void doGet(HttpServletRequest request,


HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
// header
out.println("<HTML>");
out.println("<HEAD>");
out.println(
"<TITLE>Verificando o carrinho de
compras</TITLE>");
out.println("</HEAD>");
out.println("<BODY>");
out.println("<CENTER>");
out.println("<H2>Detalhes de seu carrinho</H2>");
out.println("<BR>");
out.println("<TABLE BORDER=2>");
out.println("<TR>");
out.println("<TH>Nro.Cpias</TH>");
out.println("<TH>Ttulo</TH>");
out.println("<TH>Autor</TH>");
out.println("<TH>Editora</TH>");
out.println("<TH>Preco</TH>");
out.println("</TR>");

24/04/04 01:47:12
jp@psique.org http://www.psique.org/cursos

149

Session Bean Bean de sesso

Curso J150

HttpSession session = request.getSession(false);


if (session != null) {
try {
Carrinho carrinho = (Carrinho)
session.getAttribute("carrinho");
List lista = carrinho.getCarrinho();
int count = lista.size();
for (int i = 0; i < count; i++) {
out.println("</TR>");
String[] row = (String[]) lista.get
(i);
out.println("<TD>" + row[1] +
"</TD>");
out.println("<TD>" + row[2] +
"</TD>");
out.println("<TD>" + row[3] +
"</TD>");
out.println("<TD>" + row[4] +
"</TD>");
out.println("<TD>" + row[5] +
"</TD>");
out.println("</TR>");
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
out.println("</TABLE>");
out.println("<BR>");
out.println("<BR>");
out.println(

"<A HREF=\"BuscaServlet\">" +
"Voltar pgina de busca</A>");
out.println("</CENTER>");
out.println("</BODY>");
out.println("</HTML>");
}
}

24/04/04 01:47:14
jp@psique.org http://www.psique.org/cursos

150

Session Bean Bean de sesso

Curso J150

A distribuio do aplicativo cliente.


Para distribuir o aplicativo cliente, preciso compilar os quatro
servlets acima e criar para eles um descritor de distribuio para
WEB.
web.xml

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web
Application 2.3//EN" "http://java.sun.com/dtd/webapp_2_3.dtd">
<web-app id="WebApp">
<display-name>livraria</display-name>
<servlet>
<servlet-name>AdicionarNoCarrinhoServlet</servletname>
<servlet-class>
org.psique.livraria.servlet.AdicionarNoCarrinhoServlet
</servlet-class>
</servlet>
<servlet>
<servlet-name>BuscaServlet</servlet-name>
<servletclass>org.psique.livraria.servlet.BuscaServlet
</servlet-class>
</servlet>
<servlet>
<servlet-name>DetalhesDoLivroServlet</servlet-name>
<servlet-class>
org.psique.livraria.servlet.DetalhesDoLivroServlet
</servlet-class>
</servlet>
<servlet>
<servlet-name>VerificarCarrinhoServlet</servlet-name>
<servlet-class>
org.psique.livraria.servlet.VerificarCarrinhoServlet

24/04/04 01:47:15
jp@psique.org http://www.psique.org/cursos

151

Session Bean Bean de sesso

Curso J150

</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AdicionarNoCarrinhoServlet</servlet-name>
<url-pattern>/AdicionarNoCarrinhoServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>BuscaServlet</servlet-name>
<url-pattern>/BuscaServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>BuscaServlet</servlet-name>
<url-pattern>/index.jsp</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>DetalhesDoLivroServlet</servlet-name>
<url-pattern>/DetalhesDoLivroServlet</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>VerificarCarrinhoServlet</servlet-name>
<url-pattern>/VerificarCarrinhoServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/index.jsp</welcome-file>
</welcome-file-list>
</web-app>

Um application.xml que une os EJBs com a aplicao WEB.


application.xml

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE application PUBLIC "-//Sun Microsystems, Inc.//DTD
J2EE Application 1.3//EN"

24/04/04 01:47:17
jp@psique.org http://www.psique.org/cursos

152

Session Bean Bean de sesso

Curso J150

"http://java.sun.com/dtd/application_1_3.dtd">
<application id="livraria">
<display-name>Livraria</display-name>
<module>
<ejb>livraria-EJB.jar</ejb>
</module>
<module>
<web>
<web-uri>livraria-WAR.war</web-uri>
<context-root>/livraria</context-root>
</web>
</module>
</application>

24/04/04 01:47:19
jp@psique.org http://www.psique.org/cursos

153

Session Bean Bean de sesso

Curso J150

Entity Beans
Armazenagem de dados
Um dos problemas computacionais mais comuns armazenar dados
de forma persistente e recuperar estes dados. A serializao pode
ser uma forma interessante de armazenar objetos java o principal
problema da serializao a recuperao. Imagine que nossa
empresa tem 20.000.000 de clientes, cada cliente um objeto
serializado no disco. Se voc precisar recuperar todos os clientes
que fazem aniversrio no dia, voc ter que ler todos os 20.000.000,
ou seja, desserializ-los criando o objeto e testando se o dia e o ms
da data de nascimento tem o valor que interessa. Como pode notar,
a serializao no interessante quando os volumes de dados so
grandes.
Outra soluo poderia ser a utilizao de um banco de dados que
suporte objetos, utilizando um banco orientado a objetos isto pode
ser feito de maneira mais eficaz, mas a tecnologia de bancos de
dados orientados a objetos ainda no est madura.
A terceira opo utilizar um bom e velho banco de dados
relacional para armazenagem dos dados. Neste caso, precisamos
fazer um mapeamento dos dados que esto em forma de objetos
para a forma tabular utilizada pelo banco de dados relacional. Este
mapeamento objeto-relacional pode ser feito manualmente ou podese utilizar uma forma automtica de fazer isto. Existem vrias
solues de persistncia para isto tais como Hybernate, OJB, JDO, e
a que veremos adiante Entity Bean CMP.

24/04/04 01:47:20
jp@psique.org http://www.psique.org/cursos

154

Entity Beans

Curso J150

O que um Entity Bean?


Um entity bean um componente de dados que guarda
permanentemente os dados em um dispositivo de armazenagem
secundria - normalmente Banco de Dados. Os campos do entity
sero "mapeados" para as colunas de uma tabela de banco de
dados.
Em um aplicativo EJB, um entity bean uma vista para um registro
para uma tabela de banco de dados. Ao invs de manipular dados
diretamente no banco de dados, voc manipula um entity bean que
a representao de uma pea de dados.
O continer EJB cuida da sincronizao e de outras tarefas de
manuteno dos dados. Um entity bean vive tanto quanto os dados
que ele representa. portanto, um entity bean poderia durar anos.
Se um entity bean representa uma conta bancria, possvel que o
entity viva tanto quanto a conta bancria que fica no banco de
dados. Como a conta REAL normalmente dura muitos anos, o entity
que a representao VIRTUAL tambm pode durar muito tempo.
Resumindo Entity Bean um componente:

Que uma representao java na memria de um dado


persistente.

Esperto o bastante para saber como ler-se de um banco de dados


ou outra camada de persistncia e como popular seus campos
com os dados lidos.

Um objeto que quando alterado na memria, replica a alterao


para a camada de persistncia.

Em primeiro lugar, porque voc precisa de um objeto, tal como um


entity bean, para armazenar dados? Por que voc no acessa
24/04/04 01:47:22
jp@psique.org http://www.psique.org/cursos

155

Entity Beans

Curso J150

diretamente o banco e manipula os dados nele? Ou por que no


escreve simplesmente session beans para acessar os dados?
Simples: Primeira razo: Gerenciar dados como objetos mais
Fcil. Segunda Razo: o continer EJB oferece servios que
facilitam lidar com os dados representados pelos entitys.

Qual a diferena de Entity Bean x Session


Bean?
Por que necessrio um tipo diferente de EJB (Enterprise Java
Bean)?
Pelo objetivo:
Um session bean modela um processo comercial (uma regra de
negcio), um entity bean representa dados comerciais (ou dados
do ). O continer EJB sabe como sincronizar os dados em um entity
bean com os dados dependentes no banco de dados que a entidade
representa. Alm disso, entity beans sobrevivem quebra do
servidor.
Entity beans podem ser compartilhados entre vrios clientes. J que
vrios clientes podem querer alterar dados, muito importante que
um entity bean trabalhe em transaes.
Outra diferena que os Entity Beans possuem chave primria que
um objeto que identifica unicamente cada Entity Bean. atravs da
chave primria possvel um cliente localizar um entity qualquer.
Da mesma forma que uma tabela de um banco de dados relacional,
os entitys podem implementar relacionamentos entre diferentes
tipos de entity beans.
Existem dois tipos de entitys beans: entitys com persistncia
gerenciada por bean (BMP) e entitys com persistncia gerenciada
pelo continer (CMP). Ambos so discutidos mais adiante, neste
captulo, depois de uma viso geral de um entity bean.
24/04/04 01:47:24
jp@psique.org http://www.psique.org/cursos

156

Entity Beans

Curso J150

Exatamente como um session bean, um entity precisa ser


acompanhado por vrios arquivos que voc escreve, alm do entity:

A interface remote

A interface home

A classe de chave principal

O Entity Bean

O descritor de distribuio (Deployment Descriptor)

Adiante cada arquivo destes ser comentado. O descritor de


distribuio explicado nos captulos sobre os dois tipos de entity.

A interface remote
A interface remote de um entity permite a um cliente acessar a
cpia de um entity bean. A interface remota de um entity precisa
estender a interface javax.ejb.EJBObject. Na interface remota, o
desenvolvedor de interface remote define mtodos que podem ser
chamados pelo cliente do bean. Por exemplo, a interface remote de
um entity que representa um produto pode ter dois mtodos,
chamados getPreco e getCategoria, como abaixo:

public interface Produto extends javax.ejb.EJBObject {


double getPreco(int codProduto) throws
java.rmi.RemoteException;
int getCategoria(int codProduto) throws
java.rmi.RemoteException;
}

24/04/04 01:47:25
jp@psique.org http://www.psique.org/cursos

157

Entity Beans

Curso J150

O mtodo getPreco retorna o preo do produto e o mtodo


getCategoria retorna o identificador da categoria em que o produto
se encontra. O cliente pode usar a interface remote para fazer o
seguinte:
- Obter a interface home para o objeto entity
- Remover o objeto entity
- Obter a chave primria do objeto entity
- Obter o gerenciador do objeto entity.

A interface HOME
Um cliente do entity bean obtm o objeto home - isto , uma cpia
da interface home - de um objeto remote do entity bean. O cliente
usa o objeto home para fazer o seguinte:
- Criar um objeto entity
- Remover um objeto entity
- Encontrar um objeto entity
- Obter a interface javax.ejb.EJBMetaData para um entity bean
A interface home permite ao cliente realizar essas tarefas,
fornecendo os mtodos create, finders e remove.

24/04/04 01:47:27
jp@psique.org http://www.psique.org/cursos

158

Entity Beans

Curso J150

Mtodo create
Uma interface home pode ter zero ou mais mtodos create. A
interface home pode ter mais do que um mtodo create, para
possibilitar a criao de objetos entity de diversas formas. Por
exemplo, a seguir est o mtodo create da interface home, de um
entity bean chamado produto. O nome do produto, a descrio e o
preo.

public interface ProdutoHome extends javax.ejb.EJBHome {


public Produto create(int codProduto ,
String nomeProduto ,
String descricao ,
double preco)
throws java.rmi.RemoteException,
javax.ejb.CreateException;

Um mtodo create pode lanar java.rmi.RemoteException e uma


javax.ejb.CreateException.

Mtodos finder
Um entity bean representa uma pea de dados e uma das operaes
comuns com dados a recuperao. Para localizar um entity bean,
utilizamos os mtodos finder. mtodos finder so exclusivos de
entity beans, um session bean no tem mtodo finder.

24/04/04 01:47:28
jp@psique.org http://www.psique.org/cursos

159

Entity Beans

Curso J150

Uma interface home precisa definir um mtodo findByPrimaryKey,


para permitir ao cliente achar um objeto entity passando uma chave
primria. Alm disso, uma interface home pode ter outros mtodos
finder. Por exemplo, uma interface home do entity bean Produto
tambm precisa definir os mtodos findByNome e findByPreco.
Embora um mtodo finByPrimaryKey sempre retorne zero ou um
entity bean que atinge este critrio, outros mtodo finder podem
retornar valores mltiplos.
Em mtodos finder que podem retornar mltiplos valores, os tipos
de valor de retorno para esses mtodos so java.util.Collection ou
java.util.Enumeration.
Como um exemplo, a seguinte interface home para um entity bean
chamado Produto define trs mtodos finder:

public interface ProdutoHome extends javax.ejb.EJBHome {


public Produto findByPrimaryKey(String codProduto)
throws java.rmi.RemoteException,
javax.ejb.FinderException;
public Enumeration findByNomeProduto(String nomeProduto)
throws java.rmi.RemoteException,
javax.ejb.FinderException;
public Collection findAll()
throws java.rmi.RemoteException,
javax.ejb.FinderException;
}

24/04/04 01:47:31
jp@psique.org http://www.psique.org/cursos

160

Entity Beans

Curso J150

Mtodos Remove
Um mtodo remove usado para remover um objeto entity. A
interface home de um entity bean derivada da interface
javax.ejb.EJBHome, que define dois mtodos remove. As assinaturas
dos dois mtodos remove so:

void remove(javax.ejb.Handle handle)


throws java.rmi.RemoteException ,
javax.ejb.RemoveException;

void remove(Object primaryKey)


throws java.rmi.RemoteException ,
javax.ejb.RemoveException;

A classe da chave primria


Semelhante a uma tabela de banco de dados relacional, que
normalmente tem uma chave primria para identificar unicamente
cada ocorrncia da tabela, um entity bean precisa tambm de uma
chave primria que identifique unicamente uma ocorrncia. O tipo
da classe de chave primria de um entity bean precisa ser um dos
tipos aceitos em RMI-IIOP ou seja, um tipo primitivo, um objeto
serializvel ou uma referncia remota (stub).

Um entity bean
Uma classe de entity bean precisa implementar a interface
javax.ejb.EntityBean. Essa interface define mtodos que
24/04/04 01:47:33
jp@psique.org http://www.psique.org/cursos

161

Entity Beans

Curso J150

determinam o ciclo de vida do bean, assim como outros mtodos de


retorno de chamada que so chamados pelo Continer EJB.

A interface javax.ejb.EntityBean
Essa interface estende a interface javax.ejb.EnterpriseBean e
oferece mtodos de retorno de chamada que so convocados pelo
continer EJB. Os mtodos da interface EntityBean so como a
seguir:
ejbActivate: O continer EJB chama esse mtodo quando a cpia do
entity bean recuperada do pool para se tornar associada a um
objeto entity especfico
public void ejbActivate() throws
javax.ejb.EJBException, java.rmi.RemoteException

ejbPassivate: O continer EJB chama esse mtodo quando a


associao da cpia do entity bean com o seu objeto entity est para
ser quebrada. Esse mtodo tem a seguinte assinatura:
public void ejbPassivate() throws
javax.ejb.EJBException, java.rmi.RemoteException

ejbLoad: Esse mtodo chamado pelo continer EJB para


sincronizar a posio do entity bean carregando seu estado do
banco de dados (l o estado da tabela):
public void ejbLoad() throws javax.ejb.EJBException
java.rmi.RemoteException;

ejbStore: Esse mtodo chamado pelo continer EJB para


sincronizar a posio do bean com os dados da tabela (grava o
estado do bean na tabela). A assinatura desse mtodo :
public void ejbStore() throws javax.ejb.EJBException,
java.rmi.RemoteException;
24/04/04 01:47:35
jp@psique.org http://www.psique.org/cursos

162

Entity Beans

Curso J150

ejbRemove: Esse mtodo chamado pelo continer EJB antes do


continer remover o objeto entity. Esse mtodo chamado quando
um cliente chama um mtodo remove na interface home, ou
interface remote, da entidade bean. A assinatura desse mtodo
como a seguir:
public void ejbRemove() throws javax.ejb.EJBException,
java.rmi.RemoteException;

setEntityContext: O continer EJB chama este mtodo depois de a


cpia ter sido criada ajustando o continer associado entidade. A
assinatura deste mtodo :
public void setEntityContext(EntityContext context)
throws javax.ejb.EJBEntity, java.rmi.RemoteException;

unsetEntityContext: O continer EJB chama este mtodo antes de


remover a cpia do entity bean. Esse mtodo desfaz o ajuste do
contexto de entity associado. A assinatura desse mtodo :
public void unsetEntityContext() throws
javax.ejb.EJBEntity, java.rmi.RemoteException;

Nota
O continer EJB mantm a sincronia entre dados em campos de um
entity Bean e o banco de dados usando os mtodos ejbLoad e
ejbStore de javax.ejb.EntityBean.
Graas sincronia durante as chamadas aos mtodos ejbLoad e
ejbStore, se os dados com os quais um entity bean est associado
tiverem mudado diretamente no banco de dados o estado do entity
no ser afetado.

24/04/04 01:47:38
jp@psique.org http://www.psique.org/cursos

163

Entity Beans

Curso J150

Activation e Passivation
Da mesma forma que um session bean com estado, um entity bean
tambm pode realizar os processos de ativao e passivao. Porm,
esses processos so mais envolvidos em um session bean com
estado. Com em um session bean com estado, a ativao inclui a
restaurao do estado anterior a recursos para determinado cliente,
e a passivao exige que o bean libere os recursos que esto sendo
retidos e salve o estado com a posio de conversao de um cliente
em uma armazenagem secundria.
Como o continer decide quais beans ativar e quais beans passivar?
A resposta especfica para cada continer. A maior dos continers
utiliza a estratgia LRU (Least Recently Used), que simplesmente
significa passivar o bean que foi chamado menos recentemente. A
passivao pode ocorrer a qualquer tempo, a exceo regra que
qualquer bean envolvido em uma transao no pode ser passivado
at que a transao se complete.
Em um entity bean, a passivao inclui liberar recursos, assim como
salvar os dados de volta no banco de dados. Para salvar a posio de
um entity bean, o continer EJB chama o mtodo ejbStore do bean,
antes da passivao. A ativao em um entity bean, por outro lado,
inclui a recuperao do estado, para isto o continer chama o
mtodo ejbLoad do entity depois da ativao.
Tudo que considerado parte do estado conversacional do bean
salvo (serializado) na passivao. O estado conversacional refere-se
a:

Variveis membros de um tipo primitivo no transiente

Variveis membros de um objeto Java no transiente.

O continer chama (call back) dois mtodos para informar da


ocorrncia da ativao/passivao que so:

24/04/04 01:47:39
jp@psique.org http://www.psique.org/cursos

164

Entity Beans

Curso J150

ejbPassivate() - Avisando que ocorrer uma passivao


ejbActivate() - Avisando que ocorrer uma ativao
Normalmente no necessrio codificar nada nestes mtodos, mas
estes mtodos podem servir para guardar e readquirir recursos que
no so guardados durante a ativao e passivao, como conexes
a banco de dados, sockets abertos, arquivos abertos, ou qualquer
outro que seja necessrio.

Mtodos create Criando um entity


Cada mtodo create na interface home precisa ter um mtodo
create correspondente na classe entity bean. Esse mtodo
correspondente tem os mesmos argumentos que o mtodo create na
interface home; entretanto, os nomes dos mtodos create no entity
bean so prefixados com ejb. Isso significa que, em uma classe
entity bean, voc tem zero ou mais mtodos ejbCreate, e, na
interface home, tem o mesmo nmero de mtodos create
correspondentes.
No entanto, os mtodos ejbCreate retornam um valor do tipo de
classe de chave primria, a interface home retorna um EJB object.
Alm disso, um mtodo ejbCreate precisa ser pblico e no pode ser
declarado final ou esttico.
Abaixo uma figura ilustrando o relacionamento entre o create() do
cliente (interface home) e o ejbCreate().

24/04/04 01:47:41
jp@psique.org http://www.psique.org/cursos

165

Entity Beans

Curso J150

Por exemplo, uma entidade bean chamado Produto, tem o seguinte


mtodo ejbCreate:

package org.psique.produto.ejb;
import java.rmi.RemoteException;
import javax.ejb.EJBException;
import javax.ejb.EntityContext;
import javax.ejb.RemoveException;
public class ProdutoBean implements javax.ejb.EntityBean {
public String codProduto;
public String nomeProduto;
public String descricao;
public double preco;
public String ejbCreate(
int codProduto,
String nomeProduto,
String descricao,
24/04/04 01:47:43
jp@psique.org http://www.psique.org/cursos

166

Entity Beans

Curso J150

double preco)
throws java.rmi.RemoteException,
javax.ejb.CreateException {
this.codProduto = Integer.toString(codProduto);
this.nomeProduto = nomeProduto;
this.descricao = descricao;
this.preco = preco;
return Integer.toString(codProduto);
}
public void ejbActivate() throws EJBException,
RemoteException {
}
public void ejbLoad() throws EJBException,
RemoteException {
}
public void ejbPassivate() throws EJBException,
RemoteException {
}
public void ejbRemove()
throws RemoveException, EJBException,
RemoteException {
}
public void ejbStore() throws EJBException,
RemoteException {
}
public void setEntityContext(EntityContext arg0)
throws EJBException, RemoteException {
}
public void unsetEntityContext() throws EJBException,
RemoteException {
}
}

24/04/04 01:47:45
jp@psique.org http://www.psique.org/cursos

167

Entity Beans

Curso J150

Encontrando um Entity
A classe entity bean precisa ter um mtodo finder correspondente
de todos os mtodos finder na interface home. Exatamente como os
mtodos create, um mtodo finder em uma classe entity bean
prefixado com ejb e tem a mesma lista de argumentos que o mtodo
finder correspondente na interface home.
Por exemplo, uma classe entity bean pode conter dois mtodos
finder: ejbFindByPrimaryKey e ejbfindByNome, como voc v aqui:

public ProdutoPK ejbFindByPrimaryKey(ProdutoPK chavePrimaria)


throws RemoteException, FinderException {
.
.
.
}
public Enumeration ejbFindByNome(String nome)
throws RemoteException, FinderException {
.
.
.
}

O tipo de retorno do mtodo ejbFindByPrimaryKey ProdutoPK,


que a classe de chave primria. A classe chave primria vista
mais adiante neste captulo.

Removendo um Entity
Uma classe entity bean deve definir um mtodo ejbRemove().
24/04/04 01:47:47
jp@psique.org http://www.psique.org/cursos

168

Entity Beans

Curso J150

Para destruir um entity bean no banco de dados, o cliente precisa


chamar o mtodo remove() do EJB object ou do home object. Este
mtodo faz com que o continer faa uma chamada a ejbRemove()
no bean. Note que o mtodo remove() pode ser chamado do home
object ou do EJB object.
O mtodo ejbRemove() no destri somente o dado em memria, ele
apaga o registro correspondente no banco de dados tambm!
Como os mtodos create e finder, o nome do mtodo remove
prefixado com ejb. Por exemplo, o mtodo remove de um entity bean
Produto :
public void ejbRemove()
throws java.rmi.RemoteException, javax.ejb.RemoveException
{
.
.
.
}

Reforando...
Um entity bean uma vista de uma pea e dados em um banco de
dados. Portanto, chamar os mtodos ejbCreate e ejbRemove causa
efeitos em um entity bean diferentes dos de um session bean.
Quando o continer EJB chama o mtodo ejbCreate de um entity
bean, ele cria alguns dados que corresponde cpia do entity bean
na memria. Quando o continer EJB chama o mtodo ejbRemove
de um entity bean, o continer EJB tambm apaga os dados
associados ao entity bean do banco de dados.

24/04/04 01:47:48
jp@psique.org http://www.psique.org/cursos

169

Entity Beans

Curso J150

Outros mtodos
O entity bean oferece implementaes para mtodos declarados na
interface remote. Os mtodos na classe entity bean precisam ter o
mesmo tipo de retorno e lista de argumentos que o mtodo
correspondente na interface remote. Esses mtodos precisam ser
mtodos pblicos e no podem ser estticos. Por exemplo, considere
a seguinte interface remote:

public interface Produto extends javax.ejb.EJBObject {


double getPreco(int codProduto) throws
java.rmi.RemoteException;
int getCategoria(int codProduto) throws
java.rmi.RemoteException;
}

Esse entity bean tem os seguintes mtodos:

public class ProdutoBean implements javax.ejb.EntityBean {


double getPreco(int codProduto)
throws java.rmi.RemoteException {
.
.
.
}
int getCategoria(int codProduto)
throws java.rmi.RemoteException {
.
.
.
}
.
.
.
}
24/04/04 01:47:50
jp@psique.org http://www.psique.org/cursos

170

Entity Beans

Curso J150

A interface javax.ejb.EntityContext
Todos os EJBs tem um contexto do objeto, que identifica o ambiente
do bean. Este objeto contm informaes ambientais que o
continer EJB configura. Seus beans podem acessar o contexto para
recuperar estas informaes, tais como informaes sobre
transaes e segurana.
Para os entity beans a interface para os dados do contexto
javax.ejb.EntityContext. A interface EntityContext derivada da
interface javax.ejb.EJBContext. Ela define alguns mtodos, entre
eles: getEJBObject/getEJBLocalObject (da interface
javax.ejb.EJBContext) e getPrimaryKey (da interface
javax.ejb.EntityContext).
O mtodo getEJBObject() ou getEJBLocalObject() retorna uma
referncia ao objeto enterprise associado a essa cpia de entity
bean.

javax.ejb.EJBObject getEJBObject()
throws IllegalStateException

O mtodo getPrimaryKey() retorna a chave principal do objeto. Esse


mtodo tem a seguinte assinatura:
Object getPrimaryKey()
throws IllegalStateException

24/04/04 01:47:52
jp@psique.org http://www.psique.org/cursos

171

Entity Beans

Curso J150

Este mtodo recupera a chave primria que est associada com esta
instncia de entity bean. A chave primria identifica unicamente um
bean na camada de persistncia, a chave primria pode ser utilizada
para recuperar um entity bean porque no existiro dois beans com
a mesma chave primria.
Para que utilizar getPrimaryKey? Voc pode chamar este mtodo
sempre que quizer saber com que dados do banco de dados sua
instncia est associada.

Dois tipos de entity beans


Por ora, voc deve estar ciente de que todo o ponto de ter um entity
bean que ele mantm dados. Dependente de como os seus dados
so armazenados, um entity bean pode ser de um destes tipos:

Um entity bean com persistncia gerenciada por bean (CMP)

Um entity bean com persistncia gerenciada pelo continer


(BMP)

Um entity bean com BMP cuida de processo de manuteno dos


prprios dados. O programador de bean pode usar comandos SQL
para conseguir isso.
A persistncia de dados em um entity bean com CMP, porm,
cuidada pelo continer EJB. Voc d instrues ao continer EJB
sobre como fazer isso no descritor de distribuio do aplicativo EJB.
Para o programador, entitys beans com CMP exigem menos linhas
de cdigo para programar. os entitys com CMP so mais fceis, pois
no h cdigo de acesso a dados passvel de erros.

24/04/04 01:47:53
jp@psique.org http://www.psique.org/cursos

172

Entity Beans

Curso J150

Entity Bean - BMP


Um entity bean BMP gerencia a sua prpria persistncia. Em nvel
bem bsico, o desenvolvedor de bean precisa oferecer, na classe
entity bean, um mtodo para conectar com o banco de dados.
Alternativamente, se um mtodo semelhante tiver sido
disponibilizado em outro EJB, o programador do entity precisar
escrever um mtodo que retorne um objeto java.sql.Connection,
obtido a partir do outro bean.
No entanto, a tarefa da conexo de banco de dados de alguma
forma, facilitada em um entity bean. O continer EJB carrega o
driver de banco de dados JDBC para voc. Isso significa que no
preciso usar o mtodo Class.forName() para voc mesmo carregar o
driver. Voc diz ao continer EJB como encontrar o driver JDBC.
Voc faz isso com aplicativo especfico de servidor. Veremos como
fazer isto no JBoss.
O exemplo a seguir mostra como escrever um entity BMP chamado
Produto que tem os dados na tabela Produto do banco de dados.
Para experimentar este exemplo, voc precisa ter um banco de
dados JDBC, utilizaremos o HSQLDB.
Para escrever uma classe de entity bean, precisamos criar uma
clase que implemente a interface javax.ejb.EntityBean. Esta
interface determina alguns mtodos que precisam ser
implementados. A maioria destes mtodos so de gerenciamento
chamados pelo continer EJB.
A interface EnterpriseBean vista abaixo, somente uma Marker
Interface (o pattern Marker Interface, a utilizao de uma
interface com significado semntico, ou seja, a interface no possui
mtodo algum, ela somente utilizada para marcar um dado
24/04/04 01:47:55
jp@psique.org http://www.psique.org/cursos

173

Entity Bean - BMP

Curso J150

como sendo de um tipo):


public interface javax.ejb.EnterpriseBean
implements java.io.Serializable {
}

A interface EntityBean:
public interface javax.ejb.EntityBean
extends javax.ejb.EnterpriseBean {
public void setEntityContext(javax.ejb.EntityContext);
public void unsetEntityContext();
public void ejbRemove();
public void ejbActivate();
public void ejbPassivate();
public void ejbLoad();
public void ejbStore();
}

Alm dos mtodos acima que voc deve implementar na sua classe
EntityBean, voc deve ter mtodos create e find.
Eis a lista de coisas que precisamos para criar um Entity BMP:
1 Criao da tabela produto
CREATE TABLE Produto
{
codProduto int primary key,
nomeProduto varchar(50),
descricao varchar(100),
preco double
}

2 Conseguir um driver JDBC para o banco de dados.


3 Configurar um driver diferente do hsqldb no JBoss (ex. MySQL).
a. Copiar o driver JDBC no diretrio ${JBOSS_HOME}/lib/ext

24/04/04 01:47:57
jp@psique.org http://www.psique.org/cursos

174

Entity Bean - BMP

Curso J150

b. Procurar no arquivo jboss.jcml no diretrio


JBOSSDist/conf/default as seguintes linhas:
<mbeam code=org.jboss.jdbc.JdbcProvider
name=DefaultDomain;service=JdbcProvider>
<attribuite name=Drivers>
org.hsqldb.jdbcDriver
</attribute>
</mbeam>

Em seguida, acrescente outra entrada para o seu driver, abaixo em


vermelho o exemplo para o MySQL:
<mbeam code=org.jboss.jdbc.JdbcProvider
name=DefaultDomain:service=JdbcProvider>
<attribute name=Drivers>
org.hsqldb.jdbcDriver,org.gjt.mm.mysql.Driver
</attribute>
</mbeam>

4 Preparar a estrutura de diretrios em seu projeto. As classes que


voc vai escrever aqui so parte do pacote org.psique.ejb; portanto,
preciso ter um diretrio org, dentro dele um psique e dentro dele
um EJB:
Diretrio do projeto
org
psique
ejb
META-INF

A interface remote
A primeira classe a explorar a interface remote para o entity bean
Produto com BMP. O arquivo chamado Produto.java:
24/04/04 01:47:58
jp@psique.org http://www.psique.org/cursos

175

Entity Bean - BMP

Curso J150

Produto.java

package org.psique.produto.ejb;
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
/* esta interface remote para o Produto */
public interface Produto extends EJBObject {
public int getCodProduto() throws RemoteException;
public double getPreco() throws RemoteException;
public String getNomeProduto() throws RemoteException;
public String getDescricao() throws RemoteException;
}

A interface remote define quatro mtodos de negcio: getProduto,


getPreco, getNomeProduto e getDescricao.

A interface Home
A interface home define um mtodo create que aceita quatro
argumentos e dois mtodos finder. O mtodo findByPrimaryKey
aceita um objeto primary key e retorna um objeto remote. O mtodo
findByNome aceita um nome de produto e retorna uma
Enumeration contendo todos os produtos cujos nomes combinam
com o argumento. comum incluir-se na interface home os home
mthods que so mtodos de negcio que no esto relacionados
com nenhuma instncia de Entity em particular.

ProdutoHome.java

24/04/04 01:48:00
jp@psique.org http://www.psique.org/cursos

176

Entity Bean - BMP

Curso J150

package org.psique.produto.ejb;
import
import
import
import

java.rmi.RemoteException;
javax.ejb.FinderException;
javax.ejb.CreateException;
javax.ejb.EJBHome;

import java.util.Collection;
public interface ProdutoHome extends EJBHome {
public Produto create(int productId, String productName,
String description, double price)
throws RemoteException, CreateException;
public Produto findByPrimaryKey(ProdutoPK key)
throws RemoteException, FinderException;
public Collection findByNome(String name)
throws RemoteException, FinderException;
}

A classe primary key


Um entity bean tem uma chave primria. A classe primary key para
um entity bean Produto org.psique.produto.ejb.ProdutoPK.
Verifique no cdigo abaixo que existe um campo pblico chamado
codProduto:
ProdutoPK.java

package org.psique.produto.ejb;
import java.io.Serializable;
public class ProdutoPK implements Serializable {
public String codProduto;
public ProdutoPK(String codProduto) {
this.codProduto = codProduto;
}

24/04/04 01:48:02
jp@psique.org http://www.psique.org/cursos

177

Entity Bean - BMP

Curso J150

public ProdutoPK() {}
public boolean equals(Object obj ) {
return codProduto.equals(((ProdutoPK)obj).codProduto);
}
public int hashCode() {
return codProduto.hashCode();
}
}

O entity bean
A classe entity bean a classe mais importante que contm
implementaes para os mtodos de retorno de chamada e mtodos
de negcio.

ProdutoBean.java

package org.psique.produto.ejb;
import
import
import
import
import
import
import
import
import

java.rmi.RemoteException;
java.sql.Connection;
java.sql.DriverManager;
java.sql.PreparedStatement;
java.sql.ResultSet;
java.sql.SQLException;
java.util.ArrayList;
java.util.Collection;
java.util.List;

import javax.ejb.CreateException;
import javax.ejb.EntityBean;
24/04/04 01:48:03
jp@psique.org http://www.psique.org/cursos

178

Entity Bean - BMP

import
import
import
import
import
import

Curso J150

javax.ejb.EntityContext;
javax.ejb.FinderException;
javax.ejb.ObjectNotFoundException;
javax.naming.Context;
javax.naming.InitialContext;
javax.naming.NamingException;

public class ProdutoBean implements EntityBean {


EntityContext contexto;
int codProduto;
String nomeProduto;
String descricao;
double preco;

/**
* Geter para o cdigo do produto
*
* @return
*/
public int getCodProduto() {
System.out.println("getCodProduto");
return codProduto;
}

/**
* Geter para o Nome do Produto
*
* @return
*/
public String getNomeProduto() {
System.out.println("getNomeProduto");
return nomeProduto;
}
/**
* Geter para a descrioo do produto
*
* @return
*/
public String getDescricao() {
24/04/04 01:48:05
jp@psique.org http://www.psique.org/cursos

179

Entity Bean - BMP

Curso J150

System.out.println("getDescricao");
return descricao;
}

/**
* Geter para o preo
*
* @return
*/
public double getPreco() {
System.out.println("getPreco");
return preco;
}
/**
*
* Cria um novo entity, devolve a chave primria
* do entity criado.
*
* @param codProduto
* @param nomeProduto
* @param descricao
* @param preco
* @return
* @throws RemoteException
* @throws CreateException
*/
public ProdutoPK ejbCreate(
int codProduto,
String nomeProduto,
String descricao,
double preco)
throws RemoteException, CreateException {
System.out.println("ejbCreate");
this.codProduto = codProduto;
this.nomeProduto = nomeProduto;
this.descricao = descricao;
this.preco = preco;
Connection con = null;
PreparedStatement ps = null;
try {
String sql =
"INSERT INTO Produto"
24/04/04 01:48:07
jp@psique.org http://www.psique.org/cursos

180

Entity Bean - BMP

Curso J150

+ " (codProduto, nomeProduto,


descricao, preco) "
+ " VALUES"
+ " (?, ?, ?, ?)";
con = getConnection();
ps = con.prepareStatement(sql);
ps.setInt(1, codProduto);
ps.setString(2, nomeProduto);
ps.setString(3, descricao);
ps.setDouble(4, preco);
ps.executeUpdate();
} catch (SQLException e) {
System.out.println(e.toString());
} finally {
try {
if (ps != null)
ps.close();
if (con != null)
con.close();
} catch (SQLException e) {
}
}
return new ProdutoPK(Integer.toString(codProduto));
}

/**
*
* Executado logo aps o create
*
* Deve existir um ejbPostCreate para cada
* ejbCreate existente (mesma assinatura)
*
* @param productId
* @param productName
* @param descricao
* @param preco
* @throws RemoteException
* @throws CreateException
24/04/04 01:48:09
jp@psique.org http://www.psique.org/cursos

181

Entity Bean - BMP

Curso J150

*/
public void ejbPostCreate(
int productId,
String productName,
String descricao,
double preco)
throws RemoteException, CreateException {
System.out.println("ejbPostCreate");
}
/**
* @param primaryKey
* @return
* @throws RemoteException
* @throws FinderException
*/
/**
*
* Mtodo para localizaoo pela chave primria
* obrigatria a existncia!
*
* @param primaryKey
* @return
* @throws RemoteException
* @throws FinderException
*/
public ProdutoPK
ejbFindByPrimaryKey(ProdutoPK primaryKey)
throws RemoteException, FinderException {
System.out.println("ejbFindByPrimaryKey");
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql =
"SELECT nomeProduto" +
" FROM Produto" +
" WHERE codProduto=?";
int productId =
Integer.parseInt(primaryKey.codProduto);
con = getConnection();
ps = con.prepareStatement(sql);
ps.setInt(1, productId);
rs = ps.executeQuery();
24/04/04 01:48:10
jp@psique.org http://www.psique.org/cursos

182

Entity Bean - BMP

Curso J150

if (rs.next()) {
rs.close();
ps.close();
con.close();
return primaryKey;
}
} catch (SQLException e) {
System.out.println(e.toString());
} finally {
try {
if (rs != null)
rs.close();
if (ps != null)
ps.close();
if (con != null)
con.close();
} catch (SQLException e) { }
}
throw new ObjectNotFoundException();
}
/**
* Mtodo para procurar por nome
*
* @param name
* @return
* @throws RemoteException
* @throws FinderException
*/
public Collection ejbFindByNome(String nome)
throws RemoteException, FinderException {
System.out.println("ejbFindByNome");
List produtos = new ArrayList();
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql =
"SELECT codProduto " +
" FROM Produto" +
24/04/04 01:48:12
jp@psique.org http://www.psique.org/cursos

183

Entity Bean - BMP

Curso J150

" WHERE nomeProduto=?";


con = getConnection();
ps = con.prepareStatement(sql);
ps.setString(1, nome);
rs = ps.executeQuery();
while (rs.next()) {
int codProduto = rs.getInt(1);
produtos.add(
new ProdutoPK(
Integer.toString(codProduto)));
}
} catch (SQLException e) {
System.out.println(e.toString());
} finally {
try {
if (rs != null)
rs.close();
if (ps != null)
ps.close();
if (con != null)
con.close();
} catch (SQLException e) {
}
}
return produtos;
}
/*
* Remover o entity, do continer e do B.D.
*
* @see javax.ejb.EntityBean#ejbRemove()
*/
public void ejbRemove() throws RemoteException {
System.out.println("ejbRemove");
Connection con = null;
PreparedStatement ps = null;
try {
String sql = "DELETE FROM Produto" +
" WHERE codProduto=?";
ProdutoPK chave =
(ProdutoPK) contexto.getPrimaryKey();
int codProduto =
Integer.parseInt(chave.codProduto);
con = getConnection();
24/04/04 01:48:14
jp@psique.org http://www.psique.org/cursos

184

Entity Bean - BMP

Curso J150

ps = con.prepareStatement(sql);
ps.setInt(1, codProduto);
ps.executeUpdate();
} catch (SQLException e) {
System.out.println(e.toString());
} finally {
try {
if (ps != null)
ps.close();
if (con != null)
con.close();
} catch (SQLException e) { }
}
}
public void ejbActivate() {
System.out.println("ejbActivate");
}
public void ejbPassivate() {
System.out.println("ejbPassivate");
}
/*
* @see javax.ejb.EntityBean#ejbLoad()
*/
public void ejbLoad() {
System.out.println("ejbLoad");
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql =
"SELECT nomeProduto, descricao, preco"
+ " FROM produto"
+ " WHERE codProduto=?";
con = getConnection();
ps = con.prepareStatement(sql);
ps.setInt(1, this.codProduto);
rs = ps.executeQuery();
if (rs.next()) {
this.nomeProduto = rs.getString(1);
this.descricao = rs.getString(2);
this.preco = rs.getDouble(3);
24/04/04 01:48:16
jp@psique.org http://www.psique.org/cursos

185

Entity Bean - BMP

Curso J150

}
} catch (SQLException e) {
System.out.println(e.toString());
} finally {
try {
if (rs != null)
rs.close();
if (ps != null)
ps.close();
if (con != null)
con.close();
} catch (SQLException e) {
}
}
}
public void ejbStore() {
System.out.println("ejbStore");
Connection con = null;
PreparedStatement ps = null;
try {
String sql =
"UPDATE Produto" +
" SET nomeProduto=?, descricao=?, preco=?" +
" WHERE codProduto=?";
ProdutoPK chave =
(ProdutoPK) contexto.getPrimaryKey();
int codProduto =
Integer.parseInt(chave.codProduto);
con = getConnection();
ps = con.prepareStatement(sql);
ps.setString(1, this.nomeProduto);
ps.setString(2, this.descricao);
ps.setDouble(3, this.preco);
ps.setInt(4, codProduto);
ps.executeUpdate();
} catch (SQLException e) {
System.out.println(e.toString());

24/04/04 01:48:18
jp@psique.org http://www.psique.org/cursos

186

Entity Bean - BMP

Curso J150

} finally {
try {
if (ps != null)
ps.close();
if (con != null)
con.close();
} catch (SQLException e) {
}
}
}
public void setEntityContext(EntityContext contexto) {
System.out.println("setEntityContext");
// Guarda uma referncia para o contexto
// para uso posterior.
this.contexto = contexto;
}
public void unsetEntityContext() {
System.out.println("unsetEntityContext");
contexto = null;
}
public Connection getConnection() {
String dbUrl = null;
String userName = null;
String password = null;
Context initialContext;
Context environment;
Connection connection = null;
try {
initialContext = new InitialContext();
environment =
(Context) initialContext.lookup("java:comp/env/jdbc");
dbUrl = (String) environment.lookup("dbUrl");
userName =
(String) environment.lookup("dbUserName");
password =
(String) environment.lookup("dbPassword");
24/04/04 01:48:19
jp@psique.org http://www.psique.org/cursos

187

Entity Bean - BMP

Curso J150

} catch (NamingException e) {
System.out.println(e.toString());
}
try {
connection =
DriverManager.getConnection(dbUrl,
userName,
password);
} catch (SQLException e) {
System.out.println(e.toString());
}
return connection;
}
}

Primeiro e acima de tudo, a classe entity bean tem quatro campos


para armazenar os dados: codProduto, nomeProduto, descricao e
preco. Alm disso, ela tem as implementaes de quatro mtodos de
negcio declarados na interface remota: getCodProduto,
getNomeProduto, getDescricao, getPreco.
Um mtodo importante, que ser usado por vrios outros mtodos
na classe entity bean, o getConnection, que retorna um objeto
java.sql.Connection.
Como de hbito para conectar com um banco de dados, voc precisa
passar o URL de banco de dados, o nome do usurio, senha. D para
deixar estes dados na classe entity mas no muito interessante.
melhor deixar este tipo de configurao fora do cdigo. Uma boa
forma de fazer isto utilizar JNDI para recuperar os dados. Os
dados do banco estaro armazenado no deployment descriptor.
No mtodo getConnection, no entity bean, primeiro definimos as
referncias aos objetos String e duas a objetos
javax.naming.Context, chamadas initialContext e environment:
24/04/04 01:48:21
jp@psique.org http://www.psique.org/cursos

188

Entity Bean - BMP

Curso J150

String dbUrl = null;


String userName =null;
String password = null;
Context initialContext;
Context environment;

A varivel initialContext usada para referenciar o objeto


InitialContext, obtido a partir do seguinte construtor:
initialContext = new InitialContext();

Depois voc pode buscar o ambiente do bean, passando a string


java:comp/env (buscando o nome pelo ENC Enterprise Naming
Context) para o mtodo lookup do contexto inicial, como a seguir:
environment =
(Context) initialContext.lookup(java:comp/env/jdbc);

Depois, voc pode usar o objeto environment para buscar pelos


dados:
dbUrl = (String) environment.lookup(dbUrl);
userName = (String) environment.lookup(dbUserName);
password = (String) environment.lookup(dbPassword);

Daqui para frente s utilizar o getConnection normalmente:


connection = DriverManger.getConnection(dbUrl, userName,
password);

Em cada mtodo create, o entity bean implementa um mtodo


ejbCreate e um mtodo ejbPostCreate.
O mtodo ejbCreate aceita o mesmo conjunto de argumentos,
24/04/04 01:48:23
jp@psique.org http://www.psique.org/cursos

189

Entity Bean - BMP

Curso J150

conforme definido no mtodo create, na interface home, e retorna o


objeto primary key do bean. Veja a diferena de nomenclatura,
ejbCreate na classe e create na interface home. A assinatura :

public ProdutoPK
ejbCreate(
int codProduto,
String nomeProduto,
String descricao ,
double preco)
throws RemoteException, CreateException {

O mtodo ejbCreate faz duas coisas. Primeiro preenche os campos


internos com os valores dos argumentos passados:
this.codProduto = codProduto;
this.nomeProduto = nomeProduto;
this.descricao = descricao;
this.preco = preco;

Em seguida o mtodo insere um registro no banco de dados. O


cdigo para inserir um novo registro:
Connection com = null;
PreparedStatement ps = null;
try {
String sql = INSERT INTO PRODUTO +
( codproduto, nomeProduto, descricao, preco ) +
VALUES ( ? , ? , ? , ? );
con = getConnection();
ps = com.prepareStatement(sql);
ps.setInt(1, codProduto);
ps.setString(2, nomeProduto);
ps.setString(3, descricao);
ps.setDouble(4, preco);
catch (SQLException e) {
System.out.println(e.toString());
} finally {
try {

24/04/04 01:48:25
jp@psique.org http://www.psique.org/cursos

190

Entity Bean - BMP

Curso J150

if(ps!=null)
ps.close();
if(con!=null)
con.close();
} catch(SQLException e) {}
}

Finalmente, o mtodo retorna um novo objeto ProdutoPK, como a


seguir:
return new ProdutoPK(Integer.toString(codProduto));

O mtodo ejbPostCreate no retorna um valor e no faz nada,


exceto imprimir o seu nome no console, lembre-se que necessrio
um ejbPostCreate para cada ejbCreate, o ejbPostCreate retorna
void, j o ejbCreate retorna chave primria.
public void
ejbPostCreate(
int codProduto,
String nomeProduto,
String descricao,
double preco)
throws RemoteException, createException {
System.out.println(ejbPostCreate Produto);
}

Esta classe entity bean tem dois mtodos finder: findByPrimaryKey


e findByNome. O mtodo findByPrimaryKey aceita um objeto
primary key e verifica se o banco de dados contm um registro
tendo aquela chave primria. Se existir, retornar a mesma chave,
caso contrrio, o mtodo findByPrimaryKey ir lanar a exceo
javax.ejb.ObjectNotFoundException.
O mtodo ejbFindByPrimaryKey comea compondo a declarao
SQL usada para selecionar um registro tem o identificador de
produto especificado:
24/04/04 01:48:26
jp@psique.org http://www.psique.org/cursos

191

Entity Bean - BMP

Curso J150

String sql =
SELECT codProduto FROM PRODUTO WHERE codProduto=?;

O identificador de produto obtido a partir do objeto primary key:


int codProduto = Integer.parseInt(primaryKey.codProduto);

Depois o mtodo ejbFindByPrimaryKey obtm um objeto


Connection, criar um objeto PreparedStatement e chama o mtodo
executeQuery do objeto PreparedStatement:
con = getConnection();
ps = con.prepareStatement(sql);
ps.setInt(1,codProduto);
rs = ps.executeQuery();

O mtodo executeQuery retorna um objeto ResultSet. O mtodo


next() do objeto ResultSet retorna verdadeiro se houver um prximo
registro; caso contrrio, ele retorna falso. Se o mtodo next()
retornar verdadeiro, o mtodo ejbFindByPrimaryKey retornar o
objeto primary key:
if(rs.next()) {
rs.close();
ps.close();
con.close();
return primaryKey;
}

Caso contrrio, o mtodo lanar a exceo:


throw new ObjectNotFoundException();

O outro mtodo finder chamado ejbFindbyNome e retorna um


objeto Enumeration, contendo todas as chaves primrias dos
produtos selecionados.
O entity bean tambm oferece uma implementao do mtodo
24/04/04 01:48:28
jp@psique.org http://www.psique.org/cursos

192

Entity Bean - BMP

Curso J150

ejbRemove. Quando o mtodo ejbRemove chamado, ele apaga o


registro correspondente no banco de dados:
PreparedStatement ps = null;
try {
String sql = DELETE FROM PRODUTO WHERE codProduto = ?;
ProdutoPK chave = (ProdutoPK) context.getPrimaryKey();
int codProduto = Integer.parseInt(chave.codProduto);
con = getConnection();
ps = con.prepareStatement(sql);
ps.setInt(1, codProduto);
ps.executeUpdate();
} catch (SQLException e) {
System.out.println(e.toString());
}

Para a sincronizao entre os dados do banco de dados e o entity


bean, precisamos implementar os mtodos ejbStore e ejbLoad.
O mtodo ejbLoad copia os dados do banco para os campos do entity
bean.
O mtodo ejbStore faz o contrrio, ou seja, copia os dados do entity
bean para o banco de dados.

Descritor de distribuio
Cada aplicativo EJB precisa ser acompanhado de um deployment
descriptor que deve ser salvo no diretrio META-INF do projeto, em
um arquivo chamado ejb-jar.xml.

<?xml version="1.0" encoding="ISO-8859-1"?>


<!DOCTYPE ejb-jar PUBLIC
"-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN"
"http://java.sun.com/dtd/ejb-jar_2_0.dtd">
<ejb-jar>
24/04/04 01:48:29
jp@psique.org http://www.psique.org/cursos

193

Entity Bean - BMP

Curso J150

<description>Aplicacao EJB - CMP </description>


<display-name>Aplicacao Produto</display-name>
<enterprise-beans>
<entity>
<ejb-name>ProdutoBMP</ejb-name>
<home>org.psique.produto.ejb.ProdutoHome</home>
<remote>org.psique.produto.ejb.Produto</remote>
<ejb-class>org.psique.produto.ejb.ProdutoBean
</ejb-class>
<persistence-type>Bean</persistence-type>
<prim-key-class>org.psique.produto.ejb.ProdutoPK
</prim-key-class>
<reentrant>true</reentrant>
<env-entry>
<env-entry-name>jdbc/dbUrl</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>
jdbc:hsqldb:hsql://localhost:1701
</env-entry-value>
</env-entry>
<env-entry>
<env-entry-name>jdbc/dbUserName</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>sa</env-entry-value>
</env-entry>
<env-entry>
<env-entry-name>jdbc/dbPassword</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value></env-entry-value>
</env-entry>
</entity>
</enterprise-beans>

No deployment descriptor precisamos especificar os nomes


totalmente qualificados para a interface remote, a interface home e
o entity bean. Alm disso em qualquer entity bean, tambm

24/04/04 01:48:31
jp@psique.org http://www.psique.org/cursos

194

Entity Bean - BMP

Curso J150

preciso dizer ao continer EJB qual tipo de persistncia o seu entity


est usando. Nesse caso, o elemento <persistence-type> tem o
valor bean, pois trata-se de um BMP.
H tambm trs elementos <env-entry>, cada um especificando
uma varivel de ambiente. os trs valores so os utilizados pelo
mtodo getConnection, na classe entity bean, para conectar com o
banco de dados.
Para empacotar o entity, basta criar um JAR com as classes e o
deployment descriptor. Utilizando o comando jar, no diretrio de
seu projeto o comando seria:
jar cvf produto.jar org/psique/ejb/Produto*.* META-INF/ejb-jar.xml

Para instalar s copiar o arquivo produto.jar criado no diretrio de


deploy do JBoss.

Aplicativo Cliente
Tendo um entity bean instalado no servidor, voc pode escrever um
aplicativo cliente para testar o bean:
BeanClienteBMP.java

package org.psique.produto.cliente;
import java.util.Collection;
import java.util.Iterator;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import org.psique.produto.ejb.Produto;
import org.psique.produto.ejb.ProdutoHome;

24/04/04 01:48:33
jp@psique.org http://www.psique.org/cursos

195

Entity Bean - BMP

Curso J150

public class BeanClienteBMP {


public static void main(String[] args) {
// preparando propriedades para contruir
// o objeto InitialContext
Properties properties = new Properties();
properties.put(
Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
properties.put(Context.PROVIDER_URL,
"localhost:1099");
try {
// Pega um contexto inicial
InitialContext jndiContext =
new InitialContext(properties);
System.out.println("Tenho um contexto");
// Pega a referencia para o Bean
Object ref = jndiContext.lookup("ProdutoBMP");
System.out.println("Tenho a referencia");
// Pega a referencia para a interface
// Home do Bean
ProdutoHome home =
(ProdutoHome) PortableRemoteObject.narrow(
ref,
ProdutoHome.class);
// Cria alguns objetos
System.out.println(
"Criando Inserindo gua mineral");
home.create(getChave(),
"gua mineral",
"400ml",
2.25);
System.out.println(
"Criando Inserindo gua mineral");
home.create(getChave(), "gua mineral",
"600ml",
3.25);
24/04/04 01:48:35
jp@psique.org http://www.psique.org/cursos

196

Entity Bean - BMP

Curso J150

System.out.println(
"Criando Barra de Chocolate");
home.create(
getChave(),
"Barra de Chocolate",
"Chocolate Bar 200g",
2.95);
System.out.println("Criando Biscoito");
home.create(
getChave(),
"Biscoito",
"Biscoito com menta, 300g",
9.25);
System.out.println("Criando Coca-cola");
Produto codProduto =
home.create(getChave(),
"Coca-cola",
"Coca-cola 600ml",
1.05);
codProduto.remove();
System.out.println(
"Agua mineral... procurando ");
Collection colecao =
(Collection) home.findByNome(
"gua mineral");
Iterator iterator = colecao.iterator();
while (iterator.hasNext()) {
codProduto = (Produto) iterator.next();
System.out.println("Cdigo: " +
codProduto.getCodProduto());
System.out.println(
"Nome do Produto: " +
codProduto.getNomeProduto());
System.out.println("Descrio: " +
codProduto.getDescricao());
System.out.println("Preco: " +
codProduto.getPreco());

24/04/04 01:48:37
jp@psique.org http://www.psique.org/cursos

197

Entity Bean - BMP

Curso J150

}
} catch (Exception e) {
System.out.println(e.toString());
}
}
public static int getChave() {
return (int) (Math.random() * Integer.MAX_VALUE);
}
}

Este aplicativo cliente muito semelhante ao anteriormente


utilizado para acessar os session beans. O aplicativo cliente insere
alguns registros, chamando o mtodo create do objeto home.
Remove o ltimo Ento, ele pode chamar o mtodo findByNome e
mostrar os detalhes dos produtos.

24/04/04 01:48:39
jp@psique.org http://www.psique.org/cursos

198

Entity Bean CMP

Curso J150

Entity Bean CMP


Embora um entity BMP seja timo para representar os dados, um
entity CMP ainda mais fcil de escrever. Nos entitys BMP, voc
o responsvel por escrever os mtodos create e finder, ejbStore e
ejbLoad, ou seja o acesso aos dados deve ser implementado por
voc.
Um entity CMP deixa essas responsabilidades ao continer. Voc
no precisa escrever mtodo getConnection, no precisa conectar
com o banco,. no precisa implementar ejbStore ne ejbLoad. Na
realidade possvel fazer tudo sem utilizar nada de SQL.
Nem mesmo o finder necessrio. Quase tudo feito pelo
continer. Ento, um entity CMP muito mais simples de escrever.
Entretanto existem desvantagens. Voc precisa fazer mais
configuraes no deployment descriptor, e estas configuraes so
especficas do continer que est sendo utilizado.
Utilizando CMP o continer utilizar um banco de dados padro
para o armazenamento. possvel alterar este padro pelos
arquivos de configurao.
No JBoss, se nada for especificado, o continer ir criar uma tabela
para voc, no banco de dados hsqldb. Mas voc pode utilizar outro
banco se quiser.
JBoss oferece os trs mtodos finder a seguir:

findByPrimaryKey

findAll

findBy<campo>(<tipo-campo> valor)

24/04/04 01:48:40
jp@psique.org http://www.psique.org/cursos

199

Entity Bean CMP

Curso J150

Alm disso possvel definir mtodos finder personalizados.

Entity Beans CMP so subclasses


Voc escreve uma classe abstrata, a partir desta classe, o continer
gera o entity verdadeiro que tem a lgica para acessar os dados. A
inteno foi deixar o BEAN distante da implementao do acesso
aos dados.

Entity Beans CMP no tem campos


declarados
No existem campos declarados no Entity CMP. O continer cuida
do armazenamento.

Entity Beans CMP tem mtodos Get/Set


Abstratos
Os mtodos get e set no so implementados, ficam abstratos. Por
isto so chamados de campos virtuais. A implementao feita
pelo continer quando ele cria o BEAN verdadeiro que uma
especificao do BEAN abstrato codificado por voc.

Entity Beans tm um Schema abstrato de


persistncia
O continer gera todo o cdigo JDBC, campos persistentes,
implementao dos get/set. Isto tudo gerado de acordo com o que
est previsto no deployment descriptor. As definies do
deployment descriptor sobre como as coisas devem ser persitidas
chamado de esquema abstrato de persitncia (abstract persistence
schema).

24/04/04 01:48:42
jp@psique.org http://www.psique.org/cursos

200

Entity Bean CMP

Curso J150

Ex.:
ejb-jar.xml

...
<cmp-version>2.x</cmp-version>
<abstract-schema-name>ContaBean</abstract-schema-name>
<cmp-field>
<field-name>codConta</field-name>
</cmp-field>
<cmp-field>
<field-name>nome</field-name>
</cmp-field>
<cmp-field>
<field-name>saldo</field-name>
</cmp-field>
<primkey-field>codConta</primkey-field>
...

A tag cmp-version precisa ser 2.x para voc utilizar EJB 2.0 CMP.
As especificaes EJB 1.1 e 1.0 tem vrias lacunas em relao
2.x.

A tag abstract-schema-name o apelido que voc deseja dar ao


esquema abstrato de persistncia. Pode ter o valor que quiser.
recomendado dar o nome dele aps o de seu bean. Mais tarde
este nome vai ser referenciado quando fizermos as queries.

Os elementos cmp-field so os seus campos persistentes


gerenciados pelo continer. Cada campo persistente deve ter um
getter e um setter abstrato no bean. Exemplo: o campo saldo deve
ter um mtodo abstract double getSaldo() e um abstract
void setSaldo(double saldo) no bean.

Entity Beans podem tem uma linguagem


para queries
Para possibilitar a criao de mtodos com critrios diferentes de
busca do que os findAll, findByPrimaryKey e findBy<campo>, foi
criar uma linguagem parecida com SQL, chamada EJB Query
Language (EJB-QL). EJB-QL um tipo de SQL orientado a objetos.
Contm clusulas SELECT, FROM e WHERE. O EJB-QL codificado
no deployment descriptor. O continer ir gerar a lgica para
acesso ao banco de dados.

24/04/04 01:48:44
jp@psique.org http://www.psique.org/cursos

201

Entity Bean CMP

Curso J150

Entity Beans podem ter mtodos ejbSelect()


Outra grande diferena entre BMP e CMP que nos Entities CMP
voc pode especificar mtodos ejbSelect(). Um mtodo ejbSelect()
um mtodo para queries (como um finder), com a diferena de no
ser exposto ao cliente na interface home ou remote. Os ejbSelect()
so utilizados internamente no bean como um mtodo helper para
acesso aos dados. ejbSelect() til quando seus entitys tem
relacionamentos com dados externos.
exemplo:
No bean:

...
public abstract double ejbSelectAllSaldos() throws FinderException;
public double ejbHomeGetGetSaldoTotalDoBanco() throws Exception {
Collection c = this.ejbSelectAllSaldos();
Iterator i = c.iterator();
double soma = 0;
while(i.hasNext()) {
Conta c = (Conta)(i.next());
soma += c.getSaldo();
}
return soma;
}
...

Os mtodos ejbSelect() no so expostos aos cliente nas interfaces


remotas ou locais. Eles precisam ser chamados de dentro de seu
bean, de um mtodo de negcios ou de um mtodo home de
negcios. Eles so codificados no ejb-jar.xml.
O exemplo a seguir apresenta um entity bean CMP que muito
semelhante ao entity bean Produto BMP. o objetivo comparar os
dois tipos de entity. Todos os arquivos de classe so prefixados com
CMP, e o tipo de classe primary key java.lang.String.

24/04/04 01:48:45
jp@psique.org http://www.psique.org/cursos

202

Entity Bean CMP

Curso J150

Diferenas entre CMP e BMP


Diferena

CMP

BMP

Definio da classe Abstrata

Concreta

Acesso a banco de
dados

Geradas por
ferramentas

Codificada por
desenvolvedor

Estado de
persistncia

Representado por
campos persistentes
virtuais.

Codificado como
variveis de instncias

Acesso a todos
Obrigatrio
para persistncia e
campos de
relacionamento

Nenhum

Mtodo
findByPrimaryKey

Controlado pelo
continer

Codificado pelo
desenvolvedor

Mtodos finders
customizados

Controlado pelo
continer mas o
desenvolvedor pode
definir queries em
EJB QL

Codificado pelo
desenvolvedor

Mtodos select

Controlado pelo
continer

nenhum

Retorno do
ejbCreate

Pode ser null

Precisa ser a chave


primria

A interface remote
A interface remote do bean ProdutoCMP semelhante
ProdutoBMP:
ProdutoCMP.java

24/04/04 01:48:47
jp@psique.org http://www.psique.org/cursos

203

Entity Bean CMP

Curso J150

package org.psique.produto.ejb;
/**
* Interface Remota para ProdutoCMP.
*/
public interface ProdutoCMP
extends javax.ejb.EJBObject
{
public String getCodProduto() throws
java.rmi.RemoteException;
public void setCodProduto(String cod) throws
java.rmi.RemoteException;
public String getNomeProduto() throws
java.rmi.RemoteException;
public void setNomeProduto(String nome) throws
java.rmi.RemoteException;
public String getDescricao() throws
java.rmi.RemoteException;
public void setDescricao(String descricao) throws
java.rmi.RemoteException;
public double getPreco() throws
java.rmi.RemoteException;
public void setPreco(double preco) throws
java.rmi.RemoteException;

A interface home
A interface home define um mtodo create e dois finders.
ProdutoCMP.java

package org.psique.produto.ejb;
import java.util.Collection;
import org.psique.produto.ejb.ProdutoCMP;

24/04/04 01:48:49
jp@psique.org http://www.psique.org/cursos

204

Entity Bean CMP

Curso J150

/**
* Interface Home para ProdutoCMP.
*/
public interface ProdutoCMPHome
extends javax.ejb.EJBHome
{
// Nome ENC
public static final String
COMP_NAME="java:comp/env/ejb/ProdutoCMP";
// Nome Global
public static final String JNDI_NAME="ProdutoCMP";
public org.psique.produto.ejb.ProdutoCMP
create(int codProduto ,
java.lang.String nomeProduto ,
java.lang.String descricao ,
double preco)
throws javax.ejb.CreateException,
java.rmi.RemoteException;
public ProdutoCMP findByPrimaryKey(java.lang.String pk)
throws
javax.ejb.FinderException,
java.rmi.RemoteException;
public Collection findByNomeProduto(java.lang.String nome)
throws
javax.ejb.FinderException,
java.rmi.RemoteException;
}

A classe entity bean


Comparada classe entity bean de BMP, a classe de CMP muito
mais simples e mais curta. Note que uma classe abstrata e que
tem vrias lacunas que so preenchidas pelo continer.

24/04/04 01:48:50
jp@psique.org http://www.psique.org/cursos

205

Entity Bean CMP

Curso J150

ProdutoCMPBean.java

package org.psique.produto.ejb;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;
public abstract class ProdutoCMPBean implements EntityBean {
EntityContext contexto;
public
public
public
public

String
String
String
double

codProduto;
nomeProduto;
descricao;
preco;

/**
*
* EM CMP,
* os mtodos acessores so ABSTRATOS
*
*/
public abstract String getCodProduto();
public abstract void setCodProduto(String cod);
public abstract String getNomeProduto();
public abstract void setNomeProduto(String nome);
public abstract String getDescricao();
public abstract void setDescricao(String descricao);
public abstract double getPreco();
public abstract void setPreco(double preco);
/**
* O create s se preocupa em abastecer as variveis
* de instncia utilizando-se dos getters e setters
* no necessria a criao no banco. O continer
* cuidar disto para ns.

24/04/04 01:48:52
jp@psique.org http://www.psique.org/cursos

206

Entity Bean CMP

Curso J150

*
* @param codProduto
* @param nomeProduto
* @param descricao
* @param preco
* @return
* @throws RemoteException
* @throws CreateException
*
*/
public String ejbCreate(
int codProduto,
String nomeProduto,
String descricao,
double preco)
throws RemoteException, CreateException {
System.out.println("ejbCreate");
setCodProduto(Integer.toString(codProduto));
setNomeProduto(nomeProduto);
setDescricao(descricao);
setPreco(preco);
return null;
}
/**
* Deve existir um ejbPostCreate para cada ejbCreate
* (com a mesma assinatura)
*
*
*
*/
public void ejbPostCreate(
int codProduto,
String nomeProduto,
String descricao,
double preco)
throws RemoteException, CreateException {
System.out.println("ejbPostCreate");
}
/**
* @throws RemoteException
*
*
24/04/04 01:48:54
jp@psique.org http://www.psique.org/cursos

207

Entity Bean CMP

Curso J150

*/
public void ejbRemove() throws RemoteException {
System.out.println("ejbRemove");
}
public
public
public
public

void
void
void
void

ejbActivate() {}
ejbPassivate() {}
ejbLoad() {}
ejbStore() {}

public void setEntityContext(EntityContext contexto) {


System.out.println("setEntityContext");
this.contexto = contexto;
}
public void unsetEntityContext() {
System.out.println("unsetEntityContext");
contexto = null;
}
}

A classe entity bean tem os oito mtodos de negcio:


getCodigoProduto, getNomeProduto, getDescricao, getPreco,
setCodigoProduto, setNomeProduto, setDescricao, setPreco. O
nico mtodo com contedo substancial o mtodo ejbCreate. Esse
mtodo preenche os campos de classe com os argumentos passados
ao mtodo ejbCreate. No entanto, no h cdigo para conectar com
o banco de dados, como no mtodo ejbCreate no entity bean BMP.

public String ejbCreate(int codProduto, String nomeProduto,


String descricao, double preco)
throws RemoteException, CreateException {
System.out.println("ejbCreate");
this.codProduto = Integer.toString( codProduto);
this.nomeProduto = nomeProduto;
this.descricao = descricao;
this.preco = preco;
return Integer.toString(codProduto);

24/04/04 01:48:56
jp@psique.org http://www.psique.org/cursos

208

Entity Bean CMP

Curso J150

O deployment descriptor

<?xml version="1.0" encoding="ISO-8859-1"?>


<!DOCTYPE ejb-jar PUBLIC
"-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN"
"http://java.sun.com/j2ee/dtd/ejb-jar_2_0.dtd">
<ejb-jar>
<enterprise-beans>
<entity>
<display-name>Produto CMP</display-name>
<ejb-name>ProdutoCMP</ejb-name>
<home>org.psique.produto.ejb.ProdutoCMPHome</home>
<remote>org.psique.produto.ejb.ProdutoCMP</remote>
<ejb-class>org.psique.produto.ejb.ProdutoCMPBean
</ejb-class>
<persistence-type>Container</persistence-type>
<prim-key-class>java.lang.String</prim-key-class>
<reentrant>False</reentrant>
<cmp-version>2.x</cmp-version>
<abstract-schema-name>PRODUTOSCHEMA
</abstract-schema-name>
<cmp-field>
<field-name>codProduto</field-name>
</cmp-field>
<cmp-field>
<field-name>nomeProduto</field-name>
</cmp-field>
<cmp-field>
<field-name>descricao</field-name>
</cmp-field>
<cmp-field>
<field-name>preco</field-name>
</cmp-field>
<primkey-field>codProduto</primkey-field>
<query>
<query-method>
<method-name>findByNomeProduto
24/04/04 01:48:57
jp@psique.org http://www.psique.org/cursos

209

Entity Bean CMP

Curso J150

</method-name>
<method-params>
<method-param>
java.lang.String
</method-param>
</method-params>
</query-method>
<ejb-ql><![CDATA[
SELECT OBJECT(PROD) FROM PRODUTOSCHEMA AS PROD
WHERE PROD.nomeProduto = ?1
]]></ejb-ql>
</query>
</entity>
</enterprise-beans>
</ejb-jar>

O deployment descriptor muito semelhante ao de BMP. Entretanto


esse descritor tem elementos <cmp-field> para todos os campos
que precisam ser persistidos. Neste exemplo, tais campos so
codProduto, nomeProduto, descricao e preco. O elemento <primkeyfield> tambm especifica o campo da chave primria. A Tag
<abstract-schema-name> serve para definir o nome do schema utilizado.
Outra coisa que chama a ateno a existncia de query escrita em
ejb-ql nos mtodos finders.
Verifique que o contedo de <persistence-type> Continer e no
Bean como no CMP.
O CMP empacotado da mesma forma que o BMP.
Existem algumas informaes teis ao continer que no so
passadas no ejb-jar.xml, no caso do JBoss estas informaes so
passadas no arquivo jbosscmp-jdbc.xml, que fica localizado no
mesmo diretrio que o ejb-jar.xml (META-INF).
jbosscmp-jdbc.xml

<?xml version="1.0" encoding="ISO-8859-1"?>

24/04/04 01:48:59
jp@psique.org http://www.psique.org/cursos

210

Entity Bean CMP

Curso J150

<!DOCTYPE jbosscmp-jdbc PUBLIC


"-//JBoss//DTD JBOSSCMP-JDBC 3.0//EN"
"http://www.jboss.org/j2ee/dtd/jbosscmp-jdbc_3_0.dtd">
<jbosscmp-jdbc>
<enterprise-beans>
<entity>
<ejb-name>ProdutoCMP</ejb-name>
<create-table>true</create-table>
<remove-table>true</remove-table>
<table-name>ProdutoCMP2</table-name>
<!-- CMP Fields (see Chapter 3) -->
<cmp-field>
<field-name>codProduto</field-name>
<column-name>codProduto</column-name>
</cmp-field>
<cmp-field>
<field-name>nomeProduto</field-name>
<column-name>nomeProduto</column-name>
</cmp-field>
<cmp-field>
<field-name>descricao</field-name>
<column-name>descricao</column-name>
<jdbc-type>VARCHAR</jdbc-type>
<sql-type>VARCHAR (50)</sql-type>
</cmp-field>
<cmp-field>
<field-name>preco</field-name>
<column-name>valor</column-name>
</cmp-field>
</entity>
</enterprise-beans>
</jbosscmp-jdbc>

Exemplo de aplicativo cliente


O aplicativo cliente para o CMP muito parecido ao que utilizava
BMP:
BeanClienteCMP.java

package org.psique.produto.cliente;
import java.util.Collection;
import java.util.Iterator;
24/04/04 01:49:01
jp@psique.org http://www.psique.org/cursos

211

Entity Bean CMP

Curso J150

import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import org.psique.produto.ejb.ProdutoCMP;
import org.psique.produto.ejb.ProdutoCMPHome;

public class BeanCliente {

public static void main(String[] args) {


// preparando propriedades para contruir
// o objeto InitialContext
Properties properties = new Properties();
properties.put(
Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
properties.put(Context.PROVIDER_URL, "localhost:1099");
try {
// Pega um contexto inicial
// baseado nas propriedades informadas acima
InitialContext jndiContext =
new InitialContext(properties);
System.out.println("Tenho um contexto");
// Pega a referencia para o Bean
Object ref = jndiContext.lookup("ProdutoCMP");
System.out.println("Tenho a referencia");
ProdutoCMP produto = null;
// Pega a referencia para a interface Home do Bean
ProdutoCMPHome home =
(ProdutoCMPHome) PortableRemoteObject.narrow(
ref,
ProdutoCMPHome.class);
// Cria alguns objetos
System.out.println("Criando Inserindo gua mineral");
home.create(chaveAleatoria(),
"gua mineral",
"400ml",
2.25);
System.out.println("Criando Inserindo gua mineral");
home.create(chaveAleatoria(),
"gua mineral",
24/04/04 01:49:03
jp@psique.org http://www.psique.org/cursos

212

Entity Bean CMP

Curso J150

"600ml",
3.25);
System.out.println("Criando Barra de Chocolate");
home.create(chaveAleatoria(),
"Barra de Chocolate",
"Chocolate Bar 200g",
2.95);
System.out.println("Criando coca-cola");
produto =
home.create(25,
"Coca-cola",
"Coca-cola 600ml",
1.05);
System.out.println("Removendo coca-cola");
produto.remove();

System.out.println("\n\nAgua mineral... procurando " );


Collection colecao =
(Collection) home.findByNomeProduto("gua mineral");
Iterator iterator = colecao.iterator();
while (iterator.hasNext()) {
produto = (ProdutoCMP) iterator.next();
System.out.println("Cdigo:
" +
produto.getCodProduto());
System.out.println("Nome do Produto: " +
produto.getNomeProduto());
System.out.println("Descrio:
" +
produto.getDescricao());
System.out.println("Preco:
" +
produto.getPreco());
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
public static int chaveAleatoria() {
return (int)(Math.random()*Integer.MAX_VALUE);
}
}

24/04/04 01:49:04
jp@psique.org http://www.psique.org/cursos

213

Entity Bean CMP

Curso J150

Utilizando uma classe para a chave primria


customizada
Quando utilizarmos uma chave primria customizada, temos que ter
este elemento no nosso deployment descriptor:
<prim-key-class>org.psique.BancoPK</prim-key-class>

Isto no estritamente necessrio. Voc pode escolher no criar


uma chave primria customizada, neste caso, basta informar um dos
campos persistentes do bean.
<prim-key-class>conta</prim-key-class>

24/04/04 01:49:06
jp@psique.org http://www.psique.org/cursos

214

A linguagem de consulta EJB


EJB-QL

Curso J150

A linguagem de consulta
EJB EJB-QL
Existem dois tipos de entity beans, CMP e BMP. CMP pode ser mais
simples que BMP, mas BMP oferece maior flexibilidade.
Embora a persistncia automtica pelo continer seja um bom
recurso de entitys CMP, os entitys BMP as vezes so preferidos em
funo da flexibilidade pois permitiriam a criao de finders
complexos.
Esta flexibilidade no est presente no entity CMP porque voc no
implementa os finders, voc fica dependente dos finders do
continer EJB. Que para o JBoss so: findByPrimaryKey, findAll, e
findBy<campo>.
Para contornar essa limitao de entity beans CMP, EJB 2.0
especifica uma linguagem chamada: Enterprise JavaBeans Query
Language (SQL), que os desenvolvedores de um bean podem usar
para selecionar dados para mtodos finder de entitys CMP. Para
otimizao de desempenho, a EJB QL pode ser compilada para uma
linguagem alvo do banco de dados ou outra armazenagem
persistente, exatamente como voc cria um procedimento
armazenado que encapsula a sua declarao SQL para agilizar a
execuo de sua declarao SQL.
As consultas EJB QL podem ser usadas de duas formas:

Para selecionar objetos entidades, conforme definidos nos


mtodos finder na interface home.

Para selecionar objetos entity ou outros valores derivados de um

24/04/04 01:49:08
jp@psique.org http://www.psique.org/cursos

215

A linguagem de consulta EJB


EJB-QL

Curso J150

tipo de esquema abstrato de entity bean.


As declaraes EJB SQL para seus mtodos finder ou select so
especificadas no descritor de distribuio, sob o elemento <query>.
Por exemplo, o seguinte descritor de distribuio especifica um
mtodo finder chamado findByDescricao, que aceita um parmetro
do tipo java.lang.String:
<?xml version=1.0?>
<!DOCTYPE ejb-jar PUBLIC -//Sun Microsystems, Inc.//DTD
Enterprise JavaBeans 2.0//EN
http://java.sun.com/dtd/ejb-jar_2_0.dtd>
<ejb-jar>
<enterprise-bean>
<entity>
.
.
.
<query>
<query-method>
<method-name>findByDescricao</mentod-name>
<method-param>java.lang.String</method-param>
</query-method>
<ejb-ql>
<![[
CDATA[SELECT OBJECT(produto) FROM
ProdutoCMP AS produto
WHERE descricao =?1]]>
</ejb-ql>
</query>
</enterprise-bean>
</ejb-jar>

O nome do mtodo find especificado no elemento <method-name>


e os parmetros so especificados nos elementos <methodsparam>. A prpria declarao EJB-QL dada no elemento <ejbql>.
EJB-QL muito parecido com SQL mas existem algumas diferenas
bem significativas. So elas:
24/04/04 01:49:10
jp@psique.org http://www.psique.org/cursos

216

A linguagem de consulta EJB


EJB-QL

Curso J150

EJB-QL uma linguagem tipada, significa que as comparaes


devem ter os mesmo tipos.

Em uma comparao de igualdade a varivel (single valued path)


precisa estar no lado esquerdo.

Os parmetros usam a base 1, igual em


java.sql.PreparedStatement, ou seja, o primeiro parmetro o de
nmero 1 (e no o 0).

Parmetros so admitidos somente do lado direito das


comparaes.

No arquivo ejb-jar.xml, a query deve existir e ser grafada em


EJB_QL, mas possvel fazer um override e codific-la no arquivo
jbosscmp-jdbc.xml, l possvel utilizar JBossQL, DynamicQL,
DeclaredSQL ou um campo BMP como no mtodo ejbFind. Utilizar
estas extenes no padro limitam a portabilidade de sua
aplicao.

A sintaxe EJB -QL


Entender a sintaxe de EJB QL a chave para criar um mtodo finder
eficiente. Uma consulta EJB QL precisa tomar a seguinte forma:
select_clause from_clause [where_clause]

Nessa consulta, a where_clause opcional. Cada clusula


explicada nas subsees a seguir:

A clusula SELECT
A clusula SELECT especifica a sada da consulta EJB QL. Ela pode
conter um dos seguintes:

Uma nica faixa de varivel, variando pelo tipo de esquema

24/04/04 01:49:12
jp@psique.org http://www.psique.org/cursos

217

A linguagem de consulta EJB


EJB-QL

Curso J150

abstrato de um entity bean.

Uma nica expresso vlida de caminho

Em um mtodo finder, a clusula SELECT contm ou uma nica


faixa de varivel, variando pelo tipo de esquema abstrato do entity
bean para a qual o mtodo finder definido, ou um cmr-field
indicado por uma nica expresso vlida de caminho, que avalia o
tipo de esquema abstrato do entity bean para o qual o entity
definido.
CMR quer dizer: Container Managed Relationships, ou
relacionamentos gerenciados pelo continer. So uma caracterstica
bastante poderosa de CMP 2.0. O continer gerencia
relacionamentos um para um, um para muitos e muito para muitos
com integridade referencial. Uma restrio dos CMRs que eles
tem que apenas serem definidos entre interfaces locais, quer dizer
que o relacionamento no pode ser criado entre entities em
mquinas virtuais diferentes.
Por outro lado, a clusula SELECT da consulta para um mtodo
select pode retornar os tipos de esquemas abstratos de outros entity
beans, ou valores de cmp-fields:
Formato:
SELECT [DISTINCT] {single_valued_path_expression |
<OBJECT(identification_variable)}

Quando a palavra-chave DISTINCT est presente em uma clusula


SELECT, valores duplicados so eliminados do resultado da
consulta EJB-QL.
Quando a palavra-chave DISTINCT no est presente em um
SELECT, mas a consulta especificada para um mtodo cujo tipo de
resultado java.util.Set, todos os valores duplicados tambm so
eliminados do resultado da consulta.
Como um exemplo, aqui est uma simples declarao EJB QL que

24/04/04 01:49:14
jp@psique.org http://www.psique.org/cursos

218

A linguagem de consulta EJB


EJB-QL

Curso J150

encontrar os produtos distintos:


SELECT DISTINCT OBJECT(p)
FROM Produto AS p

A clusula FROM
A clusula FROM define o domnio da consulta, declarando variveis
de identificao. O domnio da consulta pode ser restrito pelas
expresses de caminho. A clusula FROM pode conter mltiplas
variveis de identificao, separadas por uma vrgula. Ela tem a
seguinte sintaxe:
FROM identification_variable_declaration
[,identification_variable_declaration] *

Nessa clusula, o asterisco denota que o valor entre chaves que ele
segue pode ser repetido zero ou mais vezes. Alm do mais, a
identification_variable_declaration definida como a seguir:

identification_varible_declaration::=
collection_member_declaration | range_variable_declaration
collection_member_declaration::= IN
(collection_valued_path_expression) [AS] identifier
range_variable_declaration::= abstract_schema_name [AS]
identifier

Um identifier uma seqncia de caracteres com estilo de letra, de


qualquer comprimento. Alm disso, um identificador no precisa ser
um dos seguintes: SELECT, FROM, WHERE, DISTINCT, OBJECT,
NULL, TRUE, FALSE, NOT, AND, OR, BETWEEN, LIKE, IN, AS,
UNKNOWN, EMPTY, MEMBER, OF e IS.
Uma varivel de identificao age como um identificador na
clusula FROM. Ela declarada usando os operadores especiais INe, opcionalmente, AS. Uma varivel de identificao tambm tem
estilo de letra e no pode ser um identificador reservado. Ela
24/04/04 01:49:15
jp@psique.org http://www.psique.org/cursos

219

A linguagem de consulta EJB


EJB-QL

Curso J150

tambm no pode ter o mesmo nome que um nome de esquema


abstrato ou nome de ejb.
Uma declarao de varivel de identificao ou uma faixa de
declarao varivel ou uma coleo de declarao de membro. Se
uma declarao de varivel de identificao for uma faixa de
declarao de varivel, ela varia sobre um tipo de esquema abstrato
de um entity bean. A sintaxe para declarar uma varivel de
identificao como uma faixa de varivel semelhante de SQL;
opcionalmente voc usa o operador AS.
No caso onde uma declarao de varivel de identificao uma
coleo de declaraes de membros, a varivel de identificao
declarada pela coleo de declarao de membro varia sobre
valores de uma coleo obtida pela navegao, usando uma
expresso de caminho. Uma varivel de identificao de uma
coleo de declarao de membro declarada usando-se o operador
IN.
Uma expresso de caminho uma varivel de identificao que
seguida pelo operador de navegao (.) e por um cmp-field ou cmrfield.
Sintaxe para expresses vlidas de caminho nico:
single_valued_path::= {single_valued_navigation |
identification variable}.cmp_field | single_valued_navigation
single_valued_navigation::=identification_variable.
[single_valued_cmr_field.]*
single_valued_cmr_field

A seguir est a sintaxe para a coleo de expresses vlidas de


caminho:
collection_valued_path_expression::=
identification_variable.single_valued_cmr_field.]
*colleciton_valued_cmr_field

24/04/04 01:49:17
jp@psique.org http://www.psique.org/cursos

220

A linguagem de consulta EJB


EJB-QL

Curso J150

O tipo single_valued_cmr_field designado por um cmr-field em um


relacionamento um para um ou muitos para um. O tipo de expresso
o tipo de esquema abstrato da entidade bean relativa. O tipo de
collection_valued_cmr_field uma coleo de valores do tipo de
esquema abstrato do entity bean relativo.
Considere a seguinte declarao EJB QL, que incorpora uma
clusula FROM para encontrar todos os pedidos por produtos com a
categoria livro:
SELECT DISTINCT OBJECT(o)
FROM Order o, IN(o.lineItems) 1
WHERE 1.produto.categoria = livro

A clusula WHERE
A clusula WHERE de uma consulta EJB QL determina a seleo de
dados. Ela tem a seguinte sintaxe:
WHERE conditional_expression

Exemplo de select com WHERE (todo o cdigo do ejb-jar.xml):


...
<query>
<query-method>
<method-name>findProdutosMaisCaros_ejbql</method-name>
<method-params><method-param>double</method-param></method-params>
</query-method>
<ejb-ql><![CDATA[
SELECT OBJECT(g)
FROM produto p
WHERE p.preco > ?1
]]></ejb-ql>
</query>
...

Outro exemplo:
...
<query>
<query-method>
<method-name>findOrganizacao_ejbql</method-name>
<method-params>

24/04/04 01:49:19
jp@psique.org http://www.psique.org/cursos

221

A linguagem de consulta EJB


EJB-QL

Curso J150

<method-param>java.lang.String</method-param>
</method-params>
</query-method>
<ejb-ql><![CDATA[
SELECT DISTINCT geral.organizacao.chefe
FROM organizacoes as geral
WHERE geral.nome = ?1 OR gera.apelido = ?1
]]></ejb-ql>
</query>
...

Uma expresso condicional pode conter os seguintes elementos:

Literal

Identificao varivel

Expresso de caminho

Parmetro de entrada

Composio de expresso condicional

Operadores e precedncia de operadores

Expresses between

Expresses in

Expresses like

Expresses de comparao nulas

Expresses de comparao de coleo vazia

Expresses de membro de coleo

Expresses funcionais

Cada uma delas explicada nas subsees subseqentes.


24/04/04 01:49:20
jp@psique.org http://www.psique.org/cursos

222

A linguagem de consulta EJB


EJB-QL

Curso J150

Literal
Um literal pode ser um string, um numero exato, um nmero
aproximado, um booleano. Uma string literal aparece dentro de um
par de haspas simples. Se o string literal contiver um nico caracter
de haspas internamente, o caractere precisa ser tirado, usando
outro caracter . Assim O'Connor representado como O'Connor.
Um literal numrico exato um valor numrico sem ponto decimal.
Um literal numrico aproximado um valor em ponto flutuante e
representado em notao cientfica, ou um valor numrico com
ponto decimal:
9E2 = (9 x 10^2)
Um literal lgico TRUE ou False.

Identificao varivel
Uma varivel de identificao foi definida na seo anterior, A
clusula FROM. Qualquer identificao que aparece na clusula
HWERE precisa ser declarada na clusula FROM.

Expresso de caminho
A expresso de caminho tambm foi definida na seo. A clusula
FROM. ilegal usar uma collection_valued_path_expression dentro
de uma clusula WHERE como parte de uma expresso condicional,
exceto em uma empty_comparison_expression ou
collection_member_expression.

Parmetros de entrada
Os parmetros de entrada obedecem s seguintes regras:

24/04/04 01:49:22
jp@psique.org http://www.psique.org/cursos

223

A linguagem de consulta EJB


EJB-QL

Curso J150

Um parmetro de entrada designado pelo prefixo de ponto de


interrogao (?) seguido por um inteiro, como: ?1

Parmetros de entrada so numerados a partir de 1

O nmero de parmetros de entrada distintos em uma consulta


EJB QL no pode ser maior do que o nmero de parmetros de
entrada para o mtodo finder ou select.

Parmetros de entrada s podem aparecer em expresses


condicionais envolvendo expresses vlidas de caminho nico.

Um parmetro de entrada avalia o tipo de parmetro


correspondente definido na assinatura do mtodo finder ou select
associado consulta.

Se o parmetro de entrada para o mtodo finder ou select


corresponder a um EJBObject ou EJBLocalObject, o continer
mapeia o parmetro de entrada para o valor do tipo de esquema
abstrato apropriado.

A seguinte declarao EJB QL um exemplo de consulta que usa um


parmetro de entrada. A declarao encontra todos os produtos que
so mais baratos do que um valor passado como parmetro:
SELECT DISTINCT OBJECT(o)
From Produto o
WHERE o.preco < ?1

Composio de expresso condicional


Uma expresso condicional contm outras expresses condicionais,
operaes de comparao, operaes lgicas e expresses de
caminho que avaliam para valores booleanos e literais booleanas.

Operadores e precedncia de operador


Em uma clusula WHERE, os operadores podem ser um dos que se
seguem. Esses operadores so ordenados na precedncia
decrescente:
24/04/04 01:49:24
jp@psique.org http://www.psique.org/cursos

224

A linguagem de consulta EJB


EJB-QL

Curso J150

Operador de navegao (.)


Operadores aritmticos: unrio, multiplicao e diviso(*,/),
adio e subtrao (+,-)
Operadores de comparao: =, >, >=, <, <=, <>
Operadores lgicos: NOT, AND e OR

Expresses between
A seguir est a sintaxe para o uso do operador de comparao
[NOT] BETWEEN em uma expresso condicional:
arithmetic_expression [NOT] BETWEEN arithmetic-expr AND
arithmetic-expr

Expresses in
A seguinte a sintaxe para uso do operador de comparao [NOT]
IN em uma expresso condicional:
single_valued_path_expression [NOT] IN (string-literal [, stringliteral]* )

Expresses like
A seguir est a sintaxe para uso do operador de comparao [NOT]
LIKE em uma expresso condicional:
single_valued_path_expression [NOT] LIKE pattern-value [ESCAPE
escape-character]

Expresses de comparao null


Segue-se a sintaxe para uso do operador de comparao IS NULL
em uma expresso condicional:
single_valued_path_expression IS [NOT] NULL

24/04/04 01:49:26
jp@psique.org http://www.psique.org/cursos

225

A linguagem de consulta EJB


EJB-QL

Curso J150

Expresses de comparao de coleo empty


A seguir est a sintaxe para uso do operador de comparao IS
EMPTY em uma empty_collection_comparison_expression:
collection_valued_path_expression IS [NOT] EMPTY

Expresses de membro de coleo


A prxima sintaxe para o uso do operador de comparao
MEMBER OF em uma collection_member_expression:
single_valued_path_expression [NOT] MEMBER [OF]
collection_valued_path_expression

Expresses funcionais
As seguintes so funes internas de EJB QL:

Funes de string:

CONCAT(String, String) retorna String

SUBSTRING(String, inicio, comprimento) retorna string

LOCATE(String, String, inicio) retorna inteiro

LENGTH(String) retorna inteiro

Funes aritmticas:

ABS(nmero) retorna um int, um float ou um double

SQRT(double) retorna um double

24/04/04 01:49:27
jp@psique.org http://www.psique.org/cursos

226

A linguagem de consulta EJB


EJB-QL

Curso J150

EJB QL BNF
Abaixo a notao BNF de uma EJB QL, definido na especificao de
Enterprise JavaBeans:
Smbolos BNF

Sumrio de smbolos BNF utilizados


Smbolo

Descrio

::=

O elemento esquerda do smbolo


definido pela construo direita.

A construo precedente pode ocorrer zero


ou mais vezes.

{...}

A construo entre chaves deve ser


agrupada.

[...]

A construo entre colchetes opcional.

Um OR exclusivo.

BOLDFACE Uma palavra reservada (apesar das letras


maisculas no diagrama BNF, palavras
chaves no so sensveis caixa).
Whitespace

Um espao em branco pode ser um espao,


um tab horizontal ou nova linha.

Aqui o diagrama completo BNF para EJB QL:


EJB QL ::= select_clause from_clause
[where_clause]
from_clause ::= FROM
identification_variable_declaration

24/04/04 01:49:29
jp@psique.org http://www.psique.org/cursos

227

A linguagem de consulta EJB


EJB-QL

Curso J150

[, identification_variable_declaration]*
identification_variable_declaration ::=
collection_member_declaration |
range_variable_declaration
collection_member_declaration ::=
IN (collection_valued_path_expression) [AS]
identifier
range_variable_declaration ::=
abstract_schema_name [AS] identifier
single_valued_path_expression ::=
{single_valued_navigation |
identification_variable}.cmp_field |
single_valued_navigation
single_valued_navigation ::=
identification_variable.
[single_valued_cmr_field.]*
single_valued_cmr_field
collection_valued_path_expression ::=
identification_variable.
[single_valued_cmr_field.]*
collection_valued_cmr_field
select_clause ::= SELECT [DISTINCT]
{single_valued_path_expression |
OBJECT(identification_variable)}
where_clause ::= WHERE conditional_expression
conditional_expression ::= conditional_term |
conditional_expression OR conditional_term
conditional_term ::= conditional_factor |
conditional_term AND conditional_factor
conditional_factor ::= [ NOT ] conditional_test
conditional_test ::= conditional_primary
conditional_primary ::=
simple_cond_expression |
(conditional_expression)

24/04/04 01:49:31
jp@psique.org http://www.psique.org/cursos

228

A linguagem de consulta EJB


EJB-QL

Curso J150

simple_cond_expression ::=
comparison_expression |
between_expression |
like_expression |
in_expression |
null_comparison_expression |
empty_collection_comparison_expression |
collection_member_expression
between_expression ::=
arithmetic_expression [NOT] BETWEEN
arithmetic_expression AND
arithmetic_expression
in_expression ::=
single_valued_path_expression
[NOT] IN (string_literal [, string_literal]* )
like_expression ::=
single_valued_path_expression
[NOT] LIKE pattern_value [ESCAPE escapecharacter]
null_comparison_expression ::=
single_valued_path_expression IS [NOT] NULL
empty_collection_comparison_expression ::=
collection_valued_path_expression IS [NOT]
EMPTY
collection_member_expression ::=
{single_valued_navigation |
identification_variable |
input_parameter}
[NOT] MEMBER [OF]
collection_valued_path_expression
comparison_expression ::=
string_value { =|<>} string_expression |
boolean_value { =|<>} boolean_expression} |
datetime_value { = | <> | > | < }
datetime_expression |
entity_bean_value { = | <> }
entity_bean_expression |
arithmetic_value comparison_operator

24/04/04 01:49:33
jp@psique.org http://www.psique.org/cursos

229

A linguagem de consulta EJB


EJB-QL

Curso J150

single_value_designator
arithmetic_value ::= single_valued_path_expression
|
functions_returning_numerics
single_value_designator ::= scalar_expression
comparison_operator ::=
= | > | >= | < | <= | <>
scalar_expression ::= arithmetic_expression
arithmetic_expression ::= arithmetic_term |
arithmetic_expression { + | - }
arithmetic_term
arithmetic_term ::= arithmetic_factor |
arithmetic_term { * | / } arithmetic_factor
arithmetic_factor ::= { + |- } arithmetic_primary
arithmetic_primary ::=
single_valued_path_expression |
literal | (arithmetic_expression) |
input_parameter | functions_returning_numerics
string_value ::= single_valued_path_expression |
functions_returning_strings
string_expression ::= string_primary |
input_expression
string_primary ::= single_valued_path_expression |
literal |
(string_expression) |
functions_returning_strings
datetime_value ::= single_valued_path_expression
datetime_expression ::= datetime_value |
input_parameter
boolean_value ::= single_valued_path_expression
boolean_expression ::=
single_valued_path_expression |

24/04/04 01:49:35
jp@psique.org http://www.psique.org/cursos

230

A linguagem de consulta EJB


EJB-QL

Curso J150

literal | input_parameter
entity_bean_value ::=
single_valued_navigation |
identification_variable
entity_bean_expression ::= entity_bean_value |
input_parameter
functions_returning_strings ::=
CONCAT(string_expression, string_expression) |
SUBSTRING(string_expression,
arithmetic_expression,
arithmetic_expression)
functions_returning_numerics::=
LENGTH(string_expression) |
LOCATE(string_expression,
string_expression[, arithmetic_expression]) |
ABS(arithmetic_expression) |
SQRT(arithmetic_expression)

24/04/04 01:49:37
jp@psique.org http://www.psique.org/cursos

231

Servio de mensagem em Java

Curso J150

Servio de mensagem
em Java
O ltimo tipo de EJB o message driven bean (MDB) ou, mensagem
direcionada para bean. Para isto, antes precisamos de um
introduo a JMS (Java Message Service). A prpria mensagem
direcionada para bean vista a seguir.
Justificativa para utilizao de MDB que a utilizao de
mensageria mais apropriada que a utilizao de RMI-IIOP em
vrios cenrios, pois assncrono e mais simples.

Por que usar MDB


O acesso via RMI-IIOP foi a forma at agora utilizada para acesso
aos componentes distribudos. uma maneira tradicional e pesada
para a execuo dos componentes. Enquanto RMI-IIOP til em
muitos cenrios, muitas reas teriam dificuldade de utiliz-lo.

Performance
Um cliente RMI-IIOP precisa esperar ou ficar bloqueado enquanto o
servidor efetua o processamento. Apenas quando o servidor termina
todo o trabalho que tem para fazer, retorna ao cliente o resultado,
aps isto o cliente continua o processamento.

Disponibilidade
Quando um cliente RMI-IIOP chama o servidor, ele tem que estar
sendo executado. Se o servidor cair ou se a rede cair, o cliente no
pode executar suas operaes

24/04/04 01:49:39
jp@psique.org http://www.psique.org/cursos

232

Servio de mensagem em Java

Curso J150

Suporte para mltiplos transmissores e receptores


RMI-IIOP limita voc a um nico cliente conversando com um nico
servidor em um dado momento. No existe forma para mltiplos
clientes receberem eventos de broadcast de mltiplos servidores.
Mensageria (messaging) uma alternativa invocao remota de
mtodos. A idia atrs da mensageria que existe algo no meio do
cliente e do servidor. Esta coisa recebe as mensagens de um ou
mais produtores de mensagens (message producers) e encaminha
estas mensagens para um ou mais consumidores de mensagens
(message consumers). Por causa da camada intermediria, o
produtor pode enviar a mensagem e continuar processando. Ele
pode opcionalmente ser notificado de uma resposta quando o
consumidor terminar de ler a mensagem. Isto chamado de
programao assncrona.
RMI
Aplicao

Aplicao

Messaging
Aplicao

MOM

Aplicaao

Performance
Um cliente de mensageria no precisa ficar bloqueado quando
executa uma requisio. Como um exemplo, um cliente que envia
um pedido de compra ao servidor, pode continuar com o
processamento enquanto o servidor vai processando o pedido, sem a
necessidade de ficar esperando pela resposta. Sistemas do tipo atire
e esquea (fire-and-forget) podem ser simples de codificar usando
messaging.

24/04/04 01:49:41
jp@psique.org http://www.psique.org/cursos

233

Servio de mensagem em Java

Curso J150

Confiabilidade
Se seu message-oriented middleware suportar garantia de entrega,
voc pode enviar uma mensagem e ter certeza que ela chegar ao
destino, mesmo que o consumidor no momento esteja indisponvel.
Voc envia a mensagem para o MOM e o MOM encaminha a
mensagem ao consumidor, se ele no estiver disponvel no
momento, a mensagem fica no MOM at que o destinatrio volte.
Isto no possvel de ser feito com RMI-IIOP porque a conexo
direta entre cliente e servidor, no existe o MOM no meio do
caminho.

Suporte para mltiplos transmissores e receptores


A maioria dos MOMs podem aceitar mensagens encaminhadas
simultaneamente para diversos receptores.

Introduo ao envio de mensagem


Um servio de envio de mensagem um servio que oferece
comunicao entre aplicativos ou entre componentes de software.
Qualquer aplicativo ou componente de software que usa um servio
de envio de mensagem chamado de um messaging client. Em um
tpico servio de envio de mensagem, um cliente de envio de
mensagem pode enviar e receber mensagens.
Um aplicativo de chat (conversao on-line) uma boa analogia
para ilustrar um servio de envio de mensagem. Normalmente, o
servidor de Chat oferece dois mtodos de comunicao entre os
usurios:

Um usurio pode enviar uma mensagem para todos os outros


usurios

24/04/04 01:49:43
jp@psique.org http://www.psique.org/cursos

234

Servio de mensagem em Java

Curso J150

Um usurio pode enviar uma mensagem particular para outro


usurio que no estar visvel para os demais usurios.

Como voc aprender, mais adiante, JMS tambm oferece esses dois
servios.
No entanto, um servio de envio de mensagem mais sofisticado
que um aplicativo de chat. Normalmente, em um aplicativo de chat
para troca de mensagens, o remetente e o(s) destinatrio(s)
precisam estar conectados ao mesmo tempo. Em um servio de
envio de mensagem, o remetente pode enviar uma mensagem sem o
destinatrio precisar estar conectado naquele mesmo momento. O
remetente envia a mensagem para um destino, e, depois, o
destinatrio a busca l.
JMS tambm separa os clientes. O remetente no precisa saber
nada sobre o destinatrio e vice-versa.

A API JMS
Durante muitos anos, os sistemas de MOM foram evoluindo de
forma proprietria. Cada produto tinha sua prpria API, o que
tornava os sistemas que utilizavam MOM no portveis. Era
tambm complicado para os desenvolvedores j que eles precisavem
conhecer os detalhes de cada API proprietria.
A Sun uniu foras com algumas empresas associadas para fazer o
design da API JMS, de modo a permitir a aplicativos Java criar,
enviar, e ler mensagens, bem como se comunicar com outras
implementaes de envio de mensagens. A verso original de JMS
foi lanada em agosto de 1998 e foi usada principalmente para
permitir aos aplicativos Java acessar sistemas de middleware
baseados em mensagem (MOM) existentes, como MQSeries da IBM.
Atualmente a verso mais recente da API JMS 1.1, que pode ser
baixada de http://java.sun.com/products/jms/docs.html.
Os aplicativos Java, que usam JMS, so chamados de clientes JMS e
o sistema de envio de mensagem, que gerencia o roteiro e a entrega
de mensagens, chamado de provedor JMS. Um cliente JMS que
24/04/04 01:49:45
jp@psique.org http://www.psique.org/cursos

235

Servio de mensagem em Java

Curso J150

envia um mensagem chamado de um produtor e um cliente JMS


que recebe uma mensagem chamado de consumidor JMS. Um
nico cliente JMS pode ter ambas as designaes, ou seja, ele pode
ser produtor e consumidor. Um aplicativo JMS consiste em muitos
clientes JMS e em um ou mais provedores JMS.
Os dois simpticos recursos a seguir so inerentes a JMS:

Assncrono: Um cliente JMS no precisa solicitar as mensagens


para receb-las. O provedor JMS entrega mensagens ao cliente
assim que elas chegam.
confivel: Um sistema JMS pode garantir que uma mensagem seja
entregue apenas uma vez.

Normalmente, JMS preferido a um sistema de envio de mensagens


estreitamente acoplado, nas seguintes condies:

Os clientes precisam estar separados uns dos outros

A troca de mensagens pode ocorrer ainda que nem todos os


clientes estejam ativados e executando ao mesmo tempo

O modelo de negcio requer componentes para enviar


mensagens a um outro e continuar a operar sem receber uma
resposta imediata.

Os domnios de envio de mensagem API JMS


Os domnios de envio de mensagem so modelos para envio de
mensagens. A API JMS oferece estes dois domnios de envio de
mensagem: publish/subscribe (tambm chamada pub/sub) e pointto-point (ponto a ponto).

24/04/04 01:49:47
jp@psique.org http://www.psique.org/cursos

236

Servio de mensagem em Java

Curso J150

Publish/Subscribe (pub/sub)
Nesse modelo, um cliente envia uma mensagem para um tpico e a
mensagem recebida por quaisquer clientes interessados que
assinam aquele tpico. Esse o modelo um-para-muitos, onde o
remetente tambm chamado publisher (publicador) e os
destinatrios so chamados de subscribers (assinantes). O ato de
enviar uma mensagem tambm chamado de publish (publicao).
Os tpicos enviam as mensagens diretamente a todos os assinantes
e no guardam as mensagens. Um cliente s pode consumir
mensagens depois de o cliente se inscrever em um tpico, e o
assinante precisa continuar a ser ativo para consumir mensagens
publicadas. Porm esta restrio , de alguma forma, relaxada em
JMS, permitindo a um cliente criar assinaturas durveis nas quais o
cliente pode receber mensagens enviadas enquanto ele no est
ativo.
Compare o modelo pub/sub com uma estao de rdio que divulga
notcias o tempo todo. As notcias podem ser recebidas por qualquer
rdio que esteja sintonizado na freqncia e modulao da estao
de rdio. Para receber uma parte de notcias em especial, um rdio
precisa estar sintonizado na hora em que a seo de notcias
difundida.

Point-to-Point (PTP)
Nesse modelo, um cliente envia uma mensagem que s recebida
por um cliente. O remetente envia uma mensagem para uma fila e o
destinatrio extrai essa mensagem da fila, em qualquer ocasio
conveniente que o destinatrio se conecta com o sistema. Uma fila
retm todas as mensagens recebidas at que elas sejam
consumidas, ou at que a mensagem expire.
O modelo PTP semelhante ao servio postal, em que o destinatrio
tem uma caixa postal em uma loja de correio. O remetente envia
24/04/04 01:49:49
jp@psique.org http://www.psique.org/cursos

237

Servio de mensagem em Java

Curso J150

uma carta e o destinatrio vai peg-la na loja do correio. A carta s


pode ser recebida pelo destinatrio.
Publish/Subscribe
Consumidor 1
Produtor 1
Tpico

Consumidor 2

Produtor 2
Consumidor 3

Ponto-a-ponto (point-to-point):

Produtor 1
Fila

Consumidor 1

Produtor 2

O objeto modelo JMS


Os objetos mais importantes em um objeto modelo JMS so
representados pelas seguintes interfaces no pacote javax.jms:

ConnectionFactory

Destination

Connection

Session

24/04/04 01:49:51
jp@psique.org http://www.psique.org/cursos

238

Servio de mensagem em Java

MessageProducer

MessageConsumer

Message

Curso J150

Esses objetos sero vistas adiante.


Passos de um programa que utiliza JMS:
1. Localizar o driver JMS (ConnectionFactory)
A primeira necessidade que voc tem localizar o driver para o
produto compatvel com JMS que voc est utilizando. Voc faz
isto dando um lookup no driver atravs de JNDI. O driver
chamado de ConnectionFactory.
2. Criar uma conexo JMS (Connection)
Uma conexo JMS um conexo ativa que o provedor de JMS
utiliza para gerenciar a comunicao (parecida com uma conexo
JDBC). Voc utiliza o ConnectionFactory para obter o objeto
Connection. Se voc estiver transmitindo uma quantidade grande
de dados, esta conexo pode ter balanceamento de carga em um
grupo de mquinas.
3. Criar uma sesso JMS (Session)
Uma JMS Session um objeto helper que voc utiliza para enviar
e receber mensagem. Ele serve como uma factory para
consumidores e produtores de mensagens e tambm permite a
voc encapsular suas mensagens em transaes. Voc utiliza o
objeto Connection para obter o objeto Session.
4. Localizar o destino JMS (Destination)
O destino um canal ao qual voc enviar ou do qual voc
receber suas mensagens. Localizar o canal correto o mesmo
que sintonizar o canal correto para assistir televiso ou para
discar para um telefone. O Deployer quem tem o papel de
configurar os destinos para a utilizao dos provedores JMS,
24/04/04 01:49:54
jp@psique.org http://www.psique.org/cursos

239

Servio de mensagem em Java

Curso J150

ento o destino deve ser configurvel externamente.


Normalmente seu cdigo via fazer um lookup JNDI para obter o
objeto Destination.
5. Criar um JMS Producer ou um JMS Consumer
(Producer/Consumer)
Se voc quiser enviar mensagens, voc precisa chamar um objeto
JMS para passar a ele suas mensagens. Este objeto chamado de
produtor (Producer). Para receber mensagens, voc precisa
chamar um objeto JMS e pedir a ele a mensagem. Este objeto
chamado de consumidor (Consumer). Voc utiliza o Session e o
Destination para criar um Producer ou um Consumer.
6. Enviar ou receber as mensagens
Se voc for um produtor, voc precisa primeiro colocar sua
mensagem junta. Existem diversos tipos diferentes de mensagens,
voc pode mandar uma mensagem tipo texto, bytes, stream,
objetos ou mapas. Depois que voc instncia sua mensagem, voc
a envia utilizando o Producer. Se voc quiser receber mensagens,
voc primeiro recebe uma mensagem utilizando o Consumer, e
depois voc obtm a mensagem e v o que ela .
Estes passos servem para os dois tipos de mensagens, para
mensagens pub/sub e para ponto-a-ponto. As interfaces utilizadas
sero diferentes para os dois casos.

Interface Me

Ponto - a- Ponto

Pub/Sub

ConnectionFactory
Connection
Destination
Session
MessageProducer
MessageConsumer

QueueConnectionFactory
QueueConnection
Queue
QueueSession
QueueSender
QueueReceiver,
QueueBrowser

TopicConnectionFactory
TopicConnection
Topic
TopicSession
TopicPublisher
TopicSubscriber

24/04/04 01:49:55
jp@psique.org http://www.psique.org/cursos

240

Servio de mensagem em Java

Curso J150

ConnectionFactory
Um objeto ConnectionFactory usado para criar uma conexo com
um provedor JMS. Ele suporta uso consecutivo e contm parmetros
e configurao de conexo que foram definidos por um
administrador.
No pacote javax.jms, o objeto ConnectionFactory modelado pela
interface ConnectionFactroy, cuja assinatura :
public interface ConnectionFactory

A interface ConnectionFactory no define qualquer mtodo e tem


duas sub-interfaces diretas: TopicConnectionFactory e
QueueConnectionFactory. A interface QueueConnectionFactory
usada para criar uma conexo com um provedor JMS ponto-a-ponto,
e a interface TopicConnectionFactory usada para criar uma
conexo com um provedor JMS pub/sub.
Normalmente, voc faz uma busca JNDI da conexo de fbrica em
um programa de cliente JMS. Por exemplo, para obter uma conexo
com um provedor JMS ponto-a-ponto, voc usaria o seguinte cdigo:
Context context = new InitialContext();
QueueConnectionFactory queueConnectionFactory =
(QueueConnectionFactory) context.lookup
(QueueConnectionFactory);

E, para obter uma conexo para um provedor JMS pub/sub, voc usa
o seguinte cdigo:
Context context = new InitialContext()
TopicConnectionFactory topicConnectionFactory =
(TopicConnectionFactory) context.lookup
(TopicContextFactory);

Depois, voc pode usar o mtodo createQueueConnection da


interface QueueConnectionFactory para obter um objeto
24/04/04 01:49:58
jp@psique.org http://www.psique.org/cursos

241

Servio de mensagem em Java

Curso J150

QueueConnection, ou o mtodo createTopicConnection da interface


TopicConnectionFactory para obter um objeto TopicConnection.
Uma conexo de fbrica um objeto JMS administrado, ou seja,
um objeto que contm informaes de configurao criadas por um
administrador, para serem usadas por clientes JMS.

Destination
Um objeto Destination encapsula um endereo especfico de
provedor. Um objeto Destination suporta uso consecutivo e, no
pacote javax.jms, representado pela interface Destination, cuja
assinatura :
public interface Destination

A interface Destination no tem qualquer mtodo.


No domnio pub/sub, um destino um tpico. No domnio PTP, um
destino uma fila. Para acomodar isso, a interface Destination tem
duas sub-interfaces diretas: Topic e Queue.
Como o objeto ConnectionFactory, voc obtm um objeto
Destination, fazendo uma busca JNDI. Dependendo do domnio
usado, voc precisar ou de um objeto Topic ou de um objeto
Queue. Eis o cdigo para obter um Queue no domnio PTP:
Context context = new InitialContext();
QueueConnectionFactory queueConnectionFactory =
(QueueConnectionFactory) context.lookup
(QueueConnectionFactory);
Queue queue = (Queue) context.lookup(queueName);

E aqui, como voc obtm um objeto Topic no domnio pub/sub.


Context context = new InitialContext();

24/04/04 01:49:59
jp@psique.org http://www.psique.org/cursos

242

Servio de mensagem em Java

Curso J150

TopicConnectionFactory topicConnectionFactory =
(TopicConnectionFactory) context.lookup
(TopicConnectionFactory);
Topic topic = (Topic) context.lookup(topicName);

Um objeto Destination um objeto administrado por JMS , ou seja,


um objeto que contm informaes de configurao criadas por um
administrador, para serem usadas por clientes JMS.

Connections
Um objeto Connections representa uma conexo ativa do cliente
JMS com um provedor JMS. Tipicamente, ele um soquete TCP/IP
entre um cliente JMS e um provedor JMS. O)s objetos Connection
suportam uso consecutivo e so representados pela interface
javax.jms.Connection. Essa interface Connection tem a seguinte
assinatura:
public interface Connection

Um objeto Connection um objeto relativamente pesado pois criar


um objeto Connection envolve ajustar a autenticao e a
comunicao.
Em JMS h dois tipos de conexo: QueueConnection e
TopicConnection. Um objeto QueueConnection usado para obter
uma conexo para um domnio PTP, e um Topic Connection usado
para obter uma conexo par a um domnio pub/sub. Esses dois tipos
de conexo so representados por objetos que implementam a
interface QueueConnection e a interface TopicConnection,
respectivamente. Ambas, QueueConnection e TopicConnection, so
sub interfaces diretas da interface Connection e tm um mtodo
para criar o objeto Session correspondente, adequado ao seu
domnio.
Ao ser inicialmente criado, uma conexo est no modo parado,
significando que mensagens no esto sendo entregues.
Normalmente, voc deixa a conexo no modo parado, at que a
iniciao esteja completa. Ento, o cliente pode chamar o mtodo
24/04/04 01:50:03
jp@psique.org http://www.psique.org/cursos

243

Servio de mensagem em Java

Curso J150

start do objeto connection.


Em um domnio PTP, voc obtm um objeto QueueConnection,
chamado o mtodo createQueueConnection do objeto
QueueConnectionFactory, como apresentado no cdigo a seguir:

QueueConnection queueConnection =
queueConnectionFactory.createQueueConnection();

Em um domnio pub/sub, voc obtm um objeto TopicConnection,


chamando o mtodo createTopicConnection do objeto
TopicConnectionFactory, conforme demonstrado no seguinte
cdigo:
TopicConnection topicConnection =
topicConnectionFactory.createTopicConnection();

Ao obter um objeto connection, voc pode chamar o mtodo start da


interface Connection para capacitar o seu aplicativo JMS a
consumir mensagens. No se esquea de liberar recursos, fechando
uma conexo quando ela no estiver mais em uso. Voc feche uma
conexo, chamando o mtodo close da interface Connection.

Session
Um objeto Session um contexto de seqenciamento nico para
produzir e consumir mensagens. Um objeto Session representado
pela interface Session, que usa a seguinte assinatura:
public interface Session extends java.lang.Runnable

A interface Session tem duas sub interfaces diretas: TopicSession e


QueueSession. Essas representam uma sesso em um domnio
pub/sub e em um domnio PTP, respectivamente.
Para criar um objeto TopicSession, voc chama o mtodo
createTopicSession da interface TopicConnection. Para construir
um objeto QueueSession, voc usa o mtodo CreateQueueSession
24/04/04 01:50:04
jp@psique.org http://www.psique.org/cursos

244

Servio de mensagem em Java

Curso J150

da interface QueueConnection. As assinaturas destes mtodos so:

public TopicSession createTopicSession(boolean transacted, int


acknowledgeMode) throws JMSException

Os mtodos createTopicSession e createQueueSession tm os


seguintes parmetros comuns:

transacted. Esse parmetro indica se a sesso transacionada

acknowledgeMode. Esse parmetro indica se consumidor ou o


cliente reconhecero mensagens que recebem. O seu valor pode
ser um dos trs campos da interface Session.

AUTO_ACKNOWLEDGE. Automaticamente a sesso acusa o


recebimento do cliente de uma mensagem ou, quando a sesso foi
retornada com sucesso, de uma chamada a receber ou, quando o
receptor de mensagem da sesso, chamado para processar a
mensagem, retorna com sucesso.

CLIENT_ACKNOWLEDGE. O cliente acusa o recebimento de uma


mensagem consumida, chamando o mtodo acknowledge da
mensagem.

DUPS_OK_ACKNOWLEDGE. Esse modo de acusar recebimento


instrui a sesso para receber vagarosamente a entrega de
mensagens.

O parmetro acknowledgeMode ignorado se a sesso for


transacionada.
O cdigo a seguir cria um objeto TopicSession no transacionado
com o modo de acusar recebimento AUTO_ACKNOWLEDGE:
TopicSession topicSession =
topicConnection.createTopicSession(false,
Session.AUTO_ACKNOWLEDGE);

E o cdigo seguinte instrui um objeto QueueSession no


24/04/04 01:50:06
jp@psique.org http://www.psique.org/cursos

245

Servio de mensagem em Java

Curso J150

transacionado, com o modo CLIENT_ACKNOWLEDGE:


QueueSession queueSession =
queueConnection.createQueueSession(false,
Session.CLIENT_ACKNOWLEDGE);

MessageProducer
Um objeto MessageProducer usado por um cliente JMS para
enviar mensagens a um destino. No pacote javax.jms, esse objeto
representado pela interface MessageProducer, que tem a seguinte
assinatura:
public interface MessageProducer

A interface MessageProducer tem duas sub interfaces diretas:

QueueSender. Voc usa essa interface no domnio PTP

TopicPublisher. Voc usa essa interface no domnio pub/sub.

Um objeto MessageProducer criado passando um objeto


Destination ao seu mtodo produtor de mensagem do objeto session
correspondente. Por exemplo, voc cria um objeto QueueSender,
chamando o mtodo createSender da interface QueueSession,
passando uma Queue. Eis um fragmento de cdigo que cria um
objeto QueueSender.
Context context = new InitialContext();
QueueConnectionFactory queueConnectionFactory =
(QueueConnectionFactory) context.lookup
(QueueConnectionFactory);
Queue queue = (Queue) context.lookup(queueName);
QueueConnection queueConnection =
queueConnectionFactory.createQueueConnection();
QueueSession queueSession = queueConnection.createQueueSession
(false,Session.AUTO_ACKNOWLEDGE);
24/04/04 01:50:08
jp@psique.org http://www.psique.org/cursos

246

Servio de mensagem em Java

Curso J150

QueueSender queueSender = queueSession.createSender(queue);

Como um outro exemplo de criar um objeto MessageProducer, o


prximo cdigo cria um TopicPublisher:
Context context = new InitialContext();
TopicConnectionFactory topicConnectionFactory =
(TopicConnectionFactory) context.lookup
(TopicConnectionFactory);
Topic topic = (Topic) context.lookup(topicName);
TopicConnection topicConnection =
topicConnectionFactory.createTopicConnection();
TopicSession topicSession =
topicConnectionFactory.createTopicSession
(false,Session.AUTO_ACKNOWLEDGE);
TopicPublisher topicPublisher = topicSession.createPublisher
(topic);

MessageConsumer
Um objeto MessagConsumer usado por um cliente JMS para
receber mensagem de um destino. No pacote javax.jms, esse objeto
representado pela interface MessageConsumer, que tem a
seguinte assinatura:
public interface MessageConsumer

A interface MessageConsumer tem duas subinterfaces diretas:

QueueReceiver. Voc usa essa interface no domnio PTP.

TopicSubscriber. Voc usa essa interface no domnio pub/sub.

Um objeto MessageConsumer criado passando um objeto


Destination ao seu mtodo message consumer do objeto session
correspondente. Por exemplo, voc cria um objeto QueueReceiver,
chamdno o mtodo createReceier da interface QueueSession,
passando um Queue:

24/04/04 01:50:13
jp@psique.org http://www.psique.org/cursos

247

Servio de mensagem em Java

Curso J150

Context context = new InitialContext();


QueueConnectionFactory queueConnectionFactory =
(QueueConnectionFactory) context.lookup
(QueueConnectionFactory);
Queue queue = (Queue) context.lookup(queueName);
QueueConnection queueConnection =
queueConnectionFactory.createQueueConnection();
QueueSession queueSession = queueConnection.createQueueSession
(false, Session.AUTO_ACKNOWLEDGE);
QueueReceiver queueReceiver = queueSession.createreceiver
(queue);

Para criar um objeto TopicSubscriber, voc chama o mtodo


createSubscriber da interface TopicSession, passando um Topic. O
cdigo a seguir mostra como criar um objeto TopicSubscriber:
Context context = new InitialContext();
TopicConnectionFactory topicConnectionFactory =
(TopicConnectionFactory) contrext.lookup
(TopicConnectionFactory);
Topic topic = (Topic) context.lookup(topicName);
TopicConnection topicConnection =
topicConnectionFactory.createTOpicConnection();
TopicSession topicSession = topicConnection.createTopicSession
(false, Session.AUTO_ACKNOWLEDGE);
TopicSubscriber topicSubscrier = topicSession.createSubscriber
(topic);

Message
H muitos tipos de mensagens em JMS:

TextMessage Uma mensagem contendo uma string

MapMessage Uma mensagem contendo pares nome/valor. Cad


nome um objeto string e cada valor um tipo primitivo Java.

24/04/04 01:50:15
jp@psique.org http://www.psique.org/cursos

248

Servio de mensagem em Java

Curso J150

BytesMessage Uma mensagem contendo uma stream de bytes


no interpretados.

StreamMessage Uma mensagem contendo uma corrente de


valores primitivos Java.

ObjectMessage Uma mensagem contendo um objeto que pode


ser em srie.

Todas essas mensagens so representadas por interfaces que so


derivadas da interface javax.jms.Message. A interface Message
define o cabealho de mensagem e o mtodo acknowledge de todas
as mensagens.
As mensagens JMS so compostas pelas seguintes partes:

Cabealho. Todas as mensagens suportam o mesmo conjunto de


campos de cabealho. Os campos de cabealho contm valores
usados por ambos, clientes e provedores para identificar e
encaminhar mensagens.

Propriedades. Cada mensagem contm uma facilidade interna


para suportar propriedade de valores definidos por aplicativo. As
propriedades oferecem um mecanismo eficiente para suportar a
filtragem de mensagem definida por aplicativo.

Corpo. A API JMS define vrios tipos de corpo de mensagem, que


determinam o tipo de mensagem, conforme mencionado
anteriormente.

Para enviar uma mensagem preciso criar primeiro um objeto


Message, chamando um dos mtodos create message da interface
Session. Voc pode criar qualquer tipo de mensagem, chamando um
do seguintes mtodos da interface Session: createBytesMessage,
createMapMessage, createObjectMessage, createStreamMEssage e
createTextMessage. Por exemplo, o cdigo a seguir cria um objeto
TextMessage a partir de um objeto QueueSession,m ajusta nele o
texto e o envia para uma fila:

24/04/04 01:50:20
jp@psique.org http://www.psique.org/cursos

249

Servio de mensagem em Java

Curso J150

TextMessage message = queueSession.createTextMessage();


message.setText(Aqui est a mensagem);
queueSender.send(message);

Para receber uma mensagem, voc utiliza o mtodo receive da


interface messageConsumer, conforme ilustrado no seguinte
fragmento de cdigo:
Message message = queueReceived.receive();

Se for necessrio voc pode usar instanceof para verificar qual o


tipo de mensagem retornado:
if(message instanceof ObjectMessage) {
ObjectMessage objectmessage = (ObjectMessage) message;
}

Como escrever um cliente JMS


Com base no que foi visto, podemos escrever agora dois aplicativos
clientes JMS. Um envia uma mensagem a uma fila, o outro para
receber a mensagem e exibir no console.

/*
* Criado em 18/04/2004 02:54:20
(Date of creation)
*
* Por: Joo Paulo Limberger
* jp@psique.org
http://www.psique.org/jp
*/
package org.psique.queue;
import java.util.Properties;
import
import
import
import
import
import

javax.jms.JMSException;
javax.jms.Queue;
javax.jms.QueueConnection;
javax.jms.QueueConnectionFactory;
javax.jms.QueueSender;
javax.jms.QueueSession;

24/04/04 01:50:22
jp@psique.org http://www.psique.org/cursos

250

Servio de mensagem em Java

import
import
import
import
import

Curso J150

javax.jms.Session;
javax.jms.TextMessage;
javax.naming.Context;
javax.naming.InitialContext;
javax.naming.NamingException;

/**
* @author jp
*
* 18/04/2004 02:54:20
*
*
*/
public class MessageSender {
public static void main(String[] args) {
QueueConnection queueConnection = null;
try {
Properties properties = new Properties();
properties.put(
Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
properties.put(
Context.PROVIDER_URL,
"localhost:1099");

Context context =
new InitialContext(properties);
QueueConnectionFactory queueConnectionFactory =
(
QueueConnectionFactory) context
.lookup(
"ConnectionFactory");
String queueName = "queue/A";
Queue queue =
(Queue) context.lookup(queueName);
queueConnection =
queueConnectionFactory
.createQueueConnection();
QueueSession queueSession =
queueConnection
.createQueueSession(
false,
Session.AUTO_ACKNOWLEDGE);
QueueSender queueSender =
queueSession.createSender(queue);
TextMessage message =
queueSession.createTextMessage();
message.setText(
24/04/04 01:50:24
jp@psique.org http://www.psique.org/cursos

251

Servio de mensagem em Java

Curso J150

"Esta a mensagem que vou enviar");


queueSender.send(message);
System.out.println(
"Mensagem enviada.");
} catch (NamingException e) {
System.out.println(
"Naming Exception" + e);
} catch (JMSException e) {
System.out.println(
"JMS Exception" + e);
} finally {
if (queueConnection != null) {
try {
queueConnection.close();
} catch (JMSException e) {}
}
}
}
}

Inicialmente foi realizada uma busca JNDI para obter um


QueueConnectionFactory:
Context context = new InitialContext();
QueueConnectionFactory queueConnectionFactory =
(QueueConnectionFactory) context.lookup
("ConnectionFactory");

Tendo o objeto, d para obter um objeto queue, atravs de outra


busca a JNDI. A fila topic/A est pr-configurada no JBoss.
String queueName = "queue/A";
Queue queue = (Queue) context.lookup(queueName);

A partir do QueueConnectionFactory, possvel utilizar o mtodo


createQueueConnection para criar um objeto QueueConnection:
queueConnection =
queueConnectionFactory.createQueueConnection();

24/04/04 01:50:26
jp@psique.org http://www.psique.org/cursos

252

Servio de mensagem em Java

Curso J150

O objeto queueConnection criado permite a criao de um


QueueSession:
QueueSession queueSession =
queueConnection.createQueueSession(false,
Session.AUTO_ACKNOWLEDGE);

Com o queueSession, pode-se obter um QueueSender, chamando o


mtodo createSender do objeto QueueSession, passando o objeto
Queue obtido via JNDI:
QueueSender queueSender =
queueSession.createSender(queue);

Agora, voc est pronto para enviar uma mensagem:


TextMessage message = queueSession.createTextMessage();
message.setText("Esta a mensagem que vou enviar");
queueSender.send(message);

Cliente para ler a fila:


MessageReceiver.java

/*
* Criado em 18/04/2004 03:08:24
(Date of creation)
*
* Por: Joo Paulo Limberger
* jp@psique.org
http://www.psique.org/jp
*/
package org.psique.queue;
import java.util.Properties;
import
import
import
import
import
import
import

javax.jms.JMSException;
javax.jms.Message;
javax.jms.Queue;
javax.jms.QueueConnection;
javax.jms.QueueConnectionFactory;
javax.jms.QueueReceiver;
javax.jms.QueueSession;

24/04/04 01:50:28
jp@psique.org http://www.psique.org/cursos

253

Servio de mensagem em Java

import
import
import
import
import

Curso J150

javax.jms.Session;
javax.jms.TextMessage;
javax.naming.Context;
javax.naming.InitialContext;
javax.naming.NamingException;

/**
* @author jp
*
* 18/04/2004 03:08:24
*
*
*/
public class MessageReceiver {
public static void main(String[] args) {
QueueConnection queueConnection = null;
try {
Properties properties =
new Properties();
properties.put(
Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
properties.put(
Context.PROVIDER_URL,
"localhost:1099");
Context context =
new InitialContext(properties);
QueueConnectionFactory queueConnectionFactory =
(
QueueConnectionFactory) context
.lookup(
"ConnectionFactory");
String queueName = "queue/A";
Queue queue =
(Queue) context.lookup(queueName);
queueConnection =
queueConnectionFactory
.createQueueConnection();
QueueSession queueSession =
queueConnection
.createQueueSession(
false,
Session.AUTO_ACKNOWLEDGE);
QueueReceiver queueReceiver =
queueSession.createReceiver(
queue);
queueConnection.start();
System.out.println(
"Recebendo mensagem:");
Message message =
24/04/04 01:50:30
jp@psique.org http://www.psique.org/cursos

254

Servio de mensagem em Java

Curso J150

queueReceiver.receive(1);
if (message != null) {
if (message
instanceof TextMessage) {
TextMessage textMessage =
(TextMessage) message;
System.out.println(
"Mensagem recebida:\n"
+ textMessage
.getText());
}
}
} catch (NamingException e) {
System.out.println(
"Naming Exception");
} catch (JMSException e) {
System.out.println("JMS Exception");
} finally {
if (queueConnection != null) {
try {
queueConnection.close();
} catch (JMSException e) {}
}
}
}

}
O cdigo acima, recebe a mensagem enviada pelo programa
anterior. Inicialmente feita uma busca JNDI para obter um
QueueConnectionFactory, e depois o Queue:
QueueConnectionFactory queueConnectionFactory =
(QueueConnectionFactory) context.lookup
("ConnectionFactory");
String queueName = "queue/A";
Queue queue = (Queue) context.lookup(queueName);

usando o objeto QueueConnectionFactory da primeira busca JNDI,


voc chama o seu mtodo createQueueConnection para criar um
objeto QueueConnection:
queueConnection =
queueConnectionFactory.createQueueConnection();

24/04/04 01:50:32
jp@psique.org http://www.psique.org/cursos

255

Servio de mensagem em Java

Curso J150

Usando o objeto QueueConnection resultante, voc obtm um objeto


QueueSession, chamando o mtodo createQueueSession do objeto
QueueConnection, como a seguir:
QueueSession queueSession =
queueConnection.createQueueSession(false,
Session.AUTO_ACKNOWLEDGE);

Para receber uma mensagem de uma fila, voc precisa de um objeto


QueueReceiver. isso construdo a partir do mtodo createReceived
do objeto QueueSession, passando o objeto Queue obtido da
segunda busca JNDI, como a seguir:
QueueReceived queueReceived =
queueSession.createReceiver(queue);

Com o objeto QueueReceiver, possvel chamar o seu mtodo


receive para obter uma mensagem, com o seguinte cdigo:
Message message = queueReceiver.receive(1);

Em seguida voc garante que aquela mensagem no nula e que a


mensagem um objeto TextMessage. Se for, exiba o texto do objeto
TextMessage, chamando o seu mtodo getText:
if (message != null) {
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
System.out.println(textMessage.getText());
}
}

Exemplo de pub/sub
O topico um recurso administrado, ento precisamos criar o tpico

24/04/04 01:50:34
jp@psique.org http://www.psique.org/cursos

256

Servio de mensagem em Java

Curso J150

no JBoss, inclundo o cdigo abaixo na tag <server> do arquivo:


jms/jbossmq-destinations-service.xml.
server/default/deploy/jms/jbossmq-destinations-service.xml

<mbean code="org.jboss.mq.server.jmx.Topic"
name="jboss.mq.destination:service=Topic,name=Precos">
<depends optional-attributename="DestinationManager">jboss.mq:service=DestinationManager</depends>
<depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends>
<attribute name="SecurityConf">
<security>
<role name="guest" read="true" write="true"/>
<role name="publisher" read="true" write="true" create="false"/>
<role name="durpublisher" read="true" write="true" create="true"/>
</security>
</attribute>
</mbean>

A seguir o cdigo do ClientePublicadorJMS. um cliente que gera


preos aleatrios de alguns produtos.
ClientePublicadorJMS.java (PUB/SUB)

/*
* Criado em 17/04/2004 22:08:24
(Date of creation)
*
* Por: Joao Paulo Limberger
* jp@psique.org
http://www.psique.org/jp
*/
package org.psique.pubsub;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import
import
import
import
import
import
import
import
import
import
import

javax.jms.JMSException;
javax.jms.Session;
javax.jms.TextMessage;
javax.jms.Topic;
javax.jms.TopicConnection;
javax.jms.TopicConnectionFactory;
javax.jms.TopicPublisher;
javax.jms.TopicSession;
javax.naming.Context;
javax.naming.InitialContext;
javax.naming.NamingException;

/**
* @author jp
*

24/04/04 01:50:36
jp@psique.org http://www.psique.org/cursos

257

Servio de mensagem em Java

Curso J150

* 17/04/2004 22:08:24
*
*
*/
public class ClientePublicadorJMS {
public static void main(String[] args)
throws NamingException, JMSException {
// Inicializando JNDI
Properties properties = new Properties();
properties.put(
Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
properties.put(
Context.PROVIDER_URL,
"localhost:1099");
Context ctx =
new InitialContext(properties);
// Procurar pelo ConnectionFactory utilizando JNDI
TopicConnectionFactory factory =
(TopicConnectionFactory) ctx.lookup(
"javax.jms.TopicConnectionFactory");
// Utilizar o ConnectionFactory para criar a conexo JMS
TopicConnection connection =
factory.createTopicConnection();
// Usar o Connection para criar uma sesso
TopicSession session =
connection.createTopicSession(
false,
Session.AUTO_ACKNOWLEDGE);
// Procurar o topico via JNDI
Topic topico =
(Topic) ctx.lookup("topic/Precos");
// Criar o produtor da mensagem:
TopicPublisher publisher =
session.createPublisher(topico);
// inicializa a conexo
connection.start();

// Criar vrias mensagens de texto e public-las


for (int i = 0; i < 100; i++) {
TextMessage msg =
session.createTextMessage();
Preco p = getPrecoAleatorio();
msg.setText(
"Central de noticias da Loja Sucupira informa que o produto "
24/04/04 01:50:38
jp@psique.org http://www.psique.org/cursos

258

Servio de mensagem em Java

Curso J150

+ p.getProduto()
+ " teve seu preco reajustado de "
+ p.getValorAnterior()
+ " para "
+ p.getValor());
msg.setStringProperty(
"categoria",
p.getCategoria());
msg.setDoubleProperty(
"Valor",
p.getValor());
msg.setDoubleProperty(
"ValorAnterior",
p.getValor());
publisher.publish(msg);
// D um tempo
try {
Thread.sleep((long) (15000*Math.random()));
} catch (InterruptedException e) {}
}
}
static Map precos = new HashMap();
static Preco getPrecoAleatorio() {
Preco p = null;
String nomes[][] =
{ { "Leite", "Laticinios" }, {
"Iogurte", "Laticinios" }, {
"Feijao", "Cereias" }, {
"Arroz", "Cereias" }, {
"Lentilha", "Cereias" }, {
"Grao-de-bico", "Cereias" }, {
"Martelo", "Ferragens" }, {
"Prego", "Ferragens" }
};
int i =
(int) Math.random() * nomes.length;
String nome = nomes[i][0];
p = (Preco) precos.get(nome);
if (p == null) {
p = new Preco();
p.setProduto(nomes[i][0]);
p.setCategoria(nomes[i][1]);
p.setValor(
(double) ((int) (Math.random()
* 100000))
/ 100);
precos.put(p.getProduto(), p);
}
p.setValor(
(double) ((int) (Math.random()
* 100000))
/ 100);
24/04/04 01:50:39
jp@psique.org http://www.psique.org/cursos

259

Servio de mensagem em Java

Curso J150

return p;
}
}

Abaixo a classe auxiliar Preco:


Preco

/*
* Criado em 17/04/2004 22:35:08
(Date of creation)
*
* Por: Joo Paulo Limberger
* jp@psique.org
http://www.psique.org/jp
*/
package org.psique.pubsub;
/**
* @author jp
*
* 17/04/2004 22:35:08
*
*
*/
public class Preco {
private String produto;
private String categoria;
private double valor;
private double valorAnterior;
/**
* @return
*/
public String getCategoria() {
return categoria;
}
/**
* @return
*/
public double getValor() {
return valor;
}
/**
* @param string
*/
public void setCategoria(String string) {
categoria = string;
}
/**

24/04/04 01:50:42
jp@psique.org http://www.psique.org/cursos

260

Servio de mensagem em Java

Curso J150

* @param d
*/
public void setValor(double d) {
valorAnterior = valor;
valor = d;
}
/**
* @return
*/
public double getValorAnterior() {
return valorAnterior;
}
/**
* @return
*/
public String getProduto() {
return produto;
}
/**
* @param string
*/
public void setProduto(String string) {
produto = string;
}
}

Abaixo o cdigo da classe consumidora:


ClienteAssinanteJMS.java

/*
* Criado em 17/04/2004 22:08:24
(Date of creation)
*
* Por: Joo Paulo Limberger
* jp@psique.org
http://www.psique.org/jp
*/
package org.psique.pubsub;
import java.util.Properties;
import
import
import
import
import
import
import
import

javax.jms.JMSException;
javax.jms.Message;
javax.jms.Session;
javax.jms.TextMessage;
javax.jms.Topic;
javax.jms.TopicConnection;
javax.jms.TopicConnectionFactory;
javax.jms.TopicSession;

24/04/04 01:50:44
jp@psique.org http://www.psique.org/cursos

261

Servio de mensagem em Java

import
import
import
import

Curso J150

javax.jms.TopicSubscriber;
javax.naming.Context;
javax.naming.InitialContext;
javax.naming.NamingException;

/**
* @author jp
*
* 17/04/2004 22:08:24
*
*
*/
public class ClienteAssinanteJMS {
public static void main(String[] args)
throws NamingException, JMSException {
// Inicializando JNDI
Properties properties = new Properties();
properties.put(
Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
properties.put(
Context.PROVIDER_URL,
"localhost:1099");
Context ctx =
new InitialContext(properties);
// Procurar pelo ConnectionFactory utilizando JNDI
TopicConnectionFactory factory =
(TopicConnectionFactory) ctx.lookup(
"ConnectionFactory");
// Utilizar o ConnectionFactory para criar a conexo JMS
TopicConnection connection =
factory.createTopicConnection();

// Usar o Connection para criar uma sesso


TopicSession session =
connection.createTopicSession(
false,
Session.AUTO_ACKNOWLEDGE);
// Procurar o topico via JNDI
Topic topico =
(Topic) ctx.lookup("topic/Precos");
// Criar o assinante da mensagem:
// vai receber todas as mensagens cuja propriedade
// categoria seja igual a Cereais
TopicSubscriber subscriber =
session.createSubscriber(topico,
"categoria = 'Cereais'",false);
24/04/04 01:50:46
jp@psique.org http://www.psique.org/cursos

262

Servio de mensagem em Java

Curso J150

//TopicSubscriber subscriber =
//
session.createSubscriber(topico);
// Inicia a conexo...
connection.start();
while (true) {
System.out.println(
"Aguardando a chegada de uma mensagem");
// Espera 250 segundos por uma mensagem
Message mensagem =
subscriber.receive(250000);
if(mensagem==null) {
System.out.println("Cansei de esperar!!!");
break;
}
System.out.println(
"Chegou uma mensagem!");
try {
if (mensagem
instanceof TextMessage) {
TextMessage tm =
(TextMessage) mensagem;
String produto =
tm.getStringProperty(
"produto");
String categoria =
tm.getStringProperty(
"categoria");
double valor =
tm.getDoubleProperty(
"Valor");
double valorAnterior =
tm.getDoubleProperty(
"ValorAnterior");
String msg = tm.getText();
System.out.println(
"Nova mensagem\n" + msg);
System.out.println(
"valor" + valor);
System.out.println(
"valor anterior "
+ valorAnterior);
System.out.println(
"categoria " + categoria);
} else {
System.out.println(
"Nao estou preparado para receber "
+ mensagem
.getClass()
.getName());
}
24/04/04 01:50:48
jp@psique.org http://www.psique.org/cursos

263

Servio de mensagem em Java

Curso J150

} catch (Exception e) {
System.err.println("Ops!" + e);
}
}
}

JBoss Camadas de Invocao


O subsistem (IL) Invocation Layer, responsvel por definir o
protocolo de comunicao que possibilita aos clientes enviar
mensagens para uma destinao (Destination). JBossMQ pode
suportar diferentes formas de invocao concorrentemente. Todas
as camadas de invocao tem uma natureza dual que permite que
clientes enviem mensagens e ao mesmo tempo recebam mensagens
do servidor.
Existem SEIS camadas de invocao:

RMI IL
A primeira camada de invocao baseada em RMI (Remote
Method Invocation). bem robusta pois baseada na tecnologia
RMI. Deve ser usada quando aplicaes clientes possuirem muitas
threads compartilhando a mesma conexo.
Esta IL vai tentar conectar-se via conexo TCP/IP via socket do
servidor para o cliente. Logo, clientes atrs de firewalls ou com
restries de segurana no devem utilizar.

OIL IL
A prxima camada que foi desenvolvida foi a Optimized IL (OIL). A
OIL usa protocolo TCP/IP e serializao que tem um overhead muito
baixo. Este foi o protocolo recomendado baseado em socket at a
adio do UIL2.
24/04/04 01:50:50
jp@psique.org http://www.psique.org/cursos

264

Servio de mensagem em Java

Curso J150

Esta camada tambm ir tentar estabelecer uma conexo TCP/IP via


socket. Logo clientes atrs de firewalls no devem usar esta IL.

UIL IL
A Unified Invocation Layer (UIL) foi desenvolvida para permitir a
clientes Applet conectarem-se a servidores. Ela quase igual ao
protocolo OIL exceto que uma camada multiplexadora foi utilizada
para permitir canais dual. A camada multiplexadora cria dois
sockets virtuais sobre um socket fsico. Esta IL mais lenta que a
OIL porque tem um grande overhead na multiplexao. Esta IL est
depreciada em favor da UIL2.

UIL2 IL
A Unified version 2 Invocation Layer (UIL2) uma nova variao do
protocolo da UIL que tambm usa um nico socket entre o cliente e
o servidor, s que diferentemente do UIL e do OIL que utilizam
bloqueamento de mensagens a nvel de socket, o protocolo UIL2 usa
um nvel de transporte verdadeiramente assncrono para enviar e
receber mensagens. Isto possibilita melhora na utilizao do canal e
a IL preferida.

JVM IL
A Java Virtual Machine (JVM) IL foi desenvolvida para acabar com o
overhead do TCP/IP quando o cliente JMS estiver sendo executado
na mesma mquina virtual. Esta IL usa chamada direta a mtodos
dos servios do servidor e do cliente. Isto aumenta muito a
eficincia pois sockets no so criados e no necessria a criao
de threads auxiliares (para monitorar os sockets). Esta a IL que
ser usada pelos Message Driven Beans (MDB) ou outro
componente que executado na mesma mquina virtual que o
servidor tais como servlets ou MBeans.

24/04/04 01:50:51
jp@psique.org http://www.psique.org/cursos

265

Servio de mensagem em Java

Curso J150

HTTP IL
A camada de invocao HTTP permite o acesso aos servios do
JBossMQ sobre os protocolos HTTP ou HTTPS . Esta IL consiste em
um servlet baixado no deploy/jms/jbossmq-httpil.sar para controlar
o trfego http. Esta IL til para acessar o JMS atravs de firewall
quando a nico porto admitido requer HTTP.

Configurao da IL
No diretrio ${JBOSS_HOME}/server/default/deploy/jms, existem
arquivos xxx-service.xml, onde xxx a IL (oil-service.xml, oil2service.xml, rmi-il-service.xml, jvm-il-service.xml, uil2-service.xml).
Nestes arquivos pode-se ver o Atributo ConnectionFactoryJNDIRef,
que o nome que deve ser acessado para obter a fbrica
(ConnectionFactory). A conexo via http obtida utilizando-se
(HTTPConnectionFactory), pois via http o acesso via Servlet, o
gerenciamento feito pelo MBean
org.jboss.mq.il.http.HTTPServerILService .

24/04/04 01:50:53
jp@psique.org http://www.psique.org/cursos

266

Beans Direcionados para


Mensagem (MDB)

Curso J150

Beans Direcionados para


Mensagem (MDB)
No tpico anterior vimos JMS. O objetivo foi conseguir
conhecimento bsico de JMS para trabalharmos com o terceiro tipo
de EJB que o Message-driven beans (MDB). As mensagens
direcionadas para beans so um novo tipo de bean acrescido
especificao EJB 2.0. O modelo MDB destinado a entrada de
mensagens JMS. Com os outros dois tipos de beans, voc s pode
enviar e receber mensagens sncronas, no existindo a possibilidade
de troca assncrona.

O que um bean direcionado para


mensagem
Para o cliente (e em relao ao servio de envio de mensagem), um
bean direcionado para mensagem (MDB) um consumidor de
mensagens assncronas. No entanto, olhando para esse
comportamento, um bean direcionado para mensagem semelhante
a um session bean stateless, pelo fato de um bean direcionado para
mensagem no manter o estado da conversao. Um MDB criado
e controlado pelo continer EJB. Porm diferente de session beans e
de entity beans, MDBs no tem interface home ou remote. Os
aplicativos cliente acessam um MDB atravs de JMS, enviando
mensagens ao destino JMS.

24/04/04 01:50:55
jp@psique.org http://www.psique.org/cursos

267

Beans Direcionados para


Mensagem (MDB)

Curso J150

MDB no tem interfaces home ou remote


Os message-driven beans no tem interface home, local home,
remote ou local. Voc no chama um message-driven bean usando
rmi. A razo que o MDB processa mensagens e estas mensagens
so recebidas de um cliente via a API JMS. MDB podem consumir
qualquer tipo de mensagem JMS, de canais (tpico) ou filas (queue).

MDB tem um nico mtodo de negcio


MDBs so receptores de mensagem JMS, e os receptores de
mensagens JMS no sabem que tipo de mensagem est chegado. Os
MDBs tem um nico mtodo de negcio chamado onMessage(). Este
mtodo fracamente tipado pois aceita um objeto Message
genrico que pode representar qualquer coisa Uma ByteMessage,
ObjectMessage, TextMessage, StreamMessage ou MapMessage.
Voc no pode criar muito mtodos de negcio em seu MDB, no
lugar, voc precisa abrir a mensagem em tempo de execuo e
descobrir que tipo de mensagem .

MDB no tem nenhum valor de retorno


Isto porque um MDB desacoplado do produtor da mensagem. O
produtor da mensagem no espera pela resposta do MDB, ele envia
a mensagem e continua o processamento logo aps a mensagem
seja transmitida.

MDB no enviam exceptions de volta ao


cliente
O produtor da mensagem no espera que o MDB receba a
mensagem nem que o processe. Quando o MDB processar a
mensagem, pode ser que o cliente j no exista mais.

24/04/04 01:50:57
jp@psique.org http://www.psique.org/cursos

268

Beans Direcionados para


Mensagem (MDB)

Curso J150

MDBs so stateless
Os MDBs no armazenam estado conversasional.

MDBs podem ser assinantes durveis ou no


durveis
Uma assinatura durvel para um tpico significa que o assinante
JMS receber todas as mensagens, mesmo que o assinante esteja
inativo. Se uma mensagem for enviada para um canal que tem um
assinante durvel inativo, a mensagem persistida e entregue
quando o assinante durvel retornar ativa. Uma assinatura no
durvel para um tpico indica que o assinante s receber as
mensagens que forem publicadas enquanto o assinante estiver
ativo. Mensagens enviadas enquanto o assinante estiver inativo
sero perdidas.

A Application Programming
Interface (API)
Uma classe de message-driven bean precisa ser uma classe pblica
e precisa implementar as duas seguintes interfaces:

javax.ejb.MessageDrivenBean

javax.jms.MessageListener

Todo o MDB, alm de implementar as interfaces acima, deve possuir


um mtodo ejbCreate() que retorna void e no recebe nenhum
argumento.
Alm das duas interfaces, voc precisa saber sobre a interface
MessageDrivenContext que oferecida pelo continer EJB para
cpia de MDB.

24/04/04 01:50:59
jp@psique.org http://www.psique.org/cursos

269

Beans Direcionados para


Mensagem (MDB)

Curso J150

A interface javax.jms.MessageListener
A assinatura da interface javax.jms.MessageListener a seguinte:
public interface javax.jms.MessageListener {
public void onMessage(Message message);
}

Como se pode ver, uma interface de um nico mtodo, que o que


ser chamado quando as mensagens chegarem.

A interface javax.ejb.MessageDrivenBean
A javax.ejb.MessageDrivenBean tem a seguinte assinatura:
public interface MessageDrivenBean extends EnterpriseBean

Ela define dois mtodos: setMessageDrivenContext e ejbRemove. As


assinaturas de ambos os mtodos so as seguintes:
public void
setMessageDrivenContext(MessageDrivenContext context)
throws EJBException;
public void ejbRemove() throws EJBException;

O setMessageDrivenContext ajusta o contexto de mensagem


direcionada associado, e o mtodo ejbRemove chamado pelo
continer EJB antes do continer terminar a vida do objeto
message-driven bean.

A interface javax.ejb.MessageDrivenBean
A interface MessageDrivenContext oferece acesso ao contexto da
mensagem direcionada no tempo de execuo, que o continer
oferece a uma cpia de mensagem direcionada por enterprise bean.
O continer passa a interface MessageDrivenContext a uma cpia,
24/04/04 01:51:00
jp@psique.org http://www.psique.org/cursos

270

Beans Direcionados para


Mensagem (MDB)

Curso J150

depois de ela ter sido criada. O contexto de mensagem direcionada


permanece associado cpia pelo tempo de vida da cpia.
A MessageDrivenContext derivada da interface EJBContext e tem
a seguinte assinatura:
public interface MessageDrivenContext extends EJBContext

A interface MessageDrivenContext tem os seguintes mtodos:

getRollbackOnly Verifica se a transao foi marcada s para


retorno. Esse mtodo s pode ser chamado por um bean
direcionaod para mensagem com demarcao de transao
gerenciada pelo continer.

getUserTransaction Obtm a interface de demarcao de


transao. S enterprise bens com transaes gerenciadas por
bean podem usar a interface UserTransaction.

isCallerInRole Verifica se o chamador recebeu uma funo


(papel) de segurana.

setRollbackOnly. Marca a transao s para retorno. Esse mtodo


s pode ser chamado por um bean direcionaod para mensagem
com demarcao de transao gerenciada pelo continer.

getCallerPrincipal, getEJBHome, getEJBLocalHome. Esses


mtodos so herdados da interface EJBContext e no podem ser
chamados por uma cpia de um bean direcionado para
mensagem.

Como acessar um message-driven bean


Um aplicativo cliente que deseje acessar uma mensagem
24/04/04 01:51:02
jp@psique.org http://www.psique.org/cursos

271

Beans Direcionados para


Mensagem (MDB)

Curso J150

direcionada para bean faz isso recuperando um objeto


javax.jms.Queue de uma busca JNDI. O cdigo a seguir ilustra como
uma referncia a uma fila, chamada MyQueue, pode ser obtida:
Context context = new InitialContext();
Queue queue = (Queue) context.lookup
(javax:com/env/jms/MyQueye);

Como escrever um mensagem direcionada


por bean
O prximo exemplo uma mensagem direcionada para bean
chamada MeuMDB. um simples MDB que recebe uma fila e, ao
receber uma mensagem, recupera-a e envia um objeto diferente
fila. O exemplo consiste de cinco partes:

Especificar a classe de MDB

Criar o descritor de distribuio

Configura JBoss para distribuir a bean direcionado para


mensagem

Empacotar o Bean

Escrever o aplicativo cliente

Essas cinco partes so discutidas adiante:

A classe bean direcionado para mensagem


Diferente de session beans e de entity beans, um bean direcionado
para mensagem no tem interfaces home ou remote. A nica classe
Java que voc precisa escrever para um MDB a prpria classe
bean. Segue abaixo o cdigo:
MeuMDB.java

/*
24/04/04 01:51:04
jp@psique.org http://www.psique.org/cursos

272

Beans Direcionados para


Mensagem (MDB)

Curso J150

* Criado em 20/04/2004 00:30:17


(Date of creation)
*
* Por: Joo Paulo Limberger
* jp@psique.org
http://www.psique.org/jp
*/
package org.psique.ejb;
/**
* @author jp
*
* 20/04/2004 00:30:17
*
*
*/
import
import
import
import
import
import
import
import
import
import
import
import
import

javax.ejb.EJBException;
javax.ejb.MessageDrivenBean;
javax.ejb.MessageDrivenContext;
javax.jms.JMSException;
javax.jms.Message;
javax.jms.MessageListener;
javax.jms.Queue;
javax.jms.QueueConnection;
javax.jms.QueueConnectionFactory;
javax.jms.QueueSender;
javax.jms.QueueSession;
javax.jms.TextMessage;
javax.naming.InitialContext;

public class MeuMDB


implements MessageDrivenBean, MessageListener {
MessageDrivenContext context = null;
QueueConnection connection;
QueueSession session;
public MeuMDB() {
System.out.println("Construindo MeuMDB");
}
public void setMessageDrivenContext(MessageDrivenContext
context) {
this.context = context;
System.out.println(
24/04/04 01:51:06
jp@psique.org http://www.psique.org/cursos

273

Beans Direcionados para


Mensagem (MDB)

Curso J150

"guardando o conexto setMessageDrivenContext");


}
public void ejbCreate() throws EJBException {
System.out.println("ejbCreate");
try {
InitialContext initContext =
new InitialContext();
QueueConnectionFactory qcf =
(
QueueConnectionFactory) initContext
.lookup(
"java:comp/env/jms/QCF");
connection =
qcf.createQueueConnection();
session =
connection.createQueueSession(
false,
QueueSession
.AUTO_ACKNOWLEDGE);
connection.start();
} catch (Exception e) {
throw new EJBException(
"Falhou na inicializao do MeuMDB",
e);
}
}
public void ejbRemove() {
System.out.println("ejbRemove");
context = null;
try {
if (session != null)
session.close();
if (connection != null)
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
public void onMessage(Message msg) {
System.out.println("onMessage");
24/04/04 01:51:08
jp@psique.org http://www.psique.org/cursos

274

Beans Direcionados para


Mensagem (MDB)

Curso J150

try {
TextMessage message =
(TextMessage) msg;
Queue queue =
(Queue) msg.getJMSReplyTo();
QueueSender sender =
session.createSender(queue);
TextMessage message2 =
session.createTextMessage(
message.getText());
sender.send(message2);
sender.close();
} catch (Exception e) {
e.printStackTrace();
}
}

Olhando o mtodo ejbCreate da classe message-driven bean. A


primeira linha de cdigo, depois de escrever o nome de mtodo ao
Console um bloco try que tenta obter um objeto JDNI
InitialContext e realizar uma busca JNDI, para obter um objeto
javax.jms.QueueConnectionFactory:
InitialContext initContext = new InitialContext();
QueueConnectionFactory qcf = (QueueConnectionFactory)
initContext.lookup("java:comp/env/jms/QCF");

Depois de obter o objeto QueueConnectionFactory, ele usado para


construir um QueueConnection:
connection = qcf.createQueueConnection();

24/04/04 01:51:10
jp@psique.org http://www.psique.org/cursos

275

Beans Direcionados para


Mensagem (MDB)

Curso J150

Ento o mtodo createQueueSession de queueConnection


utilizado para obter-se o queueSession:
session = connection.createQueueSession(false,
QueueSession.AUTO_ACKNOWLEDGE);

Observe que passando false, como primeiro argumento do mtodo


createQueueSession, para indicar que no est criando um objeto
sesso transacional.
Finalmente, inicia-se o objeto QueueConnection, chamando o seu
mtodo start com o seguinte cdigo:
connection.start();

Tambm importante o mtodo onMessage, que herdado da


interface MessageListener. Esse mtodo aceita um objeto
javax.jms.Message, representando a mensagem que chega, como se
v abaixo:

public void onMessage(Message msg) {


System.out.println("onMessage");
try {
TextMessage message = (TextMessage) msg;
Queue queue = (Queue) msg.getJMSReplyTo();
QueueSender sender = session.createSender(queue);
TextMessage message2 =
session.createTextMessage(message.getText());
sender.send(message2);
sender.close();
}
catch(Exception e) {
e.printStackTrace();
}
}

24/04/04 01:51:12
jp@psique.org http://www.psique.org/cursos

276

Beans Direcionados para


Mensagem (MDB)

Curso J150

O deployment descriptor
Como outros aplicativos EJB voc precisa de um descritor para
distribuir o seu MDB:

<?xml version="1.0"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD
Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejbjar_2_0.dtd">
<ejb-jar>
<enterprise-beans>
<message-driven>
<ejb-name>MeuMDB</ejb-name>
<ejb-class>org.psique.ejb.MeuMDB</ejb-class>
<transaction-type>Container</transaction-type>
<acknowledge-mode>AUTO_ACKNOWLEDGE</acknowledge-mode>
<message-driven-destination>
<destination-type>javax.jms.Queue</destination-type>
</message-driven-destination>
<resource-ref>
<res-ref-name>jms/QCF</res-ref-name>
<res-type>ConnectionFactory</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</message-driven>
</enterprise-beans>

</ejb-jar>

Note que sob o elemento <message-driven> existe um elemnto


<acknowledge-mode> que contm o valor de
AUTO_ACKNOWLEDGE

24/04/04 01:51:14
jp@psique.org http://www.psique.org/cursos

277

Beans Direcionados para


Mensagem (MDB)

Curso J150

Configurao do arquivo jboss.xml


Especificamente para distribuir o MDB em JBoss, voc precisa
configura um arquivo jboss.xml como o abaixo:

<?xml version="1.0" encoding="UTF-8"?>


<jboss>
<enterprise-beans>
<message-driven>
<ejb-name>MeuMDB</ejb-name>
<destination-jndi-name>queue/A</destination-jndi-name>
<resource-ref>
<res-ref-name>jms/QCF</res-ref-name>
<jndi-name>ConnectionFactory</jndi-name>
</resource-ref>
</message-driven>
</enterprise-beans>

</jboss>

Este arquivo contm dados que no so padronizados, ou seja o


formato proprietrio do JBoss. No ejb-jar.xml no est
especificado o nome da fila que o bean MeuMDB recebe. Portanto, a
fila precisa ser especificada pelo distribuidor de bean, incorporando
essas informaes no arquivo jboss.xml. As mensagens direcionadas
para beans precisam ter sempre um arquivo jboss.xml para a
especificao do nome de destino a partir do qual os beans devem
receber mensagens. Outro motivo pelo qual voc precisa do
jboss.xml que voc precisa mapear a referncia JMS
ConnectionFactory no descritor de distribuio para o nome JNDI
do JBossMQ ConnectionFactory distribudo.

Empacotamento do MDB
Para empacotar, utilizando jar, utilize o comando abaixo:

24/04/04 01:51:16
jp@psique.org http://www.psique.org/cursos

278

Beans Direcionados para


Mensagem (MDB)

Curso J150

jar cfv mdb.jar org/psique/ejb/MeuMDB.class META-INF/ejb-jar.xml


Este comando cria um arquivo .jar chamado mdb.jar no diretrio do
projeto. Copie este arquivo no diretrio de distribuio do JBoss.

24/04/04 01:51:17
jp@psique.org http://www.psique.org/cursos

279

JCA Java Connector


Architecture

Curso J150

JCA Java Connector


Architecture
A especificao J2EE 1.3 contm a especificao JCA Java
Connector Architecture que permite a integrao de adaptadores de
recursos ao aplication server com transaes e segurana. A
especificao de JCA pode ser obtida de:
http://java.sun.com/j2ee/connector/. A especificao de JCA
descreve como gerenciadores de recursos tais como (EIS)
Enterprise Information Systems podem ser integrados ao AS.
Exemplos de EIS podem ser ERPs (Enterprise Resource Planning),
processadores de transaes em mainframe, aplicaes no java,
etc.
A rao para o foco nos EIS principalmente porque a noo de
transao, segurana e escalabilidade so requisitos nos sistemas
de software corporativos, apesar de JCA ser aplicvel a qualquer
recurso que necessite ser integrado ao Aplication Server de uma
forma segura, escalvel e utilizando transaes.
JCA define um SPI (Service Provider Interface) padro para
integrao das facilidades de transaes, segurana e
gerenciamento de conexes de um application server com aqueles
que gerenciam os recursos que se deseja integrar. O SPI define um
contrato a nvel de sistema entre o adaptador do recurso e o
application server.
A arquitetura de conector (JCA) tambm define uma Common Client
Interface (CCI) para acessar os recursos. A CCI o objetivo do
desenvolvimento de ferramentas para EIS e outros usurios
sofisticados de recursos compartilhados. A CCI prov uma forma de
minimizar o cdigo especfico para o EIS. Tipicamente
desenvolvedores J2EE iro acessar um recurso usando algum tipo
24/04/04 01:51:19
jp@psique.org http://www.psique.org/cursos

280

JCA Java Connector


Architecture

Curso J150

de ferramenta, ou uma interface especfica para um recurso no


lugar de usar CCI diretamente. A razo que CCI no um tipo
especfico de API. Para ser usado efetivamente precisa ser usado em
conjunto com metadados que descrevem como mapear a API
genrica CCI para os tipos de dados usados internamente pelo
gerenciador do recurso.
O propsito de JCA permitir que um fabricante de um recurso
providencie um adaptador padro para seu produto. Um adaptador
de recurso um driver que utilizado por aplicaes Java para se
conectar ao recurso. O adaptador de recurso conecta-se a um
aplication server e prov conectividade entre o gerenciador do
recurso e o aplication server e a aplicao corporativa. Para fazer
isto, o fabricante do produto deve implementar um adaptador
compatvel com JCA .

24/04/04 01:51:21
jp@psique.org http://www.psique.org/cursos

281

JCA Java Connector


Architecture

Curso J150

Diagrama de classes da especificao JCA 1.0

24/04/04 01:51:23
jp@psique.org http://www.psique.org/cursos

282

JCA Java Connector


Architecture

24/04/04 01:51:25
jp@psique.org http://www.psique.org/cursos

Curso J150

283

Chamando Beans de outros


Beans

Curso J150

Chamando Beans de
outros Beans

Qualquer modelo de objetos EJB tem camadas de beans chamando


outros beans. Exemplo, o clculo de preos de produtos usando
regras, descontos, taxas e custos de envio ou um catlogo de
produtos.
O sistema de preos chama o catlogo. Por simplicidade, assumimos
que ambos os beans so stateless session beans.

Lookups JNDIs default


Para o seu bean chamar outro bean, voc precisa ir atravs do
mesmo processo que qualquer outro cliente faria, ou seja:
1. Procurar o home do outro bean via JNDI
2. Chame o mtodo create() no objeto home
3. Chame o mtodo de negcio do EJB object
4. Chame remove() no EJB object
Como ns aprendemos antes, fazer um lookup para localizar o home
via JNDI, o primeiro passo inicializar o JNDI, tal como o driver
JNDI que voc est usando, o que difere de continer para
continer. Mas se voc escrever um bean que chama outro bean,
como voc sabe qual provedor de servio JNDI usar? Alm de tudo
seus beans devem ser independente de continer. Codificar as
24/04/04 01:51:27
jp@psique.org http://www.psique.org/cursos

284

Chamando Beans de outros


Beans

Curso J150

informaes de JNDI no interior do cdigo acabam com a


portabilidade.
A boa notcia que se voc estiver procurando em um bean por
outro bean, voc no precisa incluir nenhum parmetro de JNDI.
Voc simplesmente utiliza o contexto inicial JNDI default. O
continer configura o contexto inicial JNDI antes que seus beans
sejam executados. Por exemplo, o seguinte cdigo retirado da
chamada de um bean para outro bean.
// Pega o contexto inicial default JNDI chamando
// o construtor sem argumentos
Contexto ctx = new InitialContext();
// Procurar pela interface home
Object result = ctx.lookup(java:comp/env/ejb/CatalogoHome);
// Converter o objeto result para o tipo, utilizando o estilo
// RMI-IIOP
CatalogoHome home = (CatalogoHome)
javax.rmi.PortableRemoteObject.narrow(result,
CatalogHome.class);
// Cria o beans
Catalogo c = home.create(...);

O cdigo anterior portvel porque ningum precisa suprir os


parmetros especficos do continer para inicializao de JNDI.

Referncias EJB
No exemplo anterior procuramos por um bean em
java:comp/env/ejb. Esta uma localizao JNDI que a especificao
EJB recomenda (mas no requer) que voc coloca os beans que so
referenciados por outros beans.

24/04/04 01:51:28
jp@psique.org http://www.psique.org/cursos

285

Chamando Beans de outros


Beans

Curso J150

Mas, voc no pode garantira que a localizao que voc


especificou estar disponvel. Isto pode acontecer se seu bean tiver
um conflito com outro bean.
O seu cdigo no ir funcionar se sua localizao JNDI mudar em
tempo de deployment. E normalmente, o deployer no conseguiria
modificar seu cdigo, porque ele ele estaria dentro de um arquivo .
class apenas. Isto pode acontecer por exemplo, se voc um
vendedor independente de software que vende beans, voc pode
querer proteger sua propriedade intelectual e fazer alteraes
futuras mais fcil sem que os clientes vejam o cdigo fonte.
EJB resolve esta situao com referncias EJB. Uma referncia EJB
um apelido para a localizao JNDI que voc quer procurar o
bean. Este apelido pode no corresponder localizao atual JNDI
que o deployer coloca seu bean. Seu cdigo parece com uma
interface home via seu apelido e o deployer ento liga o apelido com
a localizao real JNDI de sua escolha, mas utilizando links
simblicos.
Referncias EJB so declaradas no deployment descriptor.
Programando com referncias EJB muito melhor. Nosso bean
precificador est utilizando o catlogo bean, ento no interior do
precificador bean ns simplesmente listamos todas as informaes
necessrias sobre o catlogo bean na referncia EJB. O deployer
ento sabe que nosso bean precificar usa extamente um outro
enterprise bean catlogo e nenhum outro. Isto til porque o
deployer agora sabe qual arquivos o precificador
depende e qual localizao JNDI precisa ser conectada. Da mesma
forma, as ferramentas do continer podem facilmente inspecionar o
deployment descriptor e verificar que o deployer fez seu trabalho.
Note que enquanto este exemplo declara o bean catalogo no
deployment descriptor, ns no temos que fazer isto. O bean
24/04/04 01:51:30
jp@psique.org http://www.psique.org/cursos

286

Chamando Beans de outros


Beans

Curso J150

catlogo pode estar em seu arquivo Ejb-jar com seu prprio


deployment descriptor.
...
<enterprise-beans>
<!-aqui definimos o catalogo beans
-->
<session>
<ejb-name>Catalogo</ejb-name>
<home>org.psique.ejb.CatalogoHome</home>
....
</session>
<session>
<ejb-name>Precificador</ejb-name>
<home>org.psique.ejb.PrecificadorHome</home>
...
<ejb-ref>
<description>
Esta referncia EJB diz que o sistema de Precificao
usa o Catalogo
</description>
<!-O apelido do precificador utiliza para
procurar o Catalogo. Ns o declaramos ento o
deployer sabe como ligar o nome do Catalogo home
no java:comp/env/ejb/CatalogoHome. Isto pode no
corresponder localizao atual qual o
deployer ligou o objeto pelas ferramentas do
continer. O deployer pode configura alguns tipos
de links simblicos para ter um apelido apontando
para a localizao JNDI real.
-->
<ejb-ref-name>ejb/CatalogoHome</ejb-ref-name>
<!-- CatalogoBean um session bean -->
<ejb-ref-type>Session</ejb-ref-type>
<!-- A classe CatalogoHome -->
<home>org.psique.ejb.CatalogoHome</home>
<!-- A interface remota de Catalogo -->
<remote>org.psique.ejb.Catalogo</remote>
<!-- Opcional, o ejb-name do catlogo -->
24/04/04 01:51:32
jp@psique.org http://www.psique.org/cursos

287

Chamando Beans de outros


Beans

Curso J150

<ejb-link>Catalogo</ejb-link>
</ejb-ref>
</session>
</enterprise-beans>
....

Voc tambm pode acessar componentes EJB de um outro


componente EJB atravs da interface local, no lugar de utilizar a
interface remota. Para fazer isto, seu deployment descriptor deve
ser exatamente igual, exceto que no lugar de chamar o elemento
<ejb-ref> ns podemos cham-lo de <ejb-local-ref>, no lugar de
<home> ns usaremos <local-home>, e no lugar de <remote>
devemos usar <local>. O cdigo JNDI para procurar o bean deve
mudar, ele deve procurar o interface local home no lugar da
interface home, e chamara a interface local no lugar da remota.

24/04/04 01:51:34
jp@psique.org http://www.psique.org/cursos

288

Segurana

Curso J150

Segurana
Existem duas principais medidas que os clientes devem obedecer
para acessar um sistema EJB com segurana.
Primeiro: O cliente precisa ser autenticado. Autenticao verifica
que o cliente quem alega ser. Por exemplo, o cliente pode entrar
com um usurio/senha (segredo compartilhado) na aplicao web e
estas credenciais so verificadas no cadastro do cliente. Aps
autenticado, o cliente associado com uma identidade segura para
o resto da sesso.
Segundo: O cliente precisa estar autorizado. Uma vez que o cliente
est autenticado, ele precisa ter permisso para executar as
operaes desejadas.
Existem uma diferena importante aqui: autenticao verifica quem
o cliente , autorizao checa se um cliente j autenticado tem
direitos para executar o servio desejado. Se o cliente tem uma
identidade ento ele j foi autenticado. A autorizao ocorre
durante as chamadas a mtodos de EJB.

Autenticao
Nas verses anteriores de EJB (1.0 e 1.1), no existia uma forma
portvel de autenticao. A forma especfica utilizada pelo cliente
era implementada no cdigo do cliente era da aplicao e
proprietria do continer. Cada tipo de continer controlava a
autenticao de forma diferente.
Com EJB2.0, a autenticao se tornou protvel e robusta. A
autenticao efetuada atravs de JAAS (Java Authentication and
24/04/04 01:51:36
jp@psique.org http://www.psique.org/cursos

289

Segurana

Curso J150

Authorization Service).

O que JAAS
JAAS (Java Authentication and Authorization Service) uma
interface portvel que habilita voc a se autenticar e autorizar
usurios em Java. Ela permite que voc logue em um sistema sem
que voc conhea o sistema de segurana que est sendo utilizado.
Atrs de JAAS o application server determina se suas credenciais
so autenticas.
O poder de JAAS reside na habilidade de usar praticamente
qualquer sistema de segurana. Alguns application servers
permitem que voc configure usurios e passwords no application
server, outros utilizam arquivos de propriedades lidos pelo
application server em tempo de execuo, outros ainda funcionam
integrados a SGBDs, LDAP, etc.

As principais classes de JAAS


As principais classes podem ser quebradas em trs categorias:
common, authentication e authorization. A lista a seguir apresenta
apenas as classes common e authentication:
Classes Common:
Subject (javax.security.auth.Subject)
Principal (java.security.Principal)
Classes Authentication:
Callback (javax.security.auth.callback.Callback)
CallbackHandler (javax.security.auth.callback.CallbackHandler)
Configuration (javax.security.auth.login.Configuration)
LoginContext (javax.security.auth.login.LoginContext)
24/04/04 01:51:37
jp@psique.org http://www.psique.org/cursos

290

Segurana

Curso J150

LoginModule (javax.security.auth.spi.LoginModule)

Subject e Principal
Para autorizar um acesso a um recurso, aplicaes primeiro
precisam autenticar o requisitante da requisio. O framework JAAS
define o termo SUBJECT para representar a origem da requisio. A
classe Subject a classe central de JAAS. A classe Subject
representa informaes para uma nica entidade, tal como uma
pessoa ou um servio. Ela encapsula o principal da entidade, as
credenciais pblicas e a credencial privada. A API JAAS usa a
interface existente em Java2 java.security.Principal para
representar um principal, que essencialmente apenas um nome
digitado.
Durante o processo de autenticao, um Subject populado com
identidades associadas, ou Principals. Um Subject pode ter vrios
Principals. Por exemplo, uma pessoa pode ter um nome Principal
(Jos da Silva) e um CPF Principal (123.123.123-34), e um nome
de usurio Principal (josesilva), tudo que ajuda distinguir o
Subject de outro Subject. Para recuperar os Principals associado
a um Subject, dois mtodos esto disponveis:
{
...
public Set getPrincipals() {...}
public Set getPrincipals (Class c) {..}
}

O primeiro mtodo retorna todos os Principals contidos em um


Subject. O segundo mtodo apenas retorna aqueles Principals
que forem instncias da classe c ou uma subclasse de c. Um set
vazil ser retornado se o Subject no tiver Principals do tipo
solicitado. Note que a interface java.security.acl.Group uma
subinterface de java.security.Principal, e ento uma instncia
do conjunto de principals podem representar um grupo lgico de
outros grupos de principals ou grupos de principals.
24/04/04 01:51:39
jp@psique.org http://www.psique.org/cursos

291

Segurana

Curso J150

Autenticao de um Subject
A autenticao de um Subject requer um login no JAAS. O
procedimento de login consite dos seguintes passos:
1. Uma aplicao instancia um LoginContext passando o nome da
configurao de login e um CallbackHandler para popular os
objetos Callback obrigatrios pela configurao de
LoginModules.
2. O LoginContext consulta o Configuration para carregar todos
os LoginModules includos na configurao de login selecionada.
Se nenhum nome de configurao existir a configurao other
usada como default
3. A aplicao invoca o mtodo LoginContext.login.
4. O mtodo de login invoca todos os LoginModules carregados.
Como cada LoginModule tenta autenticar o Subject, el einvoca
um mtodo handle no CallbackHandler associado para obter as
informaes requeridas pelo processo de autenticao. As
informaes so passadas ao mtodo handle na forma de um
array de objetos Callback. Tendo sucesso, o LoginModule associa
os Principals relevantes e as credenciais com o Subject.
5. O LoginContext retorna o status de autenticao para a
aplicao. O sucesso representado pelo retorno de um mtodo
login. A falha representada pelo lanamento de uma
LoginException lanada pelo mtodo login.
6. Se a autenticao tiver sucesso, a aplicao recupera o Subject
autenticado usando o mtodo LoginContext.getSubject.
7. Depois que a autenticao do Subject estiver completa. Todos os
Principals e informaes relacionadas com o Subject pelo
mtodo de login podem ser removidas invocando o mtodo
LoginContext.logout.
A classe LoginContext prov os mtodos bsicos para autenticar os
Subjects e oferece um meio de desenvolver uma aplicao
independentemente da tecnologia utilizada para autenticao. O
LoginContext consulta um objeto Configuration para determinar
24/04/04 01:51:41
jp@psique.org http://www.psique.org/cursos

292

Segurana

Curso J150

os servios de autenticao configurados para uma aplicao. As


classes LoginModules representa o servio de autenticao. Mas
voc sempre pode inserir diferentes LoginModules em uma
aplicao sem mudar a aplicao.
Abaixo o processo de autenticao na perspectiva da aplicao:
CallbackHandler handler = new MyHandler();
LoginContext lc = new LoginContext(alguma configuracao,
handler);
try {
lc.login();
Subject subject = lc.getSubject();
}
catch(LoginException e)
{
System.out.println(Autenticao falhou!!!);
e.printStackTrace();
}
// Executa o trabalho como um Subject autenticado
...
// O trabalho est completo, execute o logout para
// remover a informao de autenticao.
Try {
lc.logout();
}
catch(LoginException e)
{
System.out.println(Falhou no logout);
e.printStackTrace();
}
// Um exemplo de classe Handler
class MyHandler implements CallbackHandler
{
public void handle(Callback[] callbacks) throws
IOException, UnsupportedCallbackException
{
for(int i = 0; i < callbacks.length; i++)
{
if(callbacks[i] instanceof NameCallback)

24/04/04 01:51:43
jp@psique.org http://www.psique.org/cursos

293

Segurana

Curso J150

{
NameCallback nc = (NameCallback) callbacks[i];
nc.setName(username);
}
else if (callbacks[i] instanceof PasswordCallback)
{
PasswordCallback pc =
(PasswordCallback) callbacks[i];
pc.setPassword(password);
}
else
{
throw new UnsupportedCallbackException(
callbacks[i],
Callback desconhecido);
}
}
}
}

A integrao com a tecnologia de autenticao feita criando uma


implementao da interface LoginModule. Isto permite que
diferentes tecnologias de autenticao possam ser plugadas em um
aplicao pelo administrador. Mltiplos LoginModules podem ser
encadeados para permitir que mais de uma tecnologia de
autenticao faa parte do processo de autenticao. Por exemplo,
um LoginModule pode executar uma autenticao baseada em
nome e senha, outra pode utilizar um hardware como um leitor de
smart card ou algum sistema biomtrico de autenticao. O ciclo de
vida de um LoginModule controlado pelo objeto LoginContext
atravs do qual o cliente cria e usa o mtodo login. O processo
consiste em duas fases:
1. O LoginContext cria cada LoginModule configurado usando seu
construtor pblico sem argumentos.
2. Cada LoginModule inicializado com uma chamada ao seu
mtodo initialize. Os argumentos Subject no deve ser nulo.
A assinatura do mtodo initialize :
public void initialize(Subject subject, CallbackHandler
handler, Map sharedState, Map options);
24/04/04 01:51:45
jp@psique.org http://www.psique.org/cursos

294

Segurana

Curso J150

3. O mtodo login ento chamado para iniciar o processo de


autenticao. Um exemplode implementao do mtodo pode
pediar o nome do usurio e a senha e ento verificar as
informaes em dados guardados em um servio de nomes tais
como NIS ou LDAP. Alternativamente implementaes podem
utilizar smart cards, dispositivos biomtricos ou simplesmente
extrair as informaes do usurio do sistema operaciona. A
validao da identidade do usurio por cada LoginModule
considerada a fase 1 da autenticao JAAS. A assinatura do
mtodo login :
boolean login() throws LoginException;
A falha indicada pelo lanamento de uma LoginException. Um
retorno de true indica sucesso, um retorno de falso indica que o
mdulo deve ser ignorado.
4. Se os LoginContext tiverem sucesso, o mtodo commit
invocado para cada LoginModule. Se a fase 1 tiver sucesso para
um LoginModule, ento o mtodo commit continua com a fase 2:
associando os Principals, credenciais pblicas, ou credenciais
privadas com o Subject. Se a fase 1 falhar para um LoginModule,
ento o commit remove qualquer informao previamente
guardada do estado da autenticao tais como nomes de usurios
e senhas. A assinatura do mtodo commit :
boolean commit() throws LoginException;
Falha para completar a fase de commit indicada lanando uma
LoginException. Retorno verdadeiro indica sucesso, falso indica
que o modulo deve ser ignorado.
5. Se a autenticao do LoginContext falhar, ento o mtodo abort
ser chamado em cada LoginModule. O mtodo abort remove
qualquer estado da autenticao criado pelos mtodos login ou
initialize. A assinatura :
boolean abort() throws LoginException;
Falha para completar a fase de abortamento indicada lanando
uma LoginException. O retorno com verdadeiro indica que o
mtodo foi bem sucedido, enquando um retorno false indica que o
mdulo de login deve ser ignorado.
6. A remoo do estado da autenticao depois de um login com
sucesso feita quando a aplicao invocar o mtodo logout no
LoginContext. Isto resulta na chamada o mtodo logout em cada
LoginModule. O mtodo logout remove remove as credenciais
24/04/04 01:51:47
jp@psique.org http://www.psique.org/cursos

295

Segurana

Curso J150

de todos os Principals e credenciais originalmente associadas


com o Subject durante a operao de commit. As credenciais
devem ser destrudas antes de remov-las. A assinatura do
mtodo logout :
boolean logout() throws LoginException;
Falha no processo de logout indicada pelo lanamento de uma
exceo LoginException. Um retorno verdadeiro indica que o
mtodo teve sucesso, enquanto um retorno falso indica que o
mdulo deve ser ignorado.
Quando um LoginModule precisar se comunicar com um usurio
para obter informaes de autenticao, ele usa um objeto
CallbackHandler. Aplicaes implementam a interface
CallbackHandler e passam-na no LoginContext o qual repassa-a
diretamente para o LoginModules. LoginModules usam o
CallbackHandler para receber entradas de usurios, tais como
password ou nmeros de PIN. A interface CallbackHandler tem um
mtodo a implementar:
void handle (Callback[] callbacks)
throws java.io.IOException, UnsupportedCallbackException;

Informaes adicionais sobre JAAS podem ser encontradas em:


http://java.sun.com/products/jaas/

Autorizao
Uma vez que o cliente esteja autenticado, ele precisa passar pelo
teste de autorizao para chamar os mtodos de seus beans. Esta
autorizao est definida nas polticas de segurana (security
24/04/04 01:51:49
jp@psique.org http://www.psique.org/cursos

296

Segurana

Curso J150

policies) dos beans. Existem duas maneiras de efetuar autorizao


com EJB:
Quando voc tem uma aplicao standalone se conectando a um
servidor EJB remoto, o usurio deve suprir as credencias para a
aplicao (ou talvez a prpria aplicao recuperar as credencias de
outro sistema). A aplicao standalone deve usar a API JAAS para
autenticar o usurio antes de chamar os componentes EJB no
Application Server. O application server deve verificar as
credenciais do usurio. Uma vez que o usurio estiver autenticado
via JAAS, o cliente pode chamar os mtodos EJB de forma segura, e
a identidade de segurana do usurio ser propagada para o
servidor nas invocaes de mtodos.
Quando voc estiver utilizando um browser como cliente que se
conecta a um servlet ou JSP, o web browser do usurio informa os
credenciais para uma camada servlet/JSP, e a camada servlet/JSP
pode usar JAAS para autenticar o usurio. O browser Web pode
informar as credencias de uma das quatro maneiras a seguir:

Basic authentication.
O cliente Web informa um nome de usurio e senha para o servidor
Web. O servidor verifica estas credenciais no repositrio de
usurios e senhas. Note que apesar de ser uma forma simples de
checar no uma forma segura pois a senha mandada aberta para
o servidor. Alguns servidores J2EE admitem que voc utilize SSL
para encriptar estes dados.

Form-based authentication
Igual basic authentication, exceto que a aplicao utiliza um form
customizado em uma tela de login.

24/04/04 01:51:51
jp@psique.org http://www.psique.org/cursos

297

Segurana

Curso J150

Digest authentication
O cliente Web informa um digest para o Web server. Este digest
uma transformao matemtica da password e da mensagem. A
senha no enviada para o Servidor. O Servidor ento tenta
reproduzir a mensagem efetuando a mesma transformao que foi
feita no cliente, exceto que desta vez o Servidor usa uma copia
segura da password do cliente mantida em camada de persistncia.
Se o digest conferir, o usurio est autenticado.

Certificate authentication
O cliente Web pode informar um certificada padro X.509 para
provar sua identidade. O cliente pode (opcionalmente) assegurar
que o servidor quem ele imagina recebendo o certificado X.509
que autentica o servidor (autenticao mtua).

De forma programtica
Voc codifica no cdigo do bean. Sua regra de negcio integrada
com regras de segurana.

De forma declarativa
O continer faz a autorizao para voc. Voc declara como a
autorizao deve ser feita no deployment descriptor e o continer
faz todas as checagens de segurana necessrias. Voc
efetivamente delega a autorizao para o continer EJB.

Viso geral segurana declarativa


O modelo de segurana utilizado na especificao J2EE um
modelo declarativo. com declaraes que voc descreve os papis
de segurana e permisses usando descritores XML. Com isto voc
24/04/04 01:51:52
jp@psique.org http://www.psique.org/cursos

298

Segurana

Curso J150

no precisa codificar as regras de segurana no interior dos


componentes. Isto isola a segurana do negcio pois a segurana
tende a ser mais uma funo da localizao onde o componente
instalado (em Produo as regras de segurana so diferentes das
regras aplicveis em ambiente de Homologao ou de
Desenvolvimento).
Utiliza-se o deployment descriptor (ejb-jar.xml e web.xml) para
descrever os requisitos de segurana de uma aplicao.

24/04/04 01:51:54
jp@psique.org http://www.psique.org/cursos

299

Segurana

Curso J150

Deployment Descriptor ejb-jar.xml especificao EJB 2.0

24/04/04 01:51:56
jp@psique.org http://www.psique.org/cursos

300

Segurana

Curso J150

Parte relacionada a segurana do deployment descriptor previsto na


especificao 2.2 de Servlet.

Referncias de segurana
Em ambos, EJBs e servlets podem ser declarados um ou mais
elementos do tipo security-role-ref. uma ligao de um papel
local para o componente com um papel da aplicao. Este
elemento usado para declarar que um componente est usando o
valor de um role-name (papel) como argumento para o mtodo

24/04/04 01:51:58
jp@psique.org http://www.psique.org/cursos

301

Segurana

Curso J150

isCallerInRole(String). Usando o mtodo isCallerInRole, um


componente pode verificar se o requisitante est no papel que foi
declarado no elemento security-role-ref/role-name. O valor do
elemento role-name precisa ser ligado ao elemento security-role
atravs de um elemento role-link. O usu tpico de isCallerInRole
para verificar alguma verificao de segurana que no pode ser
feita utilizando elemento method-permissions. O uso de
isCallerInRole no recomendado porque o resulta em insero da
lgica de segurana no cdigo do componente.
Aqui um ejb-jar.xml como exemplo:
<!-- exemplo de ejb-jar.xml -->
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>UmSessionBean</ejb-name>
...
<security-role-ref>
<role-name>OPapelAChecar</role-name>
<role-link>OPapelDaAplicacao</role-link>
</security-role-ref>
</session>
</enterprise-beans>
...
</ejb-jar>

Aqui um exemplo de web.xml


<!-- Um exemplo de web.xml -->
<web-app>
<servlet>
<servlet-name>UmServlet</servlet-name>
...
<security-role-ref>
<role-name>OPapelParaOServlet</role-name>
<role-link>OPapelDaAplicacao</role-link>
</security-role-ref>
</servlet>
...
</web-app>

24/04/04 01:52:00
jp@psique.org http://www.psique.org/cursos

302

Segurana

Curso J150

Identidade de Segurana
EJBs podem opcionalmente declarar um elemento security-identity.
novo em EJB 2.0 a capacidade de especificar qual identidade um
EJB deve usar quando ele invoca mtodos em outros componentes.
A identidade de invocao pode ser aquela que o usurio atual tem,
ou um papel especfico. O application assembler usa o elemento
security-identity com um elemento filho use-caller-identity para
indicar que a identidade do usurio correto deve ser propagada
como uma identidade de segurana para os mtodos invocados
feitos pelo continer EJB. Propagao da identidade do requisitante
usada por default na ausncia de uma declarao especfica de
um elemento security-identity.
Alternativamente, o application assembler pode user um elemento
filho run-as/role-name para especificar que um papel de segurana
especfico dado pelo valor de role-name deve ser utilizado como
identidade de segurana para a invocao do mtodo chamada pelo
EJB. Note que isto no muda a identidade do chamador (por
exemplo numa chamada de EJBContext.getCallerPrincipal()). No
lugar disto, os papis de segurana do chamador so configurados
para um nico papel especificado pelo valor do elemento runas/role-name. Um possvel uso para o elemento run-as para evitar
que clientes externos acessem EJBs internos. isto feito atribuindo
aos EJBs internos, elementos method-permission que restringe o
acesso a papeis que nunca sero atribudos a clientes externos.
EJBs que precisam usar EJB internos so ento configurados com
run-as/role-name apontando para o papel restrito aos componentes
internos.
Exemplo de descritor:
<!-- Um exemplo de ejb-jar.xml -->
<ejb-jar>
<enterprise-beans>
<sesion>
<ejb-name>UmSessionBean</ejb-name>
...
<security-identity>
<use-caller-identity/>
24/04/04 01:52:01
jp@psique.org http://www.psique.org/cursos

303

Segurana

Curso J150

</security-identity>
</session>
<sesion>
<ejb-name>ExecutarComoBean</ejb-name>
...
<security-identity>
<run-as>
<description>Um papel privado interno</description>
<role-name>PapelInterno</role-name>
</run-as>
</security-identity>
</session>
...

A especificao Servlets 2.3 tambm tem esta funcionalidade.

Papis de segurana (Security roles)


Um papel de segurana (security-role) referenciado pelos elementos
security-role-ref ou security-identity precisam ser mapeados para
um dos papis de segurana declarados na aplicao. Um
application assembler define papis lgicos de segurana
declarando elementos security-role. O valor do elemento role-name
um papel lgico para a aplicao, podem ter valores como: Amin,
Administrador, Administrator, Architect, Vendas, etc...

O que um papel (role)? A especificao J2EE ressalta que


importante manter em mente que um papel de segurana no
deployment descriptor so usados para definir uma viso de
segurana lgica para uma aplicao. Papis definidos no
deployment descriptor de J2EE no devem ser confundios com o de
grupos de usurios (user groups), users, principals, e outros
conceitos que existem no ambiente operacional da Corporao. Os
papis do deployment descriptor so definidos para a aplicao e o
domnio a aplicao. Uma aplicao de banco pode usar nomes de
papis como Gerente, Cliente, GerenteDeContas, Tesoureiro, etc.
24/04/04 01:52:03
jp@psique.org http://www.psique.org/cursos

304

Segurana

Curso J150

No JBoss um security-role apenas utilizado para mapear os valores


do elemento security-role-ref/role-name para o nome lgico que o
componente referencia. Os papis atribudos a usurios so uma
funo dinmica do gerenciamento de segurana da aplicao.
JBoss no requer que a definio dos security-roles para a
declarao das permisses dos mtodos. Mas a especificaes de
elementos security-role uma boa prtica para assegurar
portabilidade entre application servers e para a manuteno dos
deployment descriptors.
Exemplo de um fragmento que ilustra o uso de security-role
<!-- exemplo de ejb-jar.xml --.
<ejb-jar>
...
<assembly-descriptor>
<security-role>
<description>O nico papel da aplicao</description>
<role-name>OPapelDaAplicacao</role-name>
</security-role>
</assembly-descriptor>
</ejb-jar>
<!-- exemplo de web.xml -->
<web-app>
...
<security-role>
<description>O nico papel da aplicao</description>
<role-name>OPapelDaAplicacao</role-name>
</security-role>
</web-app>

Permisso para execuo de mtodos EJB


Um application assembler pode configurar papis que so
habilitados a invocar mtodos da interface home e remote atravs
da declaraa de elementos method-permission. Cata elemento
method-permission contm um ou mais elementos filhos role-name
24/04/04 01:52:05
jp@psique.org http://www.psique.org/cursos

305

Segurana

Curso J150

que definem os papis lgicos que esto autorizados a acessar os


mtodos do EJB identificados pelo elemento method. Voc pode
especificar um elemento unchecked no lugar de um role-name para
declarar que um usurio no autenticado pode acessar este mtodo
identificado pelos elementos method. Adicionalmente, voc pode
declarar que algum no tem acesso ao mtodo utilizando o elemtno
exclude-list. Se um EJB tem mtodos que no foram declarados
acessveis por um papel usando o elemento method-permission, o
metodo por default ser excludo do uso. Isto equivalente a deixar
como default os methos na tag exclude-list.

Existem tres estilos suportados para declarao do elemento


method.
Estilo 1, usado para referenciar todos os mtodos do componente.
<method>
<ejb-name>NomeEJB</ejb-name>
<method-name>*</method-name>
</method

Estilo 2, usado para referenciar um mtodo especfico do EJB. Se


existirem muitos mtodos com o mesmo nome, com vrios
overloads.
<method>
<ejb-name>NomeEJB</method-name>
<method-name>Metodo</method-name>
</method>

Estilo 3, usado para especificar um mtodo com uma assinatura


(nome + parmetros). deve ser definido na interface home ou
remote. Os valores do elemento method-param devem ser nomes
qualificados correspondendo ao tipo dos parmetors. Se existirem
vrios mtodos com o mesmo nome, a permisso aplicvel ao que
conferir exatamente com a lista de parmetros.

24/04/04 01:52:07
jp@psique.org http://www.psique.org/cursos

306

Segurana

Curso J150

<method>
<ejb-name>NomeEJB</ejb-name>
<method-name>metodo</method-name>
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</method>

Um elemento opcional method-intf pode ser utilizado para


diferenciar mtodos com o mesmo nome e e assinatura que esto
definidos na interface home e na remote de um EJB.
Exemplo de method-permission:
<ejb-jar>
<assembly-descriptor>
<method-permission>
<description>O empregado e o empregado temporario
podem acessar qualquer metodo do bean
EmpregadoService
</description>
<role-name>empregado</role-name>
<role-name>empregado-temporario</role-name>
<method>
<ejb-name>EmpregadoService</ejb-name>
<method-name>*</method-name>
</method>
</method-permision>
<method-permission>
<description>O papel de empregado pode acessar
findByPrimaryKey, getEmpregadoInfo e
updateEmpregadoInfo(String) do Bean
Pagamentos
</description>
<role-name>empregado</role-name>
<method>
<ejb-name>Pagamentos</ejb-name>
<method-name>findByPrimaryKey</method-name>
</method>
<method>
24/04/04 01:52:10
jp@psique.org http://www.psique.org/cursos

307

Segurana

Curso J150

<ejb-name>Pagamentos</ejb-name>
<method-name>getEmpregadoInfo</method-name>
</method>
<method>
<ejb-name>Pagamentos</ejb-name>
<method-name>updateMpregadoInfo</method-name>
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</method>
</method-permission>
<method-permission>
<description>O papel do admin</description>
<role-name>admin</role-name>
<method>
<ejb-name>EmpregadoAdmin</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<method-permission>
<description>Liberado para todos</description>
<unchecked/>
<method>
<ejb-name>EmpregadoHelp</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<exclude-list>
<description>Nenhum mtodo com o nome
despedirOCheve do bean
DespedirEmpregado
pode ser usada neste deployment
</description>
<method>
<ejb-name>DespedirEmpregado</ejb-name>
<method-name>despedirOChefe</method-name>
</method>
</exclude-list>
</assembly-descriptor>
</ejb-jar>

24/04/04 01:52:13
jp@psique.org http://www.psique.org/cursos

308

Segurana

Curso J150

Segurana na WEB
Em uma aplicao Web, a segurana definida pelos papis
habilitados a acessar o contedo de um padro de URL (URL
Pattern) que identifica o contedo protegido. Este conjunto de
informaes declarado usando o arquivo web.xml com o elemtno
security-constraint. O contedo a ser seguro declarado usando um
ou mais elemtnos web-resource-collection. Cada elemento webresource-collection contm uma srie de elementos url-pattern
seguidos por uma srie opcional de elementos http-method. O valor
do elemento url-pattern especifica o padro da URL que precisa
combinar com o padro da requisio. O elemento http-method
especifica o tipo de requisio HTTP permitido.
O elemento opcional user-data-constraint especifica os requisitos
para a camada de transporte da conexo entre cliente e servidor.
Estes requisitos podem ser com relao integridade do contedo
(evitando que os dados sejam corrompidos no processo de
comunicao) ou para confidencialidade (prevenindo que sejam
lidos durante o trncito). O elemento transport-guarante especifica
o grau no qual a comunicao entre cliente e servidor deve ser
protegida. Os valores so: NONE, INTEGRAL ou CONFIDENTIAL. O
valor NONE significa que a aplicao no requer qualquer garantia
no transporte. O valor INTEGRAL significa que a aplicao requer
que os dados enviados entre o cliente e o servidor sejam enviados
de forma que no possam ser mudados no trnsito. O valor
CONFIDENTIAL significa que a aplicao requer que os dados
sejam transmitidos de forma a prevenir que sejam observados
durante a transmisso. Na maioria dos casos, a presena de
INTEGRAL ou CONFIDENTIAL indica que o uso de SSL requerido.
O elemento opcional login-config usado para configurar o mtodo
de autenticao que deve ser utilizado, a lista de nomes (realm) que
deve ser utilizada por esta aplicao e os atributos que so
necessrios pelo mecanismo de login. O elemento filho auth-method
especifica o mecanismo de autenticao para a aplicao Web.
Como um prerequisito para acessar qualquer recurso Web que se
24/04/04 01:52:15
jp@psique.org http://www.psique.org/cursos

309

Segurana

Curso J150

encontra protegido na aplicao Web, o usurio deve estar


autenticado usando o mecanismo configurado. Os valores para authmethod so: BASIC, DIGEST, FORM ou CLIENT-CERT. O elemento
filho realm-name especifica que o realm-name que ser utilizado
nas autorizaes HTTP BASIC e DIGEST. O elemento filho formlogin-config especifica as pginas para login e as pginas de erro
que devem ser utilizadas em form-based login. Se o valor do authmethod no FORM, form-login-config e todos os elementos filhos
sero ignorados.
O exemplo abaixo indica que qualquer URL que se situar abaixo do
caminho /restrita na aplicao requer um papel
UsuarioAutorizado. No requerido garantia de transporte e o
metodo de autenticao usado para obter a identidade do usurio
BASIC HTTP authentication.
<web-app>
...
<security-constraint>
<web-resource-collection>
<web-resource-name>Conteudo Seguro</web-resource-name>
<url-pattern>/restrita/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>UsuarioAutorizado</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NOME</transport-guarantee>
</user-data-constraint>
</security-constraint>
...
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Area Restrita</realm-name>
</login-config>
...
<security-role>
<description>O papel requerido para acessar o contedo
restrito
</description>
<role-name>UsuarioAutorizado</role-name>
24/04/04 01:52:16
jp@psique.org http://www.psique.org/cursos

310

Segurana

Curso J150

</security-role>
</web0-app>

Habilitando a Segurana Declarativa no


JBoss
Os elementos de segurana de J2EE vistos at agora descrevem
apenas os requisitos de segurana da perspectiva da aplicao.
Uma vez que os elementos de J2EE so papis lgicos, o application
deployer mapeia estes papis do domnio da aplicao no ambiente
onde estar instalada a aplicao. A especificao omite as
especificas dependentes de servidor.

24/04/04 01:52:18
jp@psique.org http://www.psique.org/cursos

311

Segurana

Curso J150

Elementos de segurana do jboss.xml e e do jboss-web.xml


O mdulo utilizado, estar configurado no arquivo login-config.xml
do diretrio conf do JBoss. A forma mais simples de utilizar usar o
24/04/04 01:52:20
jp@psique.org http://www.psique.org/cursos

312

Segurana

Curso J150

mdulo UsersRolesLoginModule
(org.jboss.security.auth.spi.UsersRolesLoginModule) ele suporta
mltiplos usurios e papis e e baseado em dois arquivos Java
Poperties. Um deles chamado user.properties e mapeia usurio
a senha (usuario=senha), o outro chamado roles.properties
mapeia usurios a papeis. Os arquivos de properties so carregados
durante a inicializao usando o mtodo initialize da thread do class
loader do contexto. Isto significa que estes arquivos podem ser
colocados no jar de deployment do J2EE, no diretrio de
configurao do JBoss ou em qualquer diretrio includo no JBoss
do servidor. O principal propsito deste mdulo simplicidade para
testes de segurana.
O arquivo users.properties utiliza um formato usuaro=senha onde
cada entra de usurio separada por uma linha
usuario1=senha1
usuario2=senha2

O arquivo roles.properties usa o formato


usuario=papel1,papel2,... com um valor de nome de grupo
opcional.
usuario1=papel1,papel2
usuario1.PapelGrupo1=papel3,papel4,papel5
usuario2=papel1,papel4

Oformato usuario1.PapelGrupo1 usado para atribuir ao usurio


papis para um grupo de usurios onde PapelGrupo1 o nome do
grupo. O formato usuario=... uma forma abreviada de
usuario.Roles=..., onde o grupo Roles o grupo padro esperado
pelo JaasSecurityManager que contm papis que definem as
permisses de usurio:
As duas linhas abaixo so equivalentes:
jp=administrador,gerente
24/04/04 01:52:21
jp@psique.org http://www.psique.org/cursos

313

Segurana

Curso J150

jp.Roles=administrador,gerente

As configuraes para este mdulo de login so:


unautehticatedIdentify=name, define o nome que ser utilizado
quando o request no tiver informaes de autenticao. Pode ser
usado para permitir que servlets desprotegidos chamem mtodos
desprotegidos de EJBs que no requerem nenhum papel.

24/04/04 01:52:23
jp@psique.org http://www.psique.org/cursos

314

Transaes

Curso J150

Transaes
JTA Java Transaction API

Definio de Transao
Podemos definir uma transao como sendo uma unidade de
trabalho contendo uma ou mais operaes envolvendo um ou mais
recursos compartilhados tendo as propriedades ACID. ACID
significa Atomicidade, Consistncia, Isolamento e Durabilidade.
Uma transao uma unidade de trabalho, pode ser composta por
vrias operaes. No final a transao commitada se tudo der
certo. Se alguma operao intermediria falhar, tudo deve ser
desfeito e o estado, na medida do possvel, deve voltar a ser o do
incio da transao.

Estado inicial

Transao

Desfazimento (Roll-Back)

Falha

Sucesso

Estado final
Transao
efetivada

Atomicidade
Uma transao precisa ser atmica, ou seja indivisvel. Ou toda a
transao efetuada ou nada feito. Com isto no possvel que
apenas uma parte da transao seja feita. Em uma transferncia de
contas, o que se deseja : ou se faz o saque e o depsito ou no se
faz nada.

Consistncia
Quando uma transao termina, o sistema deve estar em um estado
24/04/04 01:52:25
jp@psique.org http://www.psique.org/cursos

315

Transaes

Curso J150

estvel e consistente.

Isolamento
Diferentes transaes deve ser isoladas umas das outras. Isto
significa que trabalho parcial feito em uma transao no pode ser
visto por outras at que a transao efetivada (comitada), e cada
processo em um sistema multi-usurio pode ser programado como
se fosse o nico processo acessando o sistema.

Durabilidade
As mudanas feitas durante uma transao sero feitas persistentes
quando a transao for efetivada (comitada).
Para exemplificar estes conceitos imagine uma transao para
efetuar a transferncia de fundos entre duas contas bancrias. A
transferncia envolve retirar o dinheiro de uma das contas e
depositar na outra.
S nos interessa o conjunto inteiro, saque + depsito, o sistema
ficaria inconsistente se somente uma das pernas da transao
fosse executada, isto explicita a atomicidade da transao, no
possvel dividi-la.
A consistncia significa que aps a transao a soma de ambos os
saldos deve continuar igual, ou seja, uma conta foi debitada em x, a
outra creditada em x, ento o total dos saldos deve permanecer
idntico.
O isolamento importante pois a nossa transao no pode sofrer
efeitos colaterais de outras transaes, imagine que para fazer o
saque da primeira conta temos um brevssimo intervalo de tempo
onde problemas podem ocorrer. Primeiro obtemos o saldo, depois
diminumos o valor, e em um terceiro passo atualizamos o valor do
24/04/04 01:52:27
jp@psique.org http://www.psique.org/cursos

316

Transaes

Curso J150

saldo, nenhuma outra transao deve conseguir alterar o saldo aps


termos obtido o valor e antes de persistirmos o valor atualizado!
A durabilidade evidente pois aps feita a transferncia, o saldo
das duas contas deve permanecer com o saldo final.

Locking pessimista e otimista


O isolamento transacional usualmente implementado atravs de
locking (travamento de recurso). Existe duas formas de utilizar o
locking transacional: Lock pessimista e lock otimista.
A desvantagem do lock pessimista que o recurso reservado
desde o momento do primeiro acesso em uma transao at o
momento que a transao finalizada, tornando-o indisponvel a
qualquer outra transao durante este tempo.
Se a maioria das transaes simplesmente travassem os recursos e
nunca os mudassem, um lock exclusivo pode ser desperdcio de
recursos, e locks utilizando estratgia otimista podem ser melhores.
No caso da transferncia acima, interessante que as duas contas
sejam travadas durante a transao, se outras transaes
precisarem utilizar um recurso que est em lock, a transao dever
esperar um tempo at que o recurso seja efetivada (commit) ou que
o processo seja desfeito (roll back), ou seja, o lock existe at que a
transao seja efetivada (commited) ou desfeita (rolled back).
Com estratgia otimista, um recurso no travado quando
acessado pela primeira vez, o estado do recurso salvo, durante a
transao outras transaes podem acessar o recurso
concorrentemente sem problemas. No momento da efetivao,
quando o recurso estiver para ser atualizado de forma persistente, o
estado do recurso novamente lido e comparado com o estado salvo
inicialmente. Se os dois estados no forem iguais, est para ser feita
uma alterao conflitante, e por isto a transao desfeita (roll
24/04/04 01:52:28
jp@psique.org http://www.psique.org/cursos

317

Transaes

Curso J150

back).
Na transferncia, o saldo salvo no incio, se antes de atualizar o
saldo o sistema notar que o saldo foi alterado, a transao vai falhar
e vai ser feito o desfazimento. Caso contrrio, o saldo final ser
salvo.

Componentes de uma transao distribuda


Existem vrios participantes em transaes distribudas. Incluem:

Transaction Manager(gerenciador de transao): Este


componente distribudo pelo sistema transacional. Ele gerencia
e coordena o trabalho envolvido nas transaes. O transaction
manager exposto pela interface
javax.transaction.TransactionManager de JTA.

Transaction Context (contexto da transao): Um contexto de


transao identifica uma transao em particular. Em JTA a
interface correspondente javax.transaction.Transaction.

Transaction Client (cliente da transao): Um cliente de


transao pode invocar operaes em um ou mais objetos
transacionais em uma nica transao. O cliente transacional que
inicia a transao chamado de transaction originator
(originador da transao). Um cliente de transao tambm um
usurio explcito ou implcito das interfaces de JTA.

Transactional Object (Objeto transacional): o objeto que tem o


comportamento afetado pelas operaes efetuadas com ele
dentro de um contexto transacional. Um objeto transacional pode
ser um cliente transacional. A maioria dos EJBs so objetos
transacionais.

Recoverable Resource (Recurso recupervel): um objeto


transacional cujo estado salvo se a transao for efetivada, e
cujo estado pode voltar ao do incio da transao se a transao

24/04/04 01:52:30
jp@psique.org http://www.psique.org/cursos

318

Transaes

Curso J150

sofrer um roll back. No momento da efetivao, o transaction


manager utiliza o protocolo two-phase XA para se comunicar com
todos os recoverable resources para se certificar da integridade
da transao. Um recurso recupervel representado utilizando
a interface de JTA javax.transaction.xa.XAResource.

O protocolo two-phase XA
Quando a transao est para ser efetivada, responsabilidade do
transaction manager ter certeza que tudo ser efetivado ou tudo
ser desfeito.
Quando muitos recursos estiverem envolvidos em uma transao, o
gerenciamento do commit fica mais complicado. No basta pedir
que cada recurso efetive suas alteraes, pois alguns podem
conseguir e outros no.
O protocolo two-phase XA utilizado para isto. O protocolo XA
acrescenta uma fase de preparao antes da fase de commit. Antes
de solicitar a efetivao das mudanas, o transaction manager pede
que cada recurso envolvido se prepare para o commit. Quando o
recurso sinalizar que est preparado para o commit da transao.
Ento a primeira fase consiste em solicitar aos recursos que fazem
parte da transao que se preparem para o commit. Se algum falhar
na preparao a transao ser desfeita. Mas se todos os recursos
sinalizarem que esto prontos para o commit, a segunda fase do
protocolo XA comea. A segunda fase quando o transaction
manager manda que cada um dos recursos efetivem a transao.
Como todos j sinalizaram que estavam preparados, este passo no
deve falhar.

Excees heursticas
Heurstica o mtodo de ensino que consiste em que o educando

24/04/04 01:52:32
jp@psique.org http://www.psique.org/cursos

319

Transaes

Curso J150

chegue verdade por seus prprios meios.


Em um ambiente distribudo, falhas de comunicao podem ocorrer
a qualquer momento. Se a comunicao entre o transaction
manager e um recurso no for possvel durante um perodo de
tempo, o recurso pode decidir unilateralmente efetivar ou desfazer
as mudanas feitas no contexto da transao. Esta deciso
chamada de deciso heurstica. um dos piores erros que podem
ocorrer
em um sistema transacional, pois pode levar a parte da transao
ser efetivada e parte ser desfeita, o que viola a atomicidade das
transaes e pode levar a corrupo dos dados.
Por causa do perigo das excees heursticas, um recurso que toma
uma deciso heurstica precisa manter todas as informaes sobre a
deciso em armazenamento persistente at que o transaction
manager diga que ele pode esquecer da deciso tomada. Os dados
atuais das decises heursticas que esto salvos em armazenamento
persistente dependem do tipo de recurso e no so padronizados. A
idia que um gerente de sistema possa olhar os dados, e
possivelmente modificar o recurso para corrigir problemas de
integridade que venham a acontecer.

Identificadores de transaes e ramificaes


(branches)
Em JTA, a identificao das transaes encapsulada em objetos
que implementam a interface javax.transaction.xa.Xid. O ID da
transao uma agregao de trs partes:

O identificador de formato diz a qual familia de transaes


pertence e como as outras duas partes devem ser interpretadas

O identificador global de transao, um identificador global


dentro de uma famlia

24/04/04 01:52:34
jp@psique.org http://www.psique.org/cursos

320

Transaes

Curso J150

O qualificador de ramificao identifica um ramo de uma


transao global

Os ramos de transaes so utilizados para identificar diferentes


partes de uma mesma transao global. A cada vez que o
transaction manager envolve na transao um novo recurso,
criada uma nova ramificao para a transao.

Suporte a transaes de usurio


A interface de JTA javax.transaction.UserTransaction permite que as
aplicaes explicitamente controle as transaes. Para EJB do tipo
session beans que gerenciam a transao por s (BMT Bean
Managment Transaction), um UserTransaction pode ser obtido
chamando o mtodo getUserTransaction no contexto do bean
javax.ejb.SessionContext.
O controle de transaes em J2EE basicamente a demarcao de
transaes, ou seja, o ponto inicial e o ponto final da transao. As
transaes podem ser delimitadas pelo cliente e propagadas para os
compoentes, alm disso, podem ser demarcadas no servidor.
Quando so no servidor, podem ser de forma implcita (controlada
pelo continer) atravs de declaraes no deployment descriptor ou
nos beans, explicitamente.

Controle explcito de transaes


Para se conseguir controlar explicitamente as transaes, devemos
sinalizar ao continer que o nosso bean estar utilizando BMT
(Bean-Managed Transaction), fazemos isto informando no
deployment descriptor:
<transaction-type>Bean</transaction-type>

24/04/04 01:52:36
jp@psique.org http://www.psique.org/cursos

321

Transaes

Curso J150

No cdigo, teremos que utilizar uma api para demarcar o incio e o


fim das transaes: JTA, JDBC ou JMS (melhor utilizar JTA):

Mtodos de Connection (java.sql)

Mtodos de QueueSession ou TopicSession (javax.jms)

Mtodos de UserTransaction (javax.transaction)

Exemplo com JDBC:


...
public void compra (String codProduto,
String codOrdem,
int quantidade) {
try {
con.setAutoCommit(false); // con java.sql.Connection
updateItemOrdem(codProduto, codOrdem);
updateInventario(codProduto, quantidade);
con.commit();
} catch (Exception e) {
try {
con.rollback();
throw new EJBException(Erro na transao+e);
} catch (SQLException sqx) {
throw new EJBException(Falhou rollback + sqx);
}
}
}

Exemplo com JTA:


...
public void saque(double valor) {
UserTransaction ut = sessionCtx.getUserTransaction();
try {
double estado = saldoMaquina;
ut.begin();
updateValor(valor);
saldoMaquina -= valor;

24/04/04 01:52:38
jp@psique.org http://www.psique.org/cursos

322

Transaes

Curso J150

insertMaquina(saldoMaquina);
ut.commit();
} catch (Exception ex) {
try {
ut.rollback();
saldoMaquina = estado;
} catch (SystemException e) {
throw new EJBException(Rollback falhou+e);
}
throw new EJBException(Transao falhou +ex);
}
}

As transaes normalmente terminam no mesmo local onde


comearam. Se uma operao fizer muitas chamadas, a
performance melhorada se estiverem no contexto de uma
transao. O contexto da transao, vai sendo propagado para todos
os mtodos chamados que no iniciarem uma nova transao. Se o
mtodo chamado iniciar uma nova transao, a transao principal
ser suspensa at que o mtodo termine.

Suporte a UserTransaction
A interface javax.transaction.UserTransaction permite aplicao
explicitamente controlar transaes. Para session beans que
gerenciam as transaes por s (BMT), um objeto UserTransaction
pode ser obtido chamando-se o mtodo getUserTransaction no
contexto do bean javax.ejbSessionContext.
Para beans BMT, no utilizar lookups JNDI para se obter a interface
UserTransaction. Fazer isto viola a especificao de EJB e o objeto
UserTransaction retornado no tem os acessos que o continer EJB
precisa para fazer checagens importantes.
Para usar a interface UserTransaction em outros lugares, o Mbean

24/04/04 01:52:40
jp@psique.org http://www.psique.org/cursos

323

Transaes

Curso J150

org.jboss.tm.usertx.server.ClientUserTransactionService precisa ser


configurado e iniciado. Este Mbean publica uma implementao de
UserTransaction sob o nome JNDI UserTransaction. Este Mbean
configurado por default na distribuio padro do Jboss e no tem
atributos a configurar.

Mtodos de
javax.transaction.UserTransaction:
begin()
Inicia uma nova transao. Esta transao fica associada com a
thread corrente.

commit()
Executa o protocolo de two-phase commit em uma transao
existente associada com a thread corrente. Cada gerenciador de
recurso ir efetivar as alteraes.

getStatus()
Retorna o estado da transao associada com esta thread.

rollback()
Fora o rollback de uma transao associada com a thread corrente.

setRollbackOnly()
A chamada a este mtodo far com que esta transao seja desfeita.

setTransactionTimeout(int)
Indica o mximo tempo em milissegundos que a transao pode
24/04/04 01:52:41
jp@psique.org http://www.psique.org/cursos

324

Transaes

Curso J150

ficar ativa, aps isso ser abortada. importante para evitar


situaes de deadlock.

Constantes
STATUS_ACTIVE
Indica que a transao est ocorrendo e ativa.

STATUS_NO_TRANSACTION
No existe transao no momento

STATUS_MARKED_ROLLBACK
A transao est ocorrendo mas est marcada para ser desfeita. Isto
pode ter sido ocorrido por uma chamda do mtodo setRollbackOnly
();

STATUS_PREPARING
A transao corrente est se preparando para ser efetivada
(durante a fase 1 do protocolo two-phase commit).

STATUS_PREPARED
A transao corrente est preparada para a efetivao (fase 1
completa)

STATUS_COMMITING
A transao corrente est em processo de efetivao. (durante a
fase 2)

24/04/04 01:52:43
jp@psique.org http://www.psique.org/cursos

325

Transaes

Curso J150

STATUS_COMMITED
A transao terminou de efetivar (acabou a fase 2)

STATUS_ROLLING_BACK
A transao corrente est em processo de desfazimento.

STATUS_ROLLEDBACK
A transao corrente terminou o processo de desfazimento.

STATUS_UNKNOWN
O estado da transao corrente no pode ser determinado.

Controle implcito de transaes


Transaes gerenciadas pelo continer (CMT). a forma normal de
gerenciamento de transaes. Transaes gerenciadas pelo
continer no permitem a utilizao de commit() ou rollback() de
java.sql.Connection ou javax.jms.Session dentro do cdigo do
componente. Em entity beans a nica forma de controlar as
transaes.
No deployment descriptor, para especificar que o continer
controlar a transao basta codificar:
<transaction-type>Container</transaction-type>

Feito isto, voc pode definir a poltica de transao para cada um


dos mtodos dos beans.

24/04/04 01:52:45
jp@psique.org http://www.psique.org/cursos

326

Transaes

Curso J150

<assembly-descriptor>
<container-transaction>
<method>...</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
...
</assembly-descriptor>

Exemplo de ejb-jar.xml
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>BancoEJB</ejb-name>
<home>j2eetut.bank.BancoHome</home>
<remote>j2eetut.bank.Banco</remote>
<ejb-class>j2eetut.bank.BancoBean</ejb-class>
<session-type>Stateful</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>BancoEJB</ejb-name>
<method-name>getSaldoPoupanca</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assemby-descriptor>
</ejb-jar>

O elemento <trans-attribute> indica qual ser a poltica de


transaes do mtodo do componente. Os valores possveis so:

NotSupported

Supports

Required

RequiresNew

(preferencial para EJBs)

24/04/04 01:52:47
jp@psique.org http://www.psique.org/cursos

327

Transaes

Mandatory

Never

Curso J150

Required
Indica que o mtodo deve ser chamado em uma transao. Se no
existir transao, uma nova transao ser criada, se j existir uma
transao, a nova chamada far parte do escopo da transao
anterior.

Supports
Indica que o mtodo suporta transaes. Ser includo no escopo da
transao se existir uma, se no existir no ser criada transao.

RequiresNew
Indica que uma nova transao deve ser iniciada para a chamada do
motodo. Havendo ou no transao, uma nova ser iniciada.

NotSupported
Indica que o mtodo no suporta transaes. Se o mtodo for
chamado no escopo de uma transao, a mesma ser suspensa
enquanto durar a execuo do mtodo.

Mandatory
Indica que o mtodo s pode ser chamado no escopo de uma
transao pr-existente. Se for chamado fora de transao, ser
lanada uma exceo do tipo
javax.transaction.TransactionrequiredException.

24/04/04 01:52:49
jp@psique.org http://www.psique.org/cursos

328

Transaes

Curso J150

Never
Indica que o mtodo nunca pode ser chamado durante uma
transao. Se houver uma chamada durante uma transao, ser
lanada uma RemoteException (ou EJBexception em clientes locais).

Atributo de
Transa o

Stateless
Stateful
Session Bean Session Bean
imple m e n t a n
do Session
Synchroni z a t
ion
Required
Sim
Sim
RequiresNew Sim
Sim
Mandatory
Sim
Sim
Supports
Sim
No
NotSuppor te d Sim
No
Never
Sim
No

Entity Bean

Message Driven Bean

Sim
Sim
Sim
No
No
No

Sim
No
No
No
Sim
No

Excees
A especificao de J2EE classifica as excees em System
exceptions e Application exceptions. As System exceptions so
excees que indicam erros no servidor e servios usados pela
aplicao, so instncias de RemoteException e RuntimeException.
Causam rollback automtico de transaes. As Application
exceptions so excees que indicam erro na lgica da aplicao.
So subclasses de Exception que no so System exceptions. No
causam rollback pois o continer no pode avaliar se a exceo
grave o suficiente para provocar o rollback.
O servio de transaes indispensvel para garantir a integridade
dos dados. melhor utilizar CMT (Continer-Manager Transaction)
sempre que possvel, pois mais simples, menor risco de deadlock e
gargalos, facilita a separao de papis e a especializao. O
deployer pode ajustar a poltica de transaes ao ambiente onde
24/04/04 01:52:51
jp@psique.org http://www.psique.org/cursos

329

Transaes

Curso J150

est sendo executada a aplicao.


Pode melhorar bastante a performance de aplicaes EJB pois o
continer sincroniza (efetua o load e o store) apenas uma vez por
transao.

Session Synchronization
As vzes, o continer no tem como automticamente desfazera lgo
que tenha sido feito. Um EMail enviado por exemplo, no tem como
ser desfeito. Variveis de instncia em Statefull SessionBeans
tambm no tem seu estado restaurado em caso da transao
falhar. Uma soluo para estes casos implementar
SessionSynchronization:
public class ContadorBean implements SessionBean,
SessionSynchronization {
public int val;
public int oldVal;
public void ejbCreate(int val) {
this val = val;
this.oldVal = val;
}
// Chamado antes de comear a transao
public void afterBegin() {
oldVal = val;
}
// Chamado antes do commit
public void beforeCompletion() {
}
// Chamado logo aps o commit
public void afterCompletion(boolean b) {
// b o indicativo de sucesso ou falha
if ( ! b )
val = oldVal; // Se falhar, acerte o valor
// do atributo de instncia
}
public int count() {
24/04/04 01:52:52
jp@psique.org http://www.psique.org/cursos

330

Transaes

return
}
public void
public void
public void
public void

Curso J150

++val();
ejbRemove() {}
ejbActionvate() {}
ejbPassivate() {}
setSessionContext(SessionContext ctx) {}

1 Quando este bean inicializado no ejbCreate(), ou quando a


transao comea no mtodo afterBegin(), os atributos val e oldVal
tem o mesmo valor.
2 Alguns count() so executados, incrementando val.
3. Se a transao falhar, o mtodo afterCompletion chamado
quando a transao se completar e um valor booleando falso
enviado ao mtodo para indicar a falha. O estado conversacional
do bean ento retornado ao valor inicial.

24/04/04 01:52:54
jp@psique.org http://www.psique.org/cursos

331

Anexo 1 Cluster no JBoss

Curso J150

Anexo 1 Cluster no
JBoss
O application server JBoss suporta cluster de uma forma quase
automtica. O primeiro prottipo surgiu em abril de 2001 foi
codificado por Sacha Labourey. Bill Burke juntou-se a Sacha em
Agosto de 2001 e juntos refizeram do zero o que hoje o sistema de
cluster do JBoss.

O que um cluster?
Um cluster um conjunto de ns com um objetivo comum. Um n
pode ser um computador, ou, uma instncia de um servidor (caso
em que vrias instncias de servidores existem em um nico
servidor).
No JBoss o clusterring tem dois objetivos:
1 Tolerncia a falhas
2 Balanceamento de carga.

Caractersticas do Clustering JBoss


As seguintes caractersticas so suportadas:

Descoberta automtica. Os ns em um cluster enontram outros


sem nenhuma configurao.

Fail-over e load-balancing para:

JNDI

RMI

24/04/04 01:52:56
jp@psique.org http://www.psique.org/cursos

332

Anexo 1 Cluster no JBoss

Curso J150

Entity Beans

Stateful Session Beans com replicao de estado em memria

Stateless Session Beans

Replicao de sesses HTTP com Tomcat 4.1 e 5.0

Descoberta dinmica com JNDI. Os clientes JNDI podem


automaticamente descobrir o contexto inicial (JNDI
InitialContext).

Cluster-wide replicao de rvore JNDI.

Farming. Hot-deployment distribudo por todo o cluster. Fazendo


um hot deploy em um n, ele ser enviado para todos os ns do
cluster.

Polticas de carregamento de carga plugveis para RMI.

Parties
Um cluster um conjunto de ns. No JBoss um n uma instncia
de um servidor. Vrias instncias podem ser agrupadas em uma
partio. Em uma rede, podemos ter diferentes parties. Para
diferenci-las, cada partio tem um nome.
Partio B

Partio A
JBoss
N 1

JBoss
N 5

JBoss
N 2

JBoss
N 6

JBoss
N 3

JBoss
N 7

JBoss
N 4

JBoss
N 8

JBoss
N 9

Partio C
Rede
24/04/04 01:52:58
jp@psique.org http://www.psique.org/cursos

333

Anexo 1 Cluster no JBoss

Curso J150

Proxies espertos (Smart proxies)


Independentemente da soluo de clustering, os mecanismos de
tolerncia a falhas e balanceamento de cargas (fail-over e loadbalancing) precisam ser colocados em algum lugar.
Quando um cliente se comunica com um n que repentinamente
falha, o cliente mesmo toma a iniciativa de tentar reconectar-se com
outro n em execuo. Este tipo de estratgia prov tolerncia a
falhas mas no transparente ao cliente. Este tipo de tolerncia a
falha a gerenciada pelo cliente.
No difcil de imaginar que para o mecanismo de tolerncia a
falhas ficar transparente ao cliente este mecanismo deve estar no
servidor: um servidor recebe a requisio (o dispatcher),
encaminha para o application server e se ele falhar, repassa para
outro n. Mas e se o dispatcher falhar? Este tipo de estratgia
chamado de Dispatcher-managed fail-over.
Qual seria a sada ento?
Por sorte utilizando RMI, temos a disposio vrias caractersticas
muito interessantes. Um cliente pede um stub para um objeto
remoto, posivel enviar a ele um objeto serializado. sempre
possvel fazer com que o cliente receba a classe do stub de
qualquer servidor web transparentemente. O que acontece que
quando um cliente tem uma referencia remota, ele tem um objeto
serializado que contem a URL de onde ele deve buscar as definies
da classe. O stub obtido do servidor e executado no cliente. Ento,
basta que o stub seja esperto, ou seja, o stub saiba
transparentemente buscar os dados em outro lugar em caso de
falha. Ou seja, como se o dispatcher estivesse incorporado no
cdigo do cliente. Este tipo de implementao a utilizada no JBoss
e chamada de Client proxy-managed fail-over.

24/04/04 01:52:59
jp@psique.org http://www.psique.org/cursos

334

Anexo 1 Cluster no JBoss

Curso J150

Na implementao atual, chamada de HA-RMI, o proxy que


recebido pelo cliente contm a lista dos ns que podem ser
acessados e uma poltica de balanceamento de carga. Isto significa,
que um bean baixado pode determinar em tempo de baixa qual o
comportamento que o proxy deve ter (na realidade, ele pode sempre
mudar de comportamento enquanto o continer estiver rodando).

Descoberta de ns 'Automgica'
Com os clusteres do JBoss, no existe a necessidade de definir a
topologia do cluster. As nicas informaes interessantes so: O
nome do cluster (o nome da partio). Depois que o nome da
partio for configurado, qualquer node pode dinamicamente
juntar-se ou deixar a partio.

Configurando o JBoss
Cada n participante do cluster deve ter ao menos uma partio.
Um n pode participar em mais de um cluster iniciando vrias
parties, cada uma com um nome diferente, mas o normal que
um n participe de apenas uma partio. Evidentemente cada
partio consome recursos, por isto, limitar a quantidade de
parties uma boa idia.
O JBoss vm com trs configuraes para o servidor: minimal,
default e all. A opo de clustering est apenas habilitada na
configurao all. Um arquivo chamado cluster-service.xml no
diretrio deploy descreve a configurao para a partio default do
cluster - DefaultPartition. Este xml l o MBean para parties e
inicializa o JGroups e alguns outros componentes.
Veja a definio de clustering:
<mbean code=org.jboss.ha.framework.server.ClusterPartition
name=jboss:service=DefaultPartition/>

HA-JNDI Servio de nomes e o JBoss clustering


Ter um cluster para todas as caractersticas dos EJBs parece bom.
Lembre-se que particamente qualquer acesso a EJB inicia-se com
24/04/04 01:53:01
jp@psique.org http://www.psique.org/cursos

335

Anexo 1 Cluster no JBoss

Curso J150

um lookup de sua interface home em uma rvore JNDI, as


caractersticas atuais de cluster sero ineficientes sem que a rvore
de JNDI seja clusterizada. O JBoss 3.0 tem esta caracterstica.

Existe um contexto global que compartilhado em todo o cluster


que os clientes podem utilizar para fazer lookups e binds. Isto se
chama HA-JNDI. Clientes remotos conectam-se com HA-JNDI iro
ter tolerncia a falhas e balanceamento de carga. Binds feitos por
eles para o contexto HA-JNDI sero replicados por todo o cluster
ento se um n cair, mesmo assim, todos os objetos estaro
disponveis para lookup.
Do lado do servidor, new InitialContext(), ir ser direcionado para
um contexto local no clusterizado (JNDI bsico). Quando do lado
do servidor for necessrio acessar o HA-JNDI, necessrio que o
InitialContext seja o do HA-JNDI, isto pode ser feito com o cdigo
abaixo:
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY,
org.jnp.interfaces.NamingContextFactory);
p.put(Context.URL_PKG_PREFIXES, jboss.naming:org.jnp.interfaces);
p.put(Context.PROVIDER_URL, localhost:1100); // portoi HA-JNDI
Context ctx = new InitialContext(p);

Quando um cliente remoto faz um lookup para um HA-JNDI, o HAJNDI ir delegar para um contexto JNDI local quando no for
possvel encontrar o objeto no cluster global. Ento, um EJB home
lookup para um HA-JNDI, ser sempre delegado para uma instncia
local de JNDI.
Na implementao corrente, HA-JNDI funciona com sua prpria
rvore JNDI global no cluster, bem como uma rvore JNDI local
disponvel no JBoss.

24/04/04 01:53:03
jp@psique.org http://www.psique.org/cursos

336

Anexo 1 Cluster no JBoss

Curso J150

Configurao do HA-JNDI no JBoss


Para configurar os servios de HA-JNDI, voc precisa incluir uma
entrada no XML de configurao do JBoss (jboss-services.xml ou
qualquer arquivo de configurao no diretrio /deploy).
O arquivo cluster-service.xml j inclui a definio. Voc pode ver
que este MBean depende do MBean DefaultPartition.
<mbean code=org.jboss.ha.jndi.HANamingService
name=jboss:service=HAJNDI>
<depends>jboss:service=DefaultPartition</depends>
</mbean>

ClientesHAJNDIeautodescoberta
Quando trabalhamos s com um servidor JBoss, a configurao do
JNDI bem simples: Precisamos saber unicamnete o nome do
servidor ou o endereo IP e o porto do servidor JNDI.
Quando trabalhamos com um cluster de servidores, a configurao
no to simples. Qual servidor estar sendo executado? Se
pudessemos saber isto, no precisaramos de cluster. Como no
sabemos, a propriedade java.naming.provider.url pode aceitar uma
lista de urls separadas por vrgula.
java.naming.provider.url=servidor1:1100,servidor2:1100,serv
idor3:1100,servidor4:1100

Na inicializao o cliente JNP (JNDI) ir tentar contactar todos os


servidores da lista, parando quando achar o primeiro ativo. Ento
ir baixar o stub do servidor HA-JNDI deste servidor. O stub
'esperto' baixado contm a lgica para tolerncia a falhas e outros
servidores se necessrio e a lista atualizada dos servidores ativos. A
cada nova invocao feita a um servidor, a lista dos servidores
ativos atualizada (desde que tenha sofrido alterao desde a
ltima chamada).

24/04/04 01:53:05
jp@psique.org http://www.psique.org/cursos

337

Anexo 1 Cluster no JBoss

Curso J150

Em ambientes muito dinmicos, este tipo de soluo pode no ser


adeqada. Nestes casos possvel configurar uma funcionalidade
chamada auto-discovery. Se a propriedade
java.naming.provider.url estiver vazia, ou se todos os servidores
mencionados no esto disponveis, o cliente JNP ir tentar
descobrir um servidor HA-JNDI atravs de chamadas multicast
atravs da rede. A funcionalidade de auto descoberta usa para
multicast o grupo de endereos: 230.0.0.4:1102

24/04/04 01:53:06
jp@psique.org http://www.psique.org/cursos

338

Anexo 2 Criando um session


bean no WSAD da IBM

Curso J150

Anexo 2 Criando um
session bean no WSAD
da IBM
Abaixo um passo a passo visual sobre como criar um bean utilizando
o WSAD 5.1.1 (IBM - Websphere Studio Application Developer).
O primeiro passo criar um projeto EJB:

Selecionar a specificao de EJB ele vai seguir (2.0)

24/04/04 01:53:08
jp@psique.org http://www.psique.org/cursos

339

Anexo 2 Criando um session


bean no WSAD da IBM

Curso J150

Na janela a seguir , informamos o nome do Projeto (Somador) e qual


ser o projeto do EAR (no caso escolhi criar um novo EAR para o
session bean):

Clicando Finish e mudando para a perspectiva J2EE, vemos a tela


abaixo:

24/04/04 01:53:10
jp@psique.org http://www.psique.org/cursos

340

Anexo 2 Criando um session


bean no WSAD da IBM

Curso J150

Clicar no Mdulo EJB Somador com o boto direito e escolher New


Session Bean:

24/04/04 01:53:12
jp@psique.org http://www.psique.org/cursos

341

Anexo 2 Criando um session


bean no WSAD da IBM

Curso J150

No prximo dilogo, informar o tipo de Bean (Session Bean), o


Nome do Bean (Somador), as outras opes deixei com o valor
default:

24/04/04 01:53:14
jp@psique.org http://www.psique.org/cursos

342

Anexo 2 Criando um session


bean no WSAD da IBM

Curso J150

Informamos agora os detalhes do Bean, no caso, o nosso Stateless,


transaes controladas pelo Continer, no criaremos interfaces
locais, e aceitaremos os nomes das interfaces Remote e Remote
Home.

24/04/04 01:53:16
jp@psique.org http://www.psique.org/cursos

343

Anexo 2 Criando um session


bean no WSAD da IBM

Curso J150

Clicando Finish, teremos o esqueleto do EJB Pronto:

24/04/04 01:53:17
jp@psique.org http://www.psique.org/cursos

344

Anexo 2 Criando um session


bean no WSAD da IBM

Curso J150

Agora criamos um novo mtodo no Bean (no caso, o mtodo soma,


que simplesmente, recebe dois inteiros e devolve a soma deles):

24/04/04 01:53:20
jp@psique.org http://www.psique.org/cursos

345

Anexo 2 Criando um session


bean no WSAD da IBM

24/04/04 01:53:22
jp@psique.org http://www.psique.org/cursos

Curso J150

346

Anexo 2 Criando um session


bean no WSAD da IBM

Curso J150

Para incluir nosso mtodo na interface remota, clique direito na


viso outline em cima do Mtodo, escolher Enterprise Bean e
Promote to Interface Remote:

Pronto... tudo atualizado (inclusive o EAR).

24/04/04 01:53:23
jp@psique.org http://www.psique.org/cursos

347

Anexo 3 - Acesso a dados via DAO

Curso J150

Anexo 3 - Acesso a dados


via DAO
A utilizao de BMP e CMP interessante, mas nem sempre o
continer otimiza os acessos da melhor forma possvel. Em funo
disso, muitos preferem manter o controle sobre o acesso a dados
utilizando session beans e DAOs para o trabalho. interessante
tambm a utilizao de DAOs com Entities BMP, neste caso o DAO
tem a vantagem de uniformizar e centralizar o acesso aos dados.
Abaixo o relacionamento de classes:

Quem quem:

BusinessObject
Representa os dados do cliente. o objeto que requer acesso
origem dos dados para obter os dados. Um objeto de negcio pode
ser implementado como um session bean, um entity bean, ou algum
outro objeto java, em adio a um servlet ou helper para acessar a
origem dos dados.

24/04/04 01:53:26
jp@psique.org http://www.psique.org/cursos

348

Anexo 3 - Acesso a dados via DAO

Curso J150

DataAccessObject
O DataAccessObject o objeto principal deste pattern. O
DataAccessObject abstrai as implementaes de acesso a dados
para o BusinessObject para habilitar acesso transparente aos dados.
O BusinessObject delega a leitura e gravao de dados para o
DataAccessObject.

DataSource
a representao da origem dos dados. Um data source pode ser
um banco de dados RDBMS, OODBMS, XML, arquivo sequencial,
arquivo serializado, ou qualquer outra possibilidade. Um data
source pode ser tambm um outro sistema (legado/mainframe),
servio (B2B, Webservice), ou algum tipo de repositrio (LDAP por
exemplo).

ValueObject ou TransferObject
a representao do objeto utilizado para transportar os dados
entre componentes. O DataAccessObject pode usar VOs (ou DTOs)
para retornar dados ao cliente. O DataAccessObject pode tambm
receber os dados do cliente em um VO para alterar os dados no data
source.

24/04/04 01:53:27
jp@psique.org http://www.psique.org/cursos

349

Anexo 3 - Acesso a dados via DAO

Curso J150

Estratgias
Automatic DAO Code Generation Strategy
J que cada BusinessObject corresponde a um DAO especfico,
possvel estabelecer relacionamentos entre o BusinessObject, DAO e
fonte de dados. Uma vez que os relacionamentos estiverem
estabelecidos, possvel escrever uma aplicao para gerao de
cdigo automtica para acesso aos dados. Os metadados para gerar
o DAO podem vir de um descritor escrito pelo desenvolvedor.
Alternativamente, o cdigo pode automaticamente analisar o banco
de dados para prover os DAOs para acessar o banco de dados.

Factory for Data Objects Strategy


Nesta estratgia, o DAO pode ser implementado por uma
implementao do pattern Abstract Factory e Factory Method.
Quando a origem de dados no muda de uma implementao para
outra, esta estratgia pode ser implementada utilizando o pattern
Factory Method para produzir todos os DAOs necessrios para a
aplicao.
24/04/04 01:53:29
jp@psique.org http://www.psique.org/cursos

350

Anexo 3 - Acesso a dados via DAO

Curso J150

J quando a base de dados de origem pode mudar, ou seja, podem


existir fontes de dados diferentes (RDB, XML, TEXTO, ETC.), esta
estratgia pode ser implementada utilizando Abstract Factory.
Neste caso, a estratgia prov um fbrica abstrata de DAO
(Abstract Factory) que pode construir diverso tipos de factories
concretas. Aps obter uma factory concreta, ela ser utilizada para
produzir DAOs.

24/04/04 01:53:31
jp@psique.org http://www.psique.org/cursos

351

Anexo 3 - Acesso a dados via DAO

Curso J150

Conseqncias
Possibilita Transparncia
Os Business objects podem usar o data source sem conhecer os
detalhes da implementao do data source. Acessar
transparentemente porque os detalhes esto escondidos no DAO.

Facilita Migrao
Uma camada de DAOs torna mais fcil a uma aplicao migrar para
uma implementao de banco de dados diferente. Os objetos de
negcio no conhecem a implementao da base de dados. A
migrao implica to somente em alterar a camada dos DAOs. Se
estiver implementado com Factory, possibilita prover
implementaes de fbricas concretas para cada tipo de
implementao de persistncia. Ento a migrao pode se resumir
criao de uma nova fbrica e implement-la na aplicao.

24/04/04 01:53:33
jp@psique.org http://www.psique.org/cursos

352

Anexo 3 - Acesso a dados via DAO

Curso J150

Reduz a complexidade de Cdigo nos


Objetos de Negcio
Porque os DAOs gerenciam todo o acesso a dados, h uma
simplificao no cdigo dos objetos de negcio e outros clientes de
dados que usam os DAOs. Todos os cdigos relacionados
implemetao ficam contidos nos DAOs. Se for um DAO que acessa
uma base de dados via SQL, todo o SQL ficar restrito ao DAO, fora
do DAO nenhuma outra classe conhecer SQL.

Centraliza o acesso a dados em uma camada


separada
Porque todas as operaes de acesso a dados so delegadas para os
DAOs, a camada separada pode ser vista como uma camada que
pode isolar o resto da aplicao das implementaes de acesso a
dados. Esta centralizao torna a aplicao mais simples de manter.

No til para CMP


Com CMP o continer cuida do acesso a dados, os servios de
persistncia ficam todos sob a responsabilidade do continer.
Utilizando CMP, pode ser interessante a utilizao de DAOs se
existirem outros componentes que precisam de acesso a dados.

Cria uma camada extra


Os DAOs criam uma camada de objetos entre os dados e o cliente.
Isto interessante mas uma pequena perda em funo dos
componentes extras criados.

Necessita de projeto de hierarquia de


classes
Quando utilizando a estratgia de factory, a hierarquia de fbricas
24/04/04 01:53:35
jp@psique.org http://www.psique.org/cursos

353

Anexo 3 - Acesso a dados via DAO

Curso J150

concretas e a hierarquia dos produtos concretos produzidos pelas


fbricas devem ser projetados e implementados. Este esforo
adicional deve ser considerado se houver justificativas para a
implementao, tais como a flexibilidade. Isto aumenta a
complexidade do projeto. Por outro lado, voc pode implemntar a
estratgia de factory comeando pelo pattern Factory Method
primeiro, e depois evoluindo at atingir o pattern Abstract Factory
se necessrio.

24/04/04 01:53:38
jp@psique.org http://www.psique.org/cursos

354

Curso J150

24/04/04 01:53:40
jp@psique.org http://www.psique.org/cursos

355

Definies, acrnimos e
abreviaes

Curso J150

Definies, acrnimos e
abreviaes
ACL

Access Control List uma lista de usurios com seus respecitvos


direitos. Se o usurio tem o direito pode executar a operao.

EJB

Enterprise Java Bean um componente distribuvel, instalvel no


servidor que pode ser montado em grandes aplicaes. Podem ser
particionados em vrias camadas, podem ser transacionais, podem
ser multiusurio e podem ser instalados em qualquer continer
compatvel com EJB. Todos os EJB estendem a interface
javax.ejb.EnterpriseBean.

MOM

Message-Oriented Midleware Utilizado para se referir a qualquer


infraestrutura que suporte mensageria. Uma variedade muito
grande de produtos so classificados como MOM. Exemplos: Tibco
Rendezvous, IBM MQSeries, BEA Tuxedo/Q, Microsoft MSMQ,
Talarian SmartSocketes, Progress SonicMQ, Fiorano FioranoMQ,
JBoss MQ. Estes produtos podem ter uma poro de servios
agregados, tais como garantia de entrega, tolerncia a falhas,
balanceamento de cargas.

RMI

Remote Method Invocation

24/04/04 01:53:42
jp@psique.org http://www.psique.org/cursos

356

Definies, acrnimos e
abreviaes

Curso J150

RMI-IIOP

RMI sobre Internet Inter ORB Protocol

24/04/04 01:53:44
jp@psique.org http://www.psique.org/cursos

357

Definies, acrnimos e
abreviaes

Curso J150

Bibliografia
Tutorial do J2EE
ROMAN, Ed e AMBLER, Scott, Mastering Enterprise Java Beans
Ed Roman
LABOUREY, Sacha e BURKE, Bill. JBoss AS Clustering. Atlanta, GA:
JBoss Group.

24/04/04 01:53:47
jp@psique.org http://www.psique.org/cursos

358

You might also like