Java - J2EE Primeiros Passos
Java - J2EE Primeiros Passos
Java - J2EE Primeiros Passos
ISBN: 85-7522-???-?
Este livro dedicado Clarissa e minha famlia, que sempre estiveram ao meu
lado.
Carlos Eduardo Ribeiro do Valle
Aos meus pais, pelos valores a mim ensinados, aos amigos e famlia, pelos
momentos de descontrao, e em especial minha namorada Regina, pelo constante
apoio e estmulo, sem o qual a concluso deste trabalho no seria possvel.
Andr Temple
A Deus, minha esposa Claudia e minha famlia.
Rodrigo Fernandes de Mello
Aos meus pais, por todo o apoio que prestaram durante todas as duras tarefas que
realizei. minha noiva Cristiane, pela compreenso nos momentos que tive que
deixar de lhe dar ateno para me dedicar escrita deste livro.
Danival
Agradeo minha famlia por sempre me apoiar em todos os momentos da minha
vida e minha equipe de trabalho da Fundao CPqD pelas experincias
vivenciadas.
Maurcio Schiezaro
Sobre os autores
Carlos Eduardo Ribeiro do Valle Bacharel em Cincias da Computao pelo
Instituto de Cincias Matemticas e Computao da USP. scio-diretor da
NZTech (http://www.nztech.com.br), empresa de desenvolvimento de software
que atua no mercado corporativo. Trabalha com projetos de consultoria e desenvolvimento de sistemas envolvendo tecnologias Wireless, XML, Server-Side Computing,
entre outras.
Andr Temple graduado em Cincia da Computao pela UNESP Universidade
Estadual Paulista e atua no desenvolvimento de solues de billing na arquitetura
J2EE, no CPqD Telecom & IT Solutions.
Rodrigo Fernandes de Mello doutorando do Departamento de Engenharia Eltrica
da Escola de Engenharia de So Carlos, Universidade de So Paulo. Mestre em Cincia da Computao pela Universidade Federal de So Carlos na rea de sistemas distribudos e redes de computadores. Trabalha com sistemas distribudos desde 1998.
Autor do livro Aprendendo Java 2 da Editora Novatec.
Danival Taffarel Calegari mestre em Cincia da Computao pela Unicamp e trabalha no CPqD Telecom & IT Solutions utilizando J2EE no desenvolvimento de solues de billing.
Mauricio Schiezaro bacharel em Cincia da Computao pela UNESP - Universidade Estadual Paulista e tcnico em eletro-eletrnica formado pelo Cotuca - Unicamp e
trabalha no desenvolvimento de solues de billing utilizando a arquitetura J2EE no
CPqD Telecom & IT Solutions.
Sumrio
Sobre os autores ........................................................................................................ 6
Prefcio ....................................................................................................................... 12
Parte I .............................................................................................................................. 14
Desenvolvendo Interfaces e Controles de Interao com o Usurio ...................................... 14
Captulo 1 ......................................................................................................................... 16
Introduo ................................................................................................................. 16
Captulo 2 ......................................................................................................................... 21
Instalao e Configurao .................................................................................... 21
2.1Pr-requisitos ............................................................................................................. 21
2.1Instalao e configurao no Apache Tomcat ............................................... 22
2.2Instalao e Configurao de uma Aplicao Web ...................................... 22
Captulo 3 ......................................................................................................................... 31
Servlets caractersticas bsicas ......................................................................... 31
Captulo 4 ......................................................................................................................... 49
Servlets Gerao da sada .................................................................................. 49
Captulo 5 ......................................................................................................................... 65
Servlets Captura de parmetros da requisio ........................................... 65
5.1Informaes sobre o servidor .............................................................................. 65
5.2Informaes sobre a requisio .......................................................................... 66
7
Captulo 6 ......................................................................................................................... 78
Servlets Cookies e Sesses ................................................................................ 78
Captulo 7 ......................................................................................................................... 95
Pginas JSP ................................................................................................................. 95
Sumrio
10.2 Sistemas Distribudos ........................................................................................... 135
10.3 Primeiros Ensaios de Arquiteturas para Sistemas Distribudos no Mercado ................................................................................................................................... 141
10.4 Mercado Atual para Sistemas Distribudos ................................................... 144
10
Prefcio
J2EE uma tecnologia muito recente e no muito simples de ensinar e de aprender.
Dessa forma, dividimos o livro em duas grandes partes que tratam dos componentes
principais da arquitetura. Preferimos apresentar primeiramente os conceitos relacionados aos componentes de apresentao, pois acreditamos serem mais fceis de entender e que seja o caminho mais correto no seu aprendizado. Gradualmente fornecemos ao leitor conceitos mais avanados da arquitetura, tratando dos componentes
de negcio e finalizando com uma aplicao prtica.
A primeira parte aborda de forma consistente e didtica o contedo relacionado
camada de apresentao, utilizando os componentes Java Server Pages (JSP) e Servlets. Apresentamos um histrico do desenvolvimento de aplicaes Web, relembrando o uso comum de CGI e linguagens de script. So abordados tambm os tpicos
JavaBeans, Taglibs, modelo MVC e instalao e configurao do container Web.
A segunda parte foca no paradigma de desenvolvimento de aplicaes distribudas,
destacando a evoluo das tcnicas de desenvolvimento, desde a programao estrutural at o atual uso de sistemas distribudos. So detalhados os componentes de
negcio Enterprise JavaBeans e os recursos oferecidos no uso desta tecnologia.
Esta diviso visa oferecer um contedo mais abrangente e completo ao leitor. O intuito de todo o livro ser prtico nos temas que apresenta. Todos os captulos apresentam exemplos que simplificam o processo de entendimento dos temas.
Esperamos que voc, profissional, estudante, ou entusiasta de novas tecnologias, faa
bom proveito desta literatura e que ela seja uma boa orientao para seus estudos e
realizaes profissionais.
11
12
Parte I
Desenvolvendo Interfaces e
Controles de Interao com o Usurio
Esta primeira parte aborda de forma consistente e didtica o contedo relacionado
camada de apresentao, utilizando os componentes Java Server Pages (JSP) e Servlets. Apresentamos um histrico do desenvolvimento de aplicaes Web, relembrando o uso comum de CGI e linguagens de script. So abordados tambm os tpicos
JavaBeans, Taglibs, modelo MVC e instalao e configurao do container Web.
13
14
Captulo 1
Introduo
Introduzimos, nesse captulo, a tecnologia de Servlets e JSP (JavaServer Pages), e
mostramos algumas caractersticas que tornam essas tecnologias bastante atraentes
para o desenvolvimento de aplicaes na Web.
15
16
Captulo 1 Introduo
17
Exemplo de Servlet
import java.io.*;
import javax.servlet.http.*;
18
Captulo 1 Introduo
Assim, um JSP consiste de uma pgina HTML com alguns elementos especiais, que
conferem o carter dinmico da pgina. Esses elementos podem tanto realizar um
processamento por si, como podem recuperar o resultado do processamento realizado em um Servlet, por exemplo, e apresentar esse contedo dinmico junto a pgina
JSP.
Existe tambm um recurso adicional bastante interessante na utilizao de pginas
JSP: a recompilao automtica, que permite que alteraes feitas no cdigo da pgina sejam automaticamente visveis em sua apresentao. Assim, no necessrio interromper o funcionamento da aplicao para incorporar uma modificao de layout,
por exemplo.
19
20
Captulo 2
Instalao e Configurao
Nesse captulo so apresentados os tpicos referentes a instalao e configurao de
um ambiente bsico para a implantao e execuo de aplicaes Web com Servlets
e pginas JSP.
2.1 Pr-requisitos
O primeiro passo para desenvolver aplicaes Web com Servlets e pginas JSP a
configurao de um ambiente bsico para a implantao e execuo dessas aplicaes. Esse ambiente bsico pressupe a instalao de dois componentes principais:
o Java 2 Standard Development Kit (J2SDK), utilizado para compilar aplicaes Java,
e um Servlet Container, que ir executar os Servlets desenvolvidos.
Alguns sistemas operacionais j possuem um J2SDK instalado por default. Caso esse
ainda no se encontre instalado, pode-se obt-lo no site oficial do Java (http://
java.sun.com). Neste site possvel selecionar entre as verses de J2SDK para as diversas plataformas de mercado tais como Windows, Linux, Solaris e outros.
O outro componente necessrio para o desenvolvimento de Servlets e JSP um servidor que implemente um Servlet Container. Esse servidor ser responsvel por prover um framework bsico para as diversas aplicaes desenvolvidas, inicializandoas, distribuindo as requisies entre elas e tratando os resultados do processamento
de cada aplicao.
Apesar de existirem diversos servidores disponveis no mercado, para efeito dos exemplos apresentados neste livro, utilizaremos o Apache Tomcat, disponvel no site http:/
/jakarta.apache.org. Esse servidor de aplicaes atende s especificaes mencionadas anteriormente e pode ser utilizado sem nenhum custo para o desenvolvedor.
Um ltimo componente normalmente utilizado para o desenvolvimento de Servlets e
pginas JSP um ambiente grfico de desenvolvimento (IDE). Porm, a escolha e
configurao desse ambiente foge do escopo deste livro, sendo deixado para o leitor
a tarefa de escolher a ferramenta que melhor atenda s suas necessidades.
21
22
Diretrio
Descrio
bin
conf
logs
Arquivos de log do servidor. Alm de gerar arquivos de log contendo entradas para
cada requisio recebida, como qualquer servidor Web, o Tomcat tambm pode gerar
arquivos de log com tudo o que as aplicaes desenvolvidas enviam para as sadas
padro do sistema: tipicamente, o que impresso atravs do System.out acrescido
no arquivo stdout.log, e tudo o que impresso atravs do System.err acrescido
no arquivo stderr.log.
work
Diretrio temporrio do Tomcat. Esse diretrio utilizado, por exemplo, para realizar
a recompilao automtica de pginas JSP (esse processo explicado mais adiante
no captulo Pginas JSP).
webapps
23
25
<web-app>
<display-name>RemoteIP</display-name>
<servlet>
<servlet-name>RemoteIP</servlet-name>
<servlet-class>RemoteIPServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RemoteIP</servlet-name>
<url-pattern>/RemoteIP</url-pattern>
</servlet-mapping>
</web-app>
Como o Deployment Descriptor composto de muitas sees, procuraremos apresentar as principais e suas respectivas funes, usando como exemplo a aplicao
CadastroClientes mencionada anteriormente. Uma apresentao mais detalhada e
aprofundada desse arquivo pode ser encontrada na prpria especificao de Servlets.
Pressupomos, para essa apresentao um conhecimento mnimo de XML; caso voc
no tenha familiaridade com esse tipo de documento, sugerimos que voc tente acompanhar os exemplos, e os utilize como templates para criar seus prprios Deployment Descritors.
<!DOCTYPE web-app
PUBLIC -//Sun Microsystems, Inc.//DTD Web Application 2.3//EN
http://java.sun.com/dtd/web-app_2_3.dtd>
<web-app>
.
.
.
</web-app>
26
O elemento context-param serve para que se possam definir parmetros de inicializao do contexto da aplicao; esses parmetros estaro disponveis para todos os
Servlets e pginas JSP da aplicao. Cada elemento presente deve conter o nome de
um parmetro e o seu valor correspondente. O desenvolvedor pode tambm optar
por no utilizar nenhum desses elementos em seu XML.
27
Os elementos welcome-file-list e error-page contm, respectivamente, a lista ordenada de pginas a serem utilizadas como index e as pginas a serem apresentadas em
casos de erros HTTP ou excees no tratadas pela aplicao. Esses dois elementos
so opcionais, sendo que somente o primeiro admite uma instncia por Deployment
Descriptor.
De acordo com o que apresentado na listagem anterior, se tomarmos como exemplo nossa aplicao CadastroClientes, quando feito um acesso a URL http://
192.168.0.1:8080/CadastroClientes/, o Servidor tentar retornar a pgina index.html,
conforme especificado na lista do welcome-file-list. Caso essa pgina no exista, o
Servidor tentar utilizar a pgina index.jsp.
A figura anterior tambm demonstra a utilizao do elemento error-page duas vezes:
a primeira vez para mapear erros HTTP 404 (pgina no encontrada) a uma pgina de
erro-padro, e a segunda, para mapear exceptions com.minhaempresa.exceptions.
DBConnException a uma outra pgina de erro.
Os ltimos dois elementos, servlet e servlet-mapping, servem para definir, respectivamente, os Servlets da aplicao, com seus respectivos parmetros, e os mapeamentos de URLs a cada Servlet da aplicao.
Cada elemento servlet, por sua vez, composto dos seguintes elementos:
28
Descrio
servlet-name
servlet-class
init-param
load-on-startup
Por fim, um elemento servlet-mapping contm um nome de Servlet, conforme definido em servlet-name, e um padro da URL do Servlet no servidor (URL pattern).
No exemplo anterior, todos as requisies com URLs iniciadas por /CadastroClientes/Processamento/ sero mapeadas para o Servlet cujo nome ProcessaCadastro.
Outros mapeamentos interessantes podem ser obtidos atravs de padres de URL do
tipo *.<extenso>, como por exemplo, *.wm ou *.pdf, de maneira que o acessos a
todas as URLs com o sufixo indicado sejam tratados por um mesmo Servlet.
29
<!DOCTYPE web-app
PUBLIC -//Sun Microsystems, Inc.//DTD Web Application 2.3//EN
http://java.sun.com/dtd/web-app_2_3.dtd>
<web-app>
<display-name>Cadastro de Clientes</display-name>
<context-param>
<param-name>NomeBaseDados</param-name>
<param-value>dbaplic</param-value>
</context-param>
<context-param>
<param-name>IPBancoDados</param-name>
<param-value>192.168.0.2</param-value>
</context-param>
<session-config>
<session-timeout>15</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<error-page>
<error-code>404</error-code>
<location>/404Error.html</location>
</error-page>
<error-page>
<exception-type>com.minhaempresa.exceptions.DBConnException</exception-type>
<location>/DBError.html</location>
</error-page>
30
31
32
Captulo 3
Servlets caractersticas bsicas
Nesse captulo, exploramos as caractersticas bsicas de Servlets, mostrando o funcionamento e sua interao com o Servlet Container. Implementamos tambm nossos
primeiros Servlets de exemplo.
33
Existem diversos mtodos HTTP que podem ser especificados em requisies, sendo
os mais comuns o mtodo GET, normalmente utilizado para obter o contedo de um
arquivo no servidor, e o mtodo POST, utilizado para enviar dados de formulrios
HTML ao servidor. Alm desses mtodos, o protocolo HTTP 1.0 admite tambm o
mtodo HEAD, que permite que o cliente obtenha somente os headers da resposta; j
o protocolo HTTP verso 1.1 admite os seguintes mtodos:
Mtodo
Descrio
PUT
DELETE
OPTIONS
TRACE
Alm do mtodo, path e verso, uma requisio pode conter parmetros adicionais,
chamados headers. Dois headers comuns so, por exemplo, o header User-Agent,
que contm informaes sobre o cliente que est gerando a requisio (tipo, verso
do browser etc.) e o header Accept, que serve para especificar os tipos de recursos
aceitos pelo cliente para a requisio enviada.
34
<HTML>
<BODY>
</BODY>
</HTML>
Assim, no exemplo anterior, o cdigo de status 200 indica que houve sucesso no
atendimento da requisio enviada pelo cliente, os headers indicam o tipo, tamanho
e data e hora de ltima modificao do contedo requisitado, e por fim, temos uma
pgina HTML em branco, com o contedo propriamente dito.
Outros cdigos de status bastante comuns so o 404, que indica que o recurso no foi
localizado no servidor, e o cdigo 500, que indica que houve erro no processamento
da requisio enviada.
Se voc quiser se aprofundar no estudo deste protocolo, uma boa pedida a leitura
do Guia de Referncia HTTP da Editora Novatec.
35
36
3.5 Inicializao
Conforme apresentado nos pargrafos anteriores, a inicializao do Servlet ocorre no
instante em que feita a carga da aplicao pelo Servlet Container.
Nesse instante, o Servlet Container executa o mtodo init do Servlet, dando chance
ao Servlet de executar quaisquer passos necessrios para sua inicializao, tais como:
1) leitura de parmetros de configurao
2) inicializao de variveis de classe (variveis estticas)
3) inicializao de conexes ao banco de dados, etc.
Assim, podemos ter implementado em nosso Servlet ProcCadastro, por exemplo:
37
Conforme pode ser visto, o mtodo init() admite duas assinaturas, sendo que em uma
delas, recebido como parmetro um objeto da classe javax.servlet.ServletConfig:
atravs desse objeto, o Servlet pode obter os parmetros de inicializao do Servlet,
contidos no Deployment Descriptor (veja seo 2.2). Por outro lado, caso voc opte
por implementar o mtodo init() sem nenhum parmetro, possvel tambm obter
uma referncia para o objeto ServletConfig por meio da chamada getServletConfig()
da prpria classe javax.servlet.GenericServlet (a qual nossa classe estende).
Obviamente o mtodo getInitParameter() pode retornar um valor nulo caso o parmetro inicial a ser obtido no tenha sido definido, e por isso importante que voc
faa a verificao do String retornado pela chamada do mtodo antes de utiliz-lo.
possvel tambm, a partir de um objeto da classe ServletConfig, percorrer a lista dos
parmetros de inicializao do Servlet, bastando utilizar o mtodo getInitParameterNames().
38
39
_ServidorSMTP = p_servletConfig.getInitParameter(Email.ServidorSMTP);
_Remetente = p_servletConfig.getInitParameter(Email.Remetente);
_Destinatario = p_servletConfig.getInitParameter(Email.Destinatario);
_Assunto = p_servletConfig.getInitParameter(Email.Assunto);
...
}
// Servlet para verificar conexo com banco de dados: lana thread que verifica
status da conexo periodicamente
public class VerificaConDB extends HttpServlet implements Runnable {
// Inicializao do Servlet
public void init(ServletConfig p_servletConfig) throws ServletException {
super.init(p_servletConfig);
40
super.init(p_servletConfig);
...
// Recuperando e validando parmetros de inicializao do Servlet
_ServidorSMTP = p_servletConfig.getInitParameter(Email.ServidorSMTP);
_Remetente = p_servletConfig.getInitParameter(Email.Remetente);
_Destinatario = p_servletConfig.getInitParameter(Email.Destinatario);
_Assunto = p_servletConfig.getInitParameter(Email.Assunto);
if((_ServidorSMTP == null) || (_Remetente == null) || (_Assunto == null))
throw new UnavailableException(Erro: parmetros de inicializao no
encontrados!);
41
Por outro lado, importante fazer a distino entre os parmetros iniciais do Servlet e
os parmetros iniciais do contexto, lembrando sempre que esses parmetros so definidos em sees distintas do Deployment Descriptor.
42
No exemplo a seguir, temos dois Servlets que fazem parte de uma mesma Aplicao
Web e que utilizam os atributos do contexto para indicar falhas em suas respectivas
inicializaes.
43
...
}
44
...
}
Por fim, h um outro mtodo da classe ServletContext que vale a pena conhecer: o
mtodo log() permite que voc adicione mensagens em um arquivo de log do Servidor de Aplicaes. Voc poder utilizar esse mtodo para depurar seus Servlets, gerar
alertas de problemas na sua execuo etc.
// Recuperando os
45
...
}
3.7 Finalizao
A finalizao de um Servlet deve ser tratada atravs da implementao do mtodo
destroy: no instante em que o Servlet descarregado, seu mtodo destroy(), se
tiver sido implementado, chamado, permitindo a execuo de rotinas de finalizao (como por exemplo, o encerramento de conexes com bancos de dados, finalizao de threads que tenham sido lanados etc.).
A assinatura do mtodo destroy() a seguinte:
// Servlet para verificar conexo com banco de dados: lana thread que verifica
status da conexo periodicamente
public class VerificaConDB extends HttpServlet implements Runnable {
// Inicializao do Servlet
public void init(ServletConfig p_servletConfig) throws ServletException {
super.init(p_servletConfig);
46
// Execuo do thread
public void run() {
while(_ThreadVerif != null) {
if(!ConBD.OK ()) {
...
}
}
}
// Finalizao do Servlet
public void destroy() {
_ThreadVerif = null;
}
...
}
No exemplo, o mtodo destroy() serve para indicar que o thread deve ser finalizado:
a atribuio do valor null varivel _ThreadVerif faz com que o looping principal do
mtodo run() seja finalizado.
47
Quando uma requisio HTTP recebida por uma classe que estende HttpServlet,
seu mtodo service() chamado, sendo que a implementao default desse mtodo
ir chamar a funo doXXX () correspondente ao mtodo da requisio recebida. Ou
seja, caso uma requisio com mtodo GET, por exemplo, seja recebida (vide seo
3.2, sobre o protocolo HTTP), o mtodo doGet() implementado por voc ser chamado.
Geralmente, desenvolvedores de Servlets implementam somente os mtodos doGet()
e doPost (); os mtodos restantes s so implementados em casos especiais, e requerem um conhecimento mais avanado por parte do desenvolvedor. Por ora, estaremos utilizando o mtodo doGet(); nos captulos seguintes demonstraremos com mais
detalhes alguns dos outros mtodos (principalmente, o mtodo doPost()).
Um exemplo simples de implementao do mtodo doGet() pode ser observado a
seguir:
Servlet HelloWorld
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
48
49
o nmero de
implements SingleThreadModel {
No exemplo anterior, o Servlet utiliza uma varivel de instncia _Contador e, por isso,
h a necessidade de se preocupar com a concorrncia no acesso a esta varivel.
Imagine, por exemplo, que esse Servlet no implemente a interface SingleThreadModel, e receba duas requisies simultaneamente: o primeiro doGet() poderia incrementar o contador, seguido do segundo doGet() incrementando o contador, seguido
dos dois threads, cada um por sua vez, imprimindo o valor do contador. Nessa situao, o mesmo valor de contador seria impresso nas duas pginas HTML resultantes.
50
Obviamente a implementao dessa interface tem um custo na performance de execuo do Servlet, pois, no Servlet anterior, por exemplo, no s o acesso a varivel
_Contador serializado, mas a execuo do mtodo doGet() como um todo. Em particular, a execuo dos cdigos de gerao do header e do footer HTML no precisariam ser serializados, mas so.
Por isso, em vez de implementar esta interface, na maioria das vezes mais conveniente implementar diretamente um cdigo de sincronizao nos trechos que precisam ser serializados. O Servlet ServletContador, por exemplo, poderia ser implementado da seguinte forma (com exatamente o mesmo resultado):
o nmero de
51
A implementao desse mtodo dever retornar um texto contendo informaes gerais sobre o Servlet desenvolvido, como por exemplo, o autor, verso e informaes
de copyright de seu Servlet.
Implementando esse mtodo para o nosso Servlet HelloWorld, temos:
Caso voc no implemente esse mtodo, um texto vazio ser retornado pela implementao default desse mtodo.
52
Captulo 4
Servlets Gerao da sada
Embora j tenhamos visto um pouco sobre o funcionamento da gerao de uma resposta simples de um Servlet, estaremos neste captulo analisando esse processo mais
a fundo e apresentando algumas funcionalidades mais avanadas.
53
Embora a anlise dos mtodos dessa classe fuja um pouco ao escopo deste livro (trata-se de uma classe do prprio core Java), interessante apresentar alguns de seus
mtodos aqui.
Os mtodos print () e println () dessa classe, por exemplo, podem ser utilizados para
adicionar Strings ao stream de sada do Servlet; como a sada mantida em um buffer
por questes de performance, voc pode tambm utilizar o mtodo flush () para
forar a liberao desse buffer de sada, fazendo que o contedo da resposta definido
por voc seja imediatamente enviado para o cliente.
54
}
}
}
Dessa forma, podemos capturar e tratar a exceo java.io.IOException caso ela ocorra, gerando, por exemplo, uma mensagem de log.
Mais detalhes sobre essas excees lanadas durante o processo de gerao da sada
do Servlet, incluindo suas possveis causas, so apresentadas ao longo das prximas
sees desse captulo.
55
<HTML><BODY>Hello World!</BODY></HTML>
Embora alguns headers sejam adicionados por default pelo ServletContainer, como
no caso da resposta do Servlet HelloWorld acima, podem haver situaes em que
voc queira definir ou modificar seus prprios headers HTTP, e para fazer isso, voc
deve utilizar o mtodo setHeader ().
Para indicar, por exemplo, que a resposta de um Servlet no deve ficar armazenada
em nenhum cache (armazenamento temporrio) do browser do usurio, nem em
nenhum proxy, podemos definir alguns headers adicionais especiais por meio do
seguinte trecho de cdigo:
Nesse cdigo, o header Expires indica a data de expirao, o header Last-Modified indica a data de ltima modificao, e os headers Cache-Control e Pragma
indicam o tratamento que o documento (ou seja, a resposta do Servlet) deve receber
se houver cacheamento.
Com a incluso do cdigo anterior, a resposta do Servlet passa a ser:
56
<HTML><BODY>Hello World!</BODY></HTML>
57
Se voc observou atentamente o cdigo para a modificao dos headers, voc deve
ter reparado no uso de um mtodo setDateHeader(): esse mtodo , na verdade, uma
variante do mtodo setHeader() que simplifica a definio de um header com uma
data. Assim como esse mtodo, existe um outro mtodo setIntHeader() para a definio de headers que contenham valores inteiros.
O segundo parmetro do mtodo setDateHeader() deve conter o nmero de milisegundos desde epoch (meia-noite, do dia 1 de Janeiro de 1970); o mtodo currentTimeMillis() do objeto java.lang.System retorna esse valor para o instante corrente.
Alm dos mtodos anteriores, existe o mtodo containsHeader(), para verificar se um
header j foi definido, e os mtodos addHeader(), addDateHeader() e addIntHeader() que permitem a adio de mais de um valor para um mesmo header.
58
A funo desse header Content-Type informar o tipo do contedo que est contido
na resposta, para que o browser (ou dispositivo cliente que est fazendo o acesso)
saiba como esse contedo deve ser interpretado e apresentado.
Nos exemplos anteriores esse header no foi definido explicitamente em cdigo:
nesses casos, o ServletContainer automaticamente define seu valor como text/html.
Esse valor indica que o contedo deve ser interpretado pelo browser como uma pgina HTML.
Outro header que definido automaticamente pelo ServletContainer, caso o desenvolvedor no o defina explicitamente, o header Content-Length. Esse header indica
o tamanho em bytes do contedo contido na resposta.
59
Embora a gerao de uma sada HTML seja a situao mais comum, podem haver
situaes em que voc deseje gerar outros tipos de sada. Nesses casos, voc deve
utilizar o mtodo setContentType para especificar o tipo do contedo desejado.
Assim, podemos usar o seguinte trecho de cdigo para retornar uma imagem JPEG
contida em um arquivo:
Servlet ImageServlet
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
60
} catch(IOException p_e) {
try {
if(l_imageFile != null) l_imageFile.close ();
} catch(Exception p_e2) {}
ServletContext l_context = getServletContext ();
l_context.log(Erro: no foi possvel ler imagem de arquivo);
}
}
}
No exemplo anterior, voc poder observar tambm a utilizao do mtodo getOutputStream (). Esse mtodo deve ser utilizado, em substituio ao mtodo getWriter ()
que foi usado nos exemplos anteriores, para obter uma referncia a um stream de
sada binria do Servlet.
Assim, quando voc desejar que seu Servlet retorne um contedo binrio (no-texto), como uma imagem JPEG no cdigo anterior, voc dever utilizar esse mtodo
getOutputStream (), e obter uma referncia a um objeto da classe
javax.servlet.ServletOutputStream.
Esse stream ServletOutputStream estende, na verdade, a classe java.io.OutputStream
e, sendo assim, herda os diversos mtodos write() e o mtodo flush() da classe-me.
61
Obviamente, a utilizao dos mtodos anteriores e at mesmo a obteno desse stream de sada binria do Servlet podem gerar excees do tipo java.io.IOException, em
situaes em que o usurio que est operando o browser aperta o boto Stop, antes
de todo o contedo gerado pelo seu Servlet seja enviado, por exemplo. Por isso
importante que voc se preocupe em capturar essas excees, e fazer os tratamentos
necessrios caso isso ocorra.
Servlet HelloWorldWML
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
// Quarta implementao do Servlet para pgina HelloWorld, desta vez com a gerao
da resposta em formato WML
62
63
Nos exemplos apresentados anteriormente, como esse status no foi atribudo explicitamente em cdigo, automaticamente o ServletContainer o definiu como sendo 200,
ou status OK. Vemos a seguir, por exemplo, a resposta do Servlet HelloWorld:
<HTML><BODY>Hello World!</BODY></HTML>
Temos, a seguir, uma tabela com alguns dos cdigos de status HTTP existentes e seus
respectivos significados:
Cdigo de Status Mensagem
Significado
200
OK
302
Moved Temporarily
404
500
503
Service Unavailable
Assim, no caso de nosso Servlet de gerao de imagem JPEG ImageServlet, podemos modific-lo de forma que ele retorne um cdigo 404 caso o arquivo com a imagem a ser gerada no exista.
64
65
Podemos ver, nessa implementao, que o cdigo de status definido pela constante
numrica SC_NOT_FOUND da classe HttpServletResponse.
Utilizao
de
constante
javax.servlet.HttpServletResponse
SC_NOT_FOUND
da
classe
...
p_response.setStatus(p_response.SC_NOT_FOUND);
...
Para cada cdigo de status HTTP existente, a classe HttpServletResponse define uma
constante correspondente, sendo que voc deve dar preferncia ao uso dessas constantes (em vez do nmero em si) para aumentar a legibilidade de seu cdigo.
Cdigo de Status Mensagem
Constante
200
OK
SC_OK
302
Moved Temporarily
SC_MOVED_TEMPORARILY
404
SC_NOT_FOUND
500
SC_INTERNAL_SERVER_ERROR
503
Service Unavailable
SC_SERVICE_UNAVAILABLE
Vale observar tambm que, para alguns cdigos de status, existem headers auxiliares
que contm indicaes sobre o que o cliente deve fazer ao receber aquele cdigo de
status.
Assim, no caso do cdigo 503 (SC_SERVICE_UNAVAILABLE), voc pode definir o
valor do header Retry-After para indicar o tempo estimado em segundos at que o
servio volte a ficar ativo.
Outro exemplo o cdigo de status 302 (SC_MOVED_TEMPORARILY): ao definir
esse cdigo de status, voc deve definir tambm o valor do header Location para
indicar a URL onde o novo documento pode ser encontrado.
Temos a seguir o exemplo de um Servlet que, dependendo do endereo IP do cliente
que envia a requisio, redireciona o acesso para uma nova pgina contendo uma
mensagem de acesso negado.
66
Servlet CheckIPAccess
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
} catch(IOException p_e) {
ServletContext l_context = getServletContext ();
l_context.log(Erro: + p_e.getMessage ());
}
}
}
67
Pelo cdigo:
...
if(l_ip == null) {
p_response.sendRedirect(/accessdenied.html);
return;
}
...
Veremos a seguir uma variao do ServletContador, apresentado anteriormente neste livro, que utiliza o mtodo sendRedirect() para redirecionar o milsimo acesso
para uma pgina especial:
68
Esse mtodo deve ser utilizado para a definio de cdigos de status nas faixas dos
400 e 500, como por exemplo, os cdigos SC_NOT_FOUND (404) e
SC_SERVICE_UNAVAILABLE (503), sendo que, se o segundo parmetro for utilizado,
este deve conter a mensagem descritiva que acompanha o cdigo de status.
Vale lembrar que de acordo com a configurao das pginas de erro da Aplicao
Web (descrita no Deployment Descriptor, vide seo 2.2), a definio de um cdigo de status de erro pode levar apresentao de uma pgina alternativa de erro.
69
70
redefinimos
71
72
Captulo 5
Servlets Captura de parmetros da
requisio
Alm de gerar uma resposta para cada requisio recebida, outro trabalho importante que deve ser realizado por um Servlet o de capturar e tratar os parmetros da
requisio (gerados, por exemplo, a partir de um formulrio HTML). Conforme o
resultado desse tratamento, um Servlet pode gerar respostas diferentes.
Esse captulo explora exatamente esse processo de captura dos parmetros da requisio recebida.
73
74
75
76
Os mtodos getContextPath (), getServletPath () e getPathInfo () retornam, respectivamente, o caminho do contexto, o caminho do Servlet abaixo do contexto, e o restante do path da requisio (se exclurmos as duas primeiras informaes).
Em particular, no ambiente apresentado no Captulo 2 Instalao e Configurao
desse livro (utilizando o Apache Tomcat), o caminho do contexto equivale ao subdiretrio criado abaixo da pasta webapps, ou seja, o subdiretrio da aplicao Web.
Por outro lado, o caminho do Servlet, corresponde ao mapeamento (servlet-mapping) que originou a chamada ao Servlet.
Se o Servlet anterior, ServletInfoReq, estivesse instalado junto a uma aplicao Web
livroservlets, por exemplo, e, no Deployment Descriptor dessa aplicao Web, houvesse um mapeamento da URL /ServletInfoReq/ para esse Servlet, teramos os seguintes resultados para cada requisio recebida:
Requisio
getContextPath ()
getServletPath ()
getPathInfo ()
/livroservlets/ServletInfoReq/
/livroservlets
/ServletInfoReq
null
/livroservlets/ServletInfoReq/abc/def.html
/livroservlets
/ServletInfoReq
/abc/def.html
A funo seguinte, getPathTranslated (), tenta traduzir a informao de path da requisio para o caminho real do recurso no disco. importante observar que essa funo s funciona caso a aplicao web no tenha sido implantada como um arquivo
WAR (explicado mais adiante no Captulo 9 Tpicos Adicionais).
A ltima funo, getRequestURL(), serve para construir a URL que gerou a requisio
ao Servlet, incluindo as informaes de esquema, protocolo, mtodo etc. Essa funo
deve ser chamada diretamente a partir da classe HttpUtils do pacote javax.servlet.http,
pois trata-se de um mtodo esttico dessa classe.
Agregando, ento, essas novas funes ao Servlet ServletInfoReq, temos o cdigo a
seguir:
77
78
79
Nesse formulrio, existem 3 parmetros que sero enviados junto com a requisio
ao servidor quando clicamos no boto Enviar: nome, cores e env. Em particular, o
parmetro cores pode estar associado a mais de um valor, dependendo de quantas
cores forem selecionados pelo usurio que visitar essa pgina.
Uma outra forma de enviar parmetros a sua concatenao diretamente no path da
requisio, bastando para isso acrescentar o caractere ? ao final do path, seguido de
pares <nome do parmetro>=<valor do parmetro>, separados pelo caractere &. Poderiamos, por exemplo, simular um envio de informaes do formulrio anterior atravs do seguinte path de requisio:
/livroservlets/ServletParamsReq/?nome=meunome&cores=azul&cores=preto&env=Enviar
Nesse caso, todo o texto que segue o caractere ? chamado de texto da query.
importante observar que os nomes e valores dos parmetros contidos nesse texto
devem estar codificados no formato MIME x-www-form-urlencoded.
Infelizmente, um estudo mais aprofundado da linguagem HTML e do protocolo HTTP
foge ao escopo desse livro, sendo deixado para o leitor a opo de consultar a literatura especfica (como os guias de HTML e HTTP da editora Novatec) para maiores
esclarecimentos.
O primeiro mtodo para a obteno de parmetros da requisio o mtodo getParameter(): ele recebe um nome de parmetro e retorna o valor associado a esse nome
de parmetro.
80
81
82
83
Servlet ServletVerAccept
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
84
METHOD=POST ACTION=/livroservlets/ServletUploadArq/
ENCTYPE=multipart/form-data>
Nesse formulrio de exemplo, o campo arquivo do tipo file; esse campo permite
que seja selecionado um arquivo do disco local que ser enviado junto com a requisio. Vale a pena observar tambm que existe um atributo adicional ENCTYPE, com
contedo multipart/form-data, que deve ser especificado junto ao elemento FORM.
A maneira mais fcil de se tratar esse tipo de parmetro de requisio em um Servlet
utilizando classes prontas de terceiros. Um exemplo de uma biblioteca que pode
ser utilizada para esse tipo de tratamento pode ser encontrada no endereo http://
sourceforge.net/projects/multpartrequest/.
O servlet ServletUploadArq a serguir utiliza essa biblioteca para tratar arquivos carregados pelo formulrio HTML do exemplo anterior.
Servlet ServletUploadArq
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import http.utils.multipartrequest.ServletMultipartRequest;
import http.utils.multipartrequest.MultipartRequest;
// Trata arquivos transferidos do cliente para o servidor
public class ServletUploadArq extends HttpServlet {
public void doPost(HttpServletRequest p_request, HttpServletResponse p_response)
throws IOException {
PrintWriter l_pw = p_response.getWriter ();
// Obtendo informaes sobre o arquivo carregado
// O primeiro parmetro a requisio, o segundo o nome de um diretrio
// temporrio onde devero ser armazenados os arquivos carregados no servidor,
// o terceiro o tamanho mximo em bytes permitidos, e o quarto pode
// definir o encoding a ser utilizado pelo parser (o default ISO-8859-1)
MultipartRequest l_parser = new ServletMultipartRequest(p_request,
C:\\temp, MultipartRequest.MAX_READ_BYTES, null);
String l_nomeArq = l_parser.getBaseFilename(arquivo);// Nome do arquivo
// Tamanho do arquivo
String l_tamArq = Long.toString(l_parser.getFileSize(arquivo));
85
No Servlet anterior, usamos alguns dos mtodos disponveis na biblioteca MultipartRequest. Para conhecer todos as suas funcionalidades, voc deve fazer o download
da biblioteca, e observar a documentao de sua API.
Embora estejamos falando desses mtodos pela primeira vez nesse captulo, exemplos e uma explicao mais detalhada de seu uso sero apresentados no Captulo 8
Modelo MVC.
86
Captulo 6
Servlets Cookies e Sesses
Nesse captulo so explorados os conceitos de Cookies e Sesses: atravs dessas tcnicas, veremos como possvel armazenar informaes sobre os usurios que utilizam nossas aplicaes.
87
Se voc tentar abrir essa pgina em um browser, voc poder observar que o campo
contador no visvel; por outro lado, o nome e valor desse campo sero recebidos
normalmente como um parmetro de requisio pelo seu Servlet.
Assim, podemos construir o Servlet a seguir para contar o nmero de requisies
recebidas de cada cliente:
Servlet ServletContadorReq
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
88
O Servlet ServletContadorReq anterior usa o campo escondido contador para armazenar o valor do contador na ltima requisio recebida, sendo que esse valor repassado de volta para o Servlet cada vez que o cliente pressiona o boto Atualizar.
Assim como acontece nesse Servlet, voc pode utilizar campos escondidos de formulrios HTML para armazenar informaes e fazer com que sejam passadas para seus
Servlets junto com as requisies futuras recebidas.
Por outro lado, esse mtodo tem uma grande desvantagem: para utiliz-lo, voc precisa garantir que, uma vez armazenado um valor em um campo escondido, todas as
requisies recebidas carregaro esse parmetro junto.
Isso pode gerar um grande trabalho na construo de sua aplicao, alm de no
funcionar em todos os casos: se o usurio de sua aplicao sair de sua pgina, ou at
mesmo usar os botes de navegao de seu browser (como o boto de voltar, por
exemplo), ele automaticamente ir perder os ltimos parmetros definidos.
89
Servlet ServletContadorReqMod
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
90
6.4 Cookies
Para resolver esse problema da persistncia das informaes associadas a um cliente,
necessria a utilizao de Cookies.
Cookies so pacotes de dados, gerados pelo servidor, e que so enviados junto com
a resposta de uma requisio, ficando armazenadas pelo browser do usurio. Posteriormente, a cada requisio enviada, o browser anexa tambm as informaes desses Cookies, permitindo que o servidor recupere os valores definidos anteriormente.
Um estudo completo de Cookies foge ao escopo desse livro; para obter mais detalhes
sobre eles, deve-se consultar a RFC 2109 (mais informaes no site http://
www.apps.ietf.org/rfc/rfc2109.html), que contm sua especificao.
Por outro lado, vale a pena conhecer os principais atributos de um Cookie; alm de
um nome, que identifica o Cookie para um determinado servidor e path nesse servidor, e o valor, que contm os dados em si, um Cookie possui tambm alguns atributos
adicionais:
Comentrio (Comment) Deve conter um texto descrevendo o propsito e funo do Cookie;
Perodo de expirao (MaxAge) Determina por quanto tempo (em segundos) o
Cookie ser vlido;
Domnio (Domain) Por default, uma vez definido, um Cookie s retornado
junto com requisies para o mesmo servidor que o gerou. Esse atributo permite,
por outro lado, que esse Cookie seja enviado para todos os servidores abaixo de
um mesmo domnio (conforme especificado na RFC 2109);
Caminho (Path) Por default, uma vez definido, um Cookie s passado junto
com as requisies para os recursos abaixo do diretrio virtual do recurso que
gerou o Cookie. Se esse caminho for definido, por outro lado, o Cookie passa a
ser enviado junto com as requisies para qualquer recurso abaixo caminho especificado;
A API de Servlets disponibiliza uma classe especial para representar um Cookie, a
classe javax.servlet.http.Cookie, sendo que os mtodos dessa classe permitem definir
/ recuperar os valores de seus diversos atributos.
91
Para usar um Cookie, primeiro devemos cri-lo, passando como parmetros de seu
construtor o nome e valor do Cookie, e, em seguida, devemos definir seus atributos.
Finalmente, o Cookie deve ser adicionado ao objeto HttpServletResponse para que
seja enviado para o browser do usurio.
92
93
p_response.addCookie(l_cookie);
94
A primeira assinatura retorna sempre um objeto da sesso, sendo que esse objeto
pode ter sido criado nesse instante, ou ter sido criado em uma requisio anterior (ou
seja, j havia uma sesso criada).
A segunda assinatura, por sua vez, admite um parmetro que, se for true, faz com que
o mtodo tenha o mesmo comportamento da primeira assinatura. Caso contrrio, o
mtodo pode retornar null: se ainda no houver uma sesso criada, ao invs de criar
uma nova sesso, o mtodo retorna null.
95
}
else
{
// Sesso ainda no foi criada, necessrio se criar uma nova sesso.
}
else
{
// A sesso j havia sido criada em uma requisio anterior;
// cdigo para tratar esse outro caso
96
Os primeiros quatro mtodos apresentados permitem gerenciar os objetos que queremos associar a sesso do usurio de forma similar a manipulao de uma Hashtable. Dessa forma, para cada objeto que queremos armazenar na sesso HTTP, ns
devemos associar um nome de atributo, e manipular o objeto como valor desse atributo.
Assim, se quisermos definir um atributo de sesso de nome Contador, contendo o
valor do contador de requisies usados nos Servlets ServletContadorReq, podemos
utilizar o seguinte trecho de cdigo:
Para recuperar o valor desse atributo posteriormente, podemos utilizar esse outro
trecho de cdigo:
97
Servlet ServletInfoSessao
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
98
As duas primeiras funes permitem, respectivamente, obter e definir o perodo mximo de inatividade em segundos antes que o ServletContainer invalide a sesso do
usurio, e o terceiro mtodo permite que essa sesso seja expirada (ou invalidada)
explicitamente pela aplicao.
99
Servlet FormLogin
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
100
ServletLogin
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
101
//
//
//
//
//
102
Servlet MenuPrincipal
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
//
//
//
//
//
103
Caso a aplicao venha a ter mais Servlets autenticados (que s podero ser acessados aps o login do usurio), pode valer a pena criar uma hierarquia de classes para
facilitar o processo de desenvolvimento.
Assim, podemos criar uma classe abstrata ServletLogado que faz a validao da sesso do usurio, verificando se o usurio j efetuou o login, e, se isso no tiver acontecido, redirecionando a requisio para o Servlet FormLogin.
Servlet ServletLogado
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
104
Utilizando a classe anterior, podemos criar tantos Servlets autenticados quanto quisermos: basta que esses Servlets estendam a classe ServletLogado e implementem o
mtodo doLoggedGet(), em vez do mtodo doGet(). Poderamos, por exemplo, implementar o Servlet MenuPrincipal da seguinte forma:
Servlet MenuPrincipal
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
105
106
Captulo 7
Pginas JSP
Nos quatro captulos anteriores, exploramos com detalhes como um Servlet pode
tratar uma requisio HTTP e gerar sua resposta.
Infelizmente, as aplicaes que pudemos desenvolver at agora tem uma sria limitao inerente a prpria tecnologia de Servlets: a formatao do contedo da resposta
est totalmente integrada a programao da lgica da aplicao. A tecnologia de pginas JSP, que estudaremos nesse captulo, nos ajudar a transpor essa limitao.
107
108
Todo esse processo faz com que o desenvolvedor tenha um grande trabalho cada vez
que a formatao da pgina precise ser modificada, tornando esse processo lento e
pouco flexvel.
109
%>
</BODY></HTML>
%>
Desde que esse elemento no seja alterado, podemos incluir / alterar livremente a
formatao da pgina sem afetar o funcionamento da aplicao. Podemos, portanto,
modificar essa pgina de maneira a ter a segunda verso do Servlet apresentado na
seo anterior:
Aps fazer essa modificao, ao contrrio do que acontece quando se trabalha diretamente com Servlets, voc no precisa recompilar a aplicao, essa modificao j
passa a ser automaticamente visvel para os usurios.
110
_value = null;
try {
if (_jspx_inited == false) {
synchronized (this) {
if (_jspx_inited == false) {
_jspx_init();
_jspx_inited = true;
}
}
}
111
// end
// begin [file=/pag1.jsp;from=(1,24);to=(1,51)]
out.print(request.getRemoteAddr ());
// end
// HTML // begin [file=/pag1.jsp;from=(1,53);to=(2,14)]
out.write(\\r\n</BODY></HTML>);
// end
} catch (Throwable t) {
if (out != null && out.getBufferSize() != 0)
out.clearBuffer();
if (pageContext != null) pageContext.handlePageException(t);
} finally {
if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext);
}
}
}
O Page Compiler tambm verifica a data de alterao do arquivo que contm a pgina JSP: caso essa data se modifique, o processo de compilao executado novamente para garantir que modificaes feitas na pgina sejam visveis para os usurios
da aplicao.
Devido a todo esse processo de compilao / recompilao, voc poder observar
que o primeiro acesso aps a criao ou modificao de uma pgina JSP sempre
mais lento que os acessos seguintes (at que haja uma modificao no contedo da
pgina).
112
%>
Onde o contedo do elemento dinmico est delimitado pelos caracteres <%= e %>.
Este apenas um tipo de elemento dinmico, chamado comumente de expresso.
Alm desse, existem outros 4 tipos principais de elementos dinmicos que podem
estar presentes em uma pgina JSP: diretivas, scriptlets, declaraes e JavaBeans.
As sees seguintes iro apresentar, de maneira mais detalhada, cada um desses tipos
de elementos dinmicos que podero ser utilizados por voc em suas pginas JSP.
7.6 Diretivas
O primeiro tipo de elemento dinmico que iremos estudar ser a diretiva.
O formato bsico de uma diretiva o seguinte:
Onde a palavra diretiva deve ser substituda por page, include ou taglib. Para cada um
desses tipos de diretivas, existem conjuntos de atributos especficos utilizados para
parametrizar a diretiva.
113
O atributo seguinte, import deve ser utilizado para indicar pacotes a serem importados no Servlet que ser gerado (via declarao import). Assim, devemos indicar por
meio desse atributo todos os pacotes que estaremos utilizando na programao de
nossa pgina JSP. Se quisermos utilizar a classe Vector do pacote java.util, e as classes
que esto no pacote java.io, por exemplo, poderamos declarar a diretiva page com
os seguintes atributos:
Finalmente, o atributo errorPage serve para indicar a pgina JSP a ser exibida em caso
de erro no processamento da pgina corrente. A pgina JSP que for exibir o erro
deve, por sua vez, declarar a diretiva page com o atributo isErrorPage definido explicitamente como true.
Usando todos esses atributos da diretiva page, poderamos implementar uma pgina
JSP simples de impresso da data corrente da seguinte forma:
114
A vantagem de utilizar essa diretiva est no fato de que voc pode manter contedo
esttico ou dinmico comum a diversas pginas JSP em arquivos separados, includos, atravs dessa diretiva, conforme a necessidade. Podemos, por exemplo, construir novas pginas JSP que incluem o arquivo de cabealho cabecalho.jsp e
rodape.html: se for necessrio mudar o contedo do cabealho ou do rodap, no
precisaremos editar todas as nossas pginas, apenas o contedo desses arquivos.
115
7.7 Expresses
Em todas as pginas JSP construdas at agora utilizamos um elemento dinmico chamado de Expresso: esse elemento serve para imprimir o resultado String de uma
expresso Java.
Sua sintaxe bsica a seguinte:
Obviamente, esse elemento pode ser utilizado para imprimir o contedo de uma
varivel do tipo String, ou at mesmo de uma constante String. Supondo que l_texto
seja uma varivel String, por exemplo, poderamos incluir o seguinte elemento em
uma pgina JSP para imprimir o contedo da varivel:
Por outro lado, podemos formar expresses mais complexas, como na pgina JSP
que imprime a data corrente, desde que o resultado dessas expresses sejam Strings.
7.8 Scriptlets
Uma expresso JSP possibilita o processamento de uma expresso Java, e a impresso de seu resultado junto com o contedo da pgina JSP. Embora esse recurso seja
bastante poderoso, ele no serve para situaes quando precisamos efetuar um processamento mais complexo, utilizando, por exemplo, diversos blocos de cdigo Java.
Um Scriptlet permite a insero de um bloco de cdigo Java diretamente no corpo
da pgina JSP. Sua sintaxe a seguinte:
116
Nesse exemplo de pgina JSP, utilizamos um Scriptlet para definir variveis cujos
contedos so posteriormente impressos por expresses JSP. De fato, podemos combinar o uso de Scriptlets e expresses, desde que, obviamente, seja preservada a semntica Java (ou seja, variveis sejam utilizadas somente aps serem declaradas, por
exemplo).
Construmos, a seguir, um exemplo um pouco mais elaborado de pgina JSP utilizando Scriptlets: trata-se de um formulrio HTML para input do ms do aniversrio do
usurio, sendo que Scriptlets so utilizados para construir os meses possveis da caixa de seleo do formulrio.
117
interessante observar nesse exemplo a combinao de Scriptlets, expresses e elementos estticos da pgina: o bloco de cdigo Java iniciado no primeiro Scriptlet da
pgina no finalizado nesse prprio Scriptlet, mas sim em um outro Scriptlet, inserido aps a impresso de um contedo esttico e de 2 expresses JSP.
%>
</BODY></HTML>
Classe
request
javax.servlet.http.HttpServletRequest
response
javax.servlet.http.HttpServletResponse
out
javax.servlet.jsp.JspWriter
session
javax.servlet.http.HttpSession
application javax.servlet.ServletContext
config
javax.servlet.ServletConfig
Voc deve utilizar esses objetos implcitos da mesma maneira como voc utilizaria os
objetos das respectivas classes na programao de seus Servlets. Em particular, o objeto implcito out, da classe JspWriter, prov funcionalidade semelhante a da classe
PrintWriter que utilizamos na maior parte dos exemplos com Servlets desse livro.
118
Podemos tambm construir a pgina JSP procmesaniv.jsp que far o tratamento dos
dados submetidos pelo formulrio da pgina formmesaniv.jsp, utilizando os objetos
implcitos request e response:
Pgina JSP que faz o tratamento dos dados submetidos pelo formulrio
formmesaniv.jsp (procmesaniv.jsp)
<%
Integer l_mes = null;
try {
l_mes = new Integer(request.getParameter(MES));
} catch(Exception p_e) {
l_mes = null;
}
if((l_mes == null) || (l_mes.intValue () < 1) || (l_mes.intValue () > 12))
response.sendRedirect(formmesaniv.jsp);
%><%@ include file=cabecalho.jsp %>
<%
if(l_mes.intValue () == Calendar.getInstance ().get(Calendar.MONTH) + 1)
out.println(Parabns, esse o ms de seu aniversrio!);
else out.println(Infelizmente, esse no o ms de seu aniversrio; seu
aniversrio no ms \ + l_mes.toString () + \.);
%>
<%@ include file=rodape.html %>
119
7.10 Declaraes
Esse tipo de elemento dinmico especial de uma pgina JSP serve para definir cdigos Java que devero ficar fora do mtodo de atendimento das requisies (o mtodo
service (), no mais alto nvel). Assim, esse elemento serve para declarar variveis de
classe (estticas), variveis de instncia, ou at mesmo novos mtodos.
Sua sintaxe a seguinte:
da pgina> %>
Em particular, esse elemento deve ser utilizado para definir os mtodos jspInit () e
jspDestroy () (mencionados na seo 7.4) caso voc opte por incluir um cdigo de
inicializao ou finalizao da pgina JSP.
A pgina JSP seguinte aperfeioa um pouco mais nossa pgina input do ms de aniversrio do usurio, imprimindo o nome do ms por extenso na caixa de seleo do
formulrio. O array de mapeamento do nome do ms declarado em um elemento
de declarao JSP, para evitar a alocao de memria adicional a cada atendimento
de requisio.
120
7.11 Comentrios
Existem, na verdade, dois tipos de comentrios que voc poder utilizar em sua pgina JSP.
Um primeiro tipo o comentrio HTML: independente de ser uma pgina JSP (ou
seja, mesmo sendo uma pgina HTML esttica), voc pode utilizar esse elemento
para incluir um texto que no aparecer diretamente para o usurio que estiver visualizando sua pgina. O usurio poder, por outro lado, ler o comentrio caso visualize o fonte da pgina.
A sintaxe de um comentrio HTML a seguinte:
<! <comentrio> >
O outro tipo de comentrio que voc poder utilizar um comentrio JSP: ao contrrio de um comentrio HTML, o texto escrito por voc no aparecer para o usurio
mesmo que ele visualize o fonte da pgina. A sintaxe de um comentrio JSP a seguinte:
<% <comentrio> %>
121
Pgina JSP com exemplo de uso dos dois tipos de comentrios (HTML e JSP)
<HTML><BODY>
Exemplo de uso dos tipos de comentrios de uma pgina JSP
<!Esse comentrio ir aparecer no fonte da pgina >
<% Esse comentrio no ir aparecer no fonte da pgina %>
</BODY></HTML>
7.12 JavaBeans
JavaBeans so, na verdade, classes Java reutilizveis que seguem algumas regras bem
definidas para nomeao de seus mtodos e variveis. A idia por trs do uso desses
JavaBeans em nossas pginas JSP, que eles encapsulem a lgica de nossa aplicao,
separando-a do restante da pgina.
Embora a definio exata de JavaBeans fuja ao escopo desse livro, para efeitos de uso
do uso dessas classes em pginas JSP, necessrio que se siga algumas regras bsicas
no seu desenvolvimento:
1) O construtor da classe, se declarado, no deve receber nenhum argumento.
2) Podem existir um ou mais mtodos pblicos para a definio de valores de propriedades do bean; esses mtodos so chamados de mtodos setter.
3) Podem existir um ou mais mtodos pblicos para a obteno de valores de propriedades do bean; esses mtodos so chamados de mtodos getter.
Temos, a seguir, uma exemplo de classe JavaBean que implementa uma lgica bsica
de nossa aplicao:
// Valor unitrio
private int m_PrecoUnid = 10;
122
Uma vez construdo o JavaBean, para referenci-lo em nossa pgina JSP, devemos
utilizar o elemento dinmico <jsp:useBean>, que tem a seguinte sintaxe:
<jsp:useBean id=<id do Bean> scope=<escopo do Bean> class=<classe do Bean>/>
Na sintaxe anterior, <id do Bean> deve conter o nome do JavaBean como ele ser
referenciado na pgina e <classe do Bean> deve conter o nome da classe incluindo
informaes
sobre
seu
pacote
(como
por
exemplo,
com.minhaempresa.PrecoProdBean).
O atributo scope, por outro lado, deve conter um dos seguintes valores: page (pgina; o valor default caso esse atributo no seja explicitamente definido), request
(requisio), session (sesso) ou application (aplicao); esse valor indica o escopo
dentro do qual o JavaBean ser visvel. Assim, se o escopo de um JavaBean for de
sesso, ele ser armazenado como um atributo de sesso, podendo ser referenciado
em todas as requisies dessa mesma sesso.
Se quisssemos utilizar o JavaBean PrecoProdBean em uma pgina JSP, por exemplo,
poderamos incluir as seguintes linhas de cdigo:
123
124
Da mesma forma como existe um elemento dinmico para referenciar mtodos getter
de JavaBeans, tambm existe um elemento dinmico para os mtodos setter. A sintaxe desse elemento :
<jsp:setProperty name=<nome do JavaBean> property=<nome da propriedade>
value=<valor da propriedade> />
Podemos, ento, modificar o exemplo de pgina JSP anterior para definir o valor do
preo unitrio do produto antes de exibi-lo:
Esse elemento de referncia a mtodos setter de JavaBeans admite, ainda, outra sintaxe de uso:
<jsp:setProperty name=<nome do JavaBean> property=<nome da propriedade>
param=<nome do parmetro> />
Nessa sintaxe, o valor que ser recebido pelo JavaBean para a propriedade em questo, ser o valor do parmetro <nome do parmetro>, conforme recebido pela requisio HTTP.
125
Nesse exemplo de Descritor de Biblioteca de Tags, podemos observar diversos elementos: os elementos tlibversion, shortname e info contm, respectivamente, a verso da biblioteca de Tags, seu nome (conforme referenciado posteriormente na pgina JSP) e um texto informativo sobre a biblioteca.
126
<web-app>
<taglib>
<taglib-uri>/minhabibliotags</taglib-uri>
<taglib-location>/WEB-INF/minhabibliotags.tld</taglib-location>
</taglib>
</web-app>
127
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
// Classe que gerencia Tag TagOlaMundo, utilizada em pginas JSP de nossa aplicao
public class TagOlaMundo implements Tag {
PageContext m_PageContext;
// Implementao default
public void setParent(Tag p_tag) {
}
// Implementao default
public void setPageContext(PageContext p_pageContext) {
m_PageContext = p_pageContext;
}
// Implementao default
public void release () {
}
// Implementao default
public Tag getParent () {
return null;
}
128
Nessa pgina, primeiro inclumos um elemento taglib, cujo atributo uri contm a URI
especificada no Deployment Descriptor (que por sua vez faz o mapeamento com o
arquivo .tld correto), e cujo atributo prefix especifica o prefixo a ser utilizado
antes de cada Tag.
Na linha seguinte, temos a utilizao da Tag em si: h um prefixo, conforme especificado pelo atributo prefix do elemento taglib, seguido da Tag, que dever ter sido
declarada no descritor de bibliotecas de Tags. Ao encontrar esse elemento, o container ir carregar a classe que gerencia esse Tag, e chamar os mtodos pertinentes.
importante observar que no existe nenhum contedo para a tag
minhaLib:TagOlaMundo; a notao abreviada <minhaLib:TagOlaMundo/> equivalente se escrever <minhaLib:TagOlaMundo></minhaLib:TagOlaMundo>. Caso houvesse algum contedo para essa tag, teramos que utilizar um valor diferente para o
atributo bodyContent no descritor de bibliotecas de Tags, e poderamos considerar a
implementao da interface BodyTag em vez de Tag para a classe TagOlaMundo.
129
Embora voc possa construir suas prprias bibliotecas de Tags, normalmente mais
prtico e fcil utilizar uma biblioteca j pronta, como o Apache Jakarta Struts, disponvel no site http://jakarta.apache.org/struts/.
130
Captulo 8
Modelo MVC
Nesse captulo apresentamos o modelo MVC: atravs desse modelo, procuramos
mostrar como podemos separar o trabalho de desenvolvimento do trabalho de formatao e layout da aplicao.
131
Esses mtodo retorna uma referncia para um objeto que implementa a interface
javax.servlet.RequestDispatcher e que atua como um wrapper para o recurso indicado no path passado como parmetro para a funo. Assim, se voc passar como
parmetro, por exemplo, o caminho relativo de uma pgina JSP, esse mtodo retornar uma referncia a um wrapper dessa pgina JSP.
Esse wrapper, por sua vez, disponibiliza um mtodo forward () que permite que
voc repasse a requisio para o recurso encapsulado pelo wrapper.
132
Podemos, dessa forma, implementar um Servlet de exemplo que no faz nada, apenas repassa todas as requisies recebidas para uma pgina JSP.
No Servlet anterior, existe um ponto importante que deve ser observado: o path passado como parmetro para a funo getRequestDispatcher () referencia um recurso
contido na mesma aplicao Web do Servlet, e, dessa forma, deve excluir a parte
referente ao diretrio virtual da aplicao (ou seja, esse path no deve ser escrito
como /livroservlets/OlaMundo.jsp). Alm disso, importante observar que o mtodo
forward poder lanar uma exceo: uma das causas pode ser uma exceo lanada
pelo prprio recurso referenciado pelo RequestDispatcher.
Podemos tambm implementar a pgina JSP referenciada no Servlet anterior como:
133
removeAttribute(java.lang.String p_attributeName);
Esses mtodos funcionam de maneira semelhante aos mtodos da classe ServletContext apresentada na seo 3.6: eles permitem definir, remover ou obter valores de
atributos de uma requisio. Esses valores de atributos no precisam necessariamente ser objetos String, eles podem ser objetos quaisquer Java.
Para exemplificar o uso dessas funes, vamos implementar novamente nosso Servlet ServletRepassaReqs da seguinte forma:
Segunda verso para Servlet que repassa requisies para uma pgina JSP
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
134
A pgina JSP ApresentaMensagem.jsp, por sua vez, pode ser implementada como:
Dessa forma, alm de repassar a requisio do Servlet para a pgina JSP, estamos
tambm passando objetos, definidos no Servlet, para a pgina JSP. Esse mecanismo
funciona graas aos atributos de requisio.
135
ServletLogin
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
1.
136
137
Essas pginas JSP podero ser trabalhadas pelos responsveis pelo layout e formatao de nossa aplicao, sem afetar a lgica e o trabalho de desenvolvimento.
138
Captulo 9
Tpicos adicionais
J apresentamos nos captulos anteriores as principais caractersticas e funcionalidades referentes ao desenvolvimento de aplicaes Web com Servlets e pginas JSP.
Estaremos, nesse captulo, apresentando alguns tpicos adicionais que complementaro todo o conhecimento que voc obteve at agora: voc ir conhecer arquivos
WAR, mecanismos de autenticao HTTP e pools de conexes a uma base de dados.
139
140
//
//
//
//
141
Os elementos apresentados na listagem anterior, por exemplo, definem que os acessos a URL /livroservlets/ServletAutenticacaoHTTP devem ser autenticados. Em particular, o elemento role-name define o grupo de usurios que deve ter acesso a URL
em questo: os diversos grupos, com seus respectivos usurios / senhas, devem, nesse caso, ser configurados no arquivo conf\tomcat-users.xml abaixo do diretrio de
instalao do Apache Tomcat.
Se voc optar por utilizar esse mtodo de autenticao, voc deve chamar em seu
cdigo os mtodos getRemoteUser () e getUserPrincipal (), da classe HttpServletRequest, para obter o nome do usurio e seu grupo.
Mais detalhes com relao a autenticao baseada em elementos de segurana do
Deployment Descriptor da aplicao podem ser encontrados na especificao de
Servlets.
142
import java.io.*;
import java.sql.*;
import java.util.*;
import java.util.Date;
// Nome da aplicao
= null;
// Tamanho mximo desse pool: dessa forma evitamos que, caso haja
// um erro na aplicao, novas conexes sejam abertas indefinidamente
// at derrubar o servidor de banco de dados.
private int m_TamMaxPool = 0;
143
// Driver jdbc
m_Url = p_url;
m_Usuario = p_usuario;
m_Senha = p_senha;
m_TamMaxPool = p_tamMaxPool;
m_Timeout = p_timeout;
144
try {
if (l_con.isClosed ()) l_con = null;
} catch (Exception p_e) { l_con = null; }
145
// Libera uma conexo previamente alocada (retorna essa conexo para o pool)
// OBS: esse mtodo precisa ser synchronized para evitar problemas de
// concorrncia no acesso ao Pool
public synchronized void liberaConexao(Connection p_con) {
if(m_Pool != null)
{
try {
if(!p_con.isClosed ()) m_Pool.addElement(p_con);
} catch (Exception p_e) {}
m_NumConsAlocadas -;
}
}
146
m_Pool.removeAllElements ();
try {
DriverManager.deregisterDriver(m_DriverJdbc);
} catch(Exception p_e) {
throw new PoolConBDException(m_Aplic, no foi possvel
descadastrar driver jdbc);
}
}
}
}
// Hashtable com mapeamento entre nomes das aplicaes e seus respectivos pools
private static Hashtable m_PoolsAplics = new Hashtable ();
// Veja PoolConBDAplic.alocaConexao
public static Connection alocaConexao(String p_aplic) throws PoolConBDException
{
PoolConBDAplic l_pool = (PoolConBDAplic) m_PoolsAplics.get(p_aplic);
if(l_pool != null) return l_pool.alocaConexao ();
147
// Veja PoolConBDAplic.obtemNumConsAlocadas
public static int obtemNumConsAlocadas(String p_aplic)
{
PoolConBDAplic l_pool = (PoolConBDAplic) m_PoolsAplics.get(p_aplic);
// Veja PoolConBDAplic.liberaConexao
public static void liberaConexao(String p_aplic, Connection p_con)
{
PoolConBDAplic l_pool = (PoolConBDAplic) m_PoolsAplics.get(p_aplic);
if(l_pool != null) l_pool.liberaConexao(p_con);
}
// Vide PoolConDBAplic.destroiPool
public static synchronized void destroiPool(String p_aplic)
throws PoolConBDException
{
PoolConBDAplic l_pool = (PoolConBDAplic) m_PoolsAplics.get(p_aplic);
if (l_pool != null)
{
l_pool.destroiPool();
m_PoolsAplics.remove(p_aplic);
}
}
}
interessante observar que a classe anterior permite que sejam configurados / utilizados no apenas um nico pool de conexes a base de dados, mas sim diversos
pools: como so declaradas variveis estticas, todas as aplicaes Web sendo executadas na mesma instncia da mquina virtual Java iro compartilhar esses mesmos
objetos. Sendo assim, necessrio prever a alocao e liberao de conexes por
aplicao, de forma que o funcionamento de uma aplicao no interfira no funcionamento de outra.
148
import javax.servlet.*;
import javax.servlet.http.*;
import com.livroservlets.*;
149
+ p_e.getMessage () + \);
}
}
try {
l_pw.println(Alocando conexo com a base de dados ... <BR>);
Connection l_con = PoolConBD.alocaConexao(LivroServlets);
l_pw.println(</BODY></HTML>);
l_pw.flush ();
}
}
150
Parte II
Desenvolvimento de Aplicaes
Distribudas Utilizando EJB
Esta parte foca no paradigma de desenvolvimento de aplicaes distribudas, destacando a evoluo das tcnicas de desenvolvimento, desde a programao estrutural
at o atual uso de sistemas distribudos. So detalhados os componentes de negcio
Enterprise JavaBeans e os recursos oferecidos no uso desta tecnologia.
151
152
Captulo 10
Novas Tcnicas de Desenvolvimento
Este captulo apresenta um histrico evolutivo das tcnicas de desenvolvimento de
sistemas. Destacando, principalmente, o paradigma baseado no desenvolvimento de
aplicaes distribudas.
153
Servidor Web
CGI
Servidor
154
Servidor Web
Script
Servidor
155
Computador
Virtualmente nico
Servidor
156
Sistema
Centralizado
Sistema
Distribudo
X
PC
Workstation
PC
PC
...
Workstation
Workstation
Workstation
...
Servidor
Servidor
Servidor
157
Mdulo A
Mdulo B
Servidor
Servidor
Mdulo C
Servidor
Mdulo A
Servidor
Mdulo B
Mdulo C
Servidor
158
Mdulo A
Servidor
Mdulo B
Servidor
Mdulo C
Servidor
Figura 10.8 Redistribuio dos mdulos da figura 10.7, gerada pela adio de
um novo computador no ambiente.
Caso a aplicao fique muito carregada podemos redistribuir seus mdulos B e C,
conforme a figura 10.9.
Sistema Distribudo
Mdulo A
Servidor
Mdulo B
Mdulo C
Servidor
159
160
Mdulo A
Servidor
Mdulo B
Servidor
Mdulo C
Servidor
161
Java/RMI
Com o desenvolvimento da plataforma Java, a Sun Microsystems observou um novo
horizonte no desenvolvimento de aplicaes em rede de computadores e iniciou o
desenvolvimento de um suporte para objetos distribudos chamado Java/RMI. RMI
significa Remote Method Invocation, ou seja, a invocao de mtodos remotos. Este
suporte simplificou a construo de aplicaes distribudas, contudo funciona apenas para a linguagem Java, ao contrrio de Corba.
Aplicao Distribuda
Middleware CORBA
Servidor
Servidor
Servidor
J2EE
Observando o lado promissor da tecnologia Java/RMI a Sun Microsystems desenvolveu um padro chamado J2EE (Java 2 Enterprise Edition). Com isto, a empresa segmentou a tecnologia Java e comeou cada vez mais a se preocupar com o mercado
de aplicaes distribudas.
162
Microsoft .NET
Observando a conquista do mercado pelo J2EE, a Microsoft lanou sua prpria tecnologia para o desenvolvimento de aplicaes distribudas, a .NET. A .NET no um
padro aberto tal como Corba e J2EE, por isto, somente a Microsoft a oferece.
163
164
Captulo 11
J2EE e Enterprise JavaBeans
Este captulo apresenta os principais conceitos da plataforma J2EE (Java 2 Enterprise
Edition), que foi desenvolvida para suportar aplicaes distribudas construdas na
linguagem Java.
165
166
Cliente
HTML
Container
Pgina
Html
Servidor J2EE
Servlet
JSP
Container Web
App-Client
Container
EIS
Stand
Alone
EJB
Applet
Container
Container EJB
Applet
167
Servidor
Cliente
RMI
Skeleton
Stub
RMI
Objeto
169
java.rmi.Remote
<<Interface>>
javax.ejb.EJBHome
getEJBMetaDat a()
getHomeHandle()
remove()
remove()
java.rmi.Remote
<<Interface>>
javax.ejb.EJBObject
getEJBHome()
getHandle()
getPrimaryKey()
is Ident ical()
remove()
170
<<Interface>>
javax.ejb.EJBLocalHome
remove()
Figura 11.5 - Diagrama de Classes UML da Interface LocalHome
<<Interface>>
javax.ejb.EJBLocalObject
getEJBLocalHome()
getPrimaryKey()
remove()
isIdent ical()
Figura 11.6 - Diagrama de Classes UML da Interface Local
Para um EJB do tipo Message-Driven Bean, no precisamos implementar nenhuma
dessas interfaces porque, este tipo de Enterprise JavaBean apresenta um comportamento diferente de um Session Bean e um Entity Bean, proporcionando processamento assncrono. O que precisamos fazer implementar uma interface de Listener
que ser associado ao MOM.
<<Interface>>
javax.jms.MessageListener
onMessage()
Figura 11.7 Diagrama de Classes UML da Interface Listener.
171
172
Servidor J2EE
Cliente
EJBHome stub
Home Interface
Container EJB
Home Interface
EJB
Home
EJBObject stub
Remote Interface
Remote Interface
Bean
EJB
Object
Figura 11.8 Figura do cliente acessando o servidor EJB, com as classe EJB
Home e EJB Object (encapsulando o EJB).
173
174
Captulo 12
Session Beans
Este captulo apresenta os Session Beans. Estes so componentes, da plataforma J2EE,
responsveis por implementar a lgica das aplicaes. Contudo, eles apresentam
caractersticas e funcionalidades prprias, voltadas para a construo de sistemas de
alta escala.
175
H om e
R em ote
SBExampleHome
SBExample
<<instantiate>>
c reat e()
<<EJBRealizeHome>>
<<EJBReali zeRemote>>
<<EJBSess ion>>
SBExam pleBean
EJB_Context : SessionCont ext = null
SBExam pleBean()
ejbCreate()
ejbRem ove()
ejbAct ivate()
ejbPassivate()
setSessionCont ext()
import javax.ejb.*;
import java.util.*;
import java.rmi.*;
176
import javax.ejb.*;
import java.util.*;
import java.rmi.*;
Bean: SBExampleBean.
package com.novatec.book.example.ejb.session;
import javax.ejb.*;
177
Para obter este servio, o cliente deve realizar a localizao do EJB no servidor de
aplicao utilizando o seu nome JNDI, solicitar uma referncia para a interface Home
do EJB e com ela executar o mtodo de ciclo de vida: create(). Assim, o cliente ter
acesso interface Remote que apresenta os mtodos de negcio, isto , os servios
disponveis para o EJB e dessa forma, poder execut-los para as operaes desejadas.
Maiores detalhes de localizao e obteno das referncias para as interfaces sero
vistos nos exemplos mais detalhados de EJB e a utilizao de cada servio, alm de
especificar os arquivos de instalao (deployment descriptors).
At aqui introduzimos o EJB Session Bean, mas ainda no detalhamos os dois tipos
de Session Bean que sero vistos nos prximos tpicos e que so:
Session Bean Stateless
Session Bean Stateful
178
import javax.ejb.*;
/**
* Exemplo de Session Bean que apresenta os servios aos seus clientes.
* Estes servios so implementados atravs de mtodos de negcio.
* EJB do tipo Session Bean apresentam os mtodos ejbCreate() e ejbRemove(), alm
* dos mtodos ejbActivate() e ejbPassivate() para Session Beans do tipo Stateful.
*/
public class SBStatelessExampleBean implements SessionBean {
/**
* Contexto do Session Bean.
*/
private SessionContext sessionContext;
/**
* Executado pelo container aps a criao da instncia do EJB.
* @throws CreateException exceo na criao de uma entidade do EJB.
*/
public void ejbCreate() throws CreateException {
}
/**
* Utilizado pelo container para destruir a instncia do EJB.
* Para o EJB Session Bean Stateless, deve-se liberar os recursos alocados
* para este EJB neste mtodo.
*/
public void ejbRemove() {
}
/**
* Utilizado pelo container para ativar o objeto do pool de EJBs.
* Neste momento devem ser recuperados todos os recursos utilizados pelo EJB.
* Isto feito somente para Session Bean do tipo Stateful.
* Este mtodo deve ser definido para o EJB Session Bean Stateless tambm,
* apesar de no ser utilizado, pois este tipo de EJB no fica passivo.
*/
179
/**
* Utilizado pelo container para devolver o objeto ao pool de EJBs.
* Neste mtodo devem ser liberados todos os recursos alocados pelo EJB.
* Isto feito somente para Session Bean do tipo Stateful.
* Este mtodo deve ser definido para o EJB Session Bean Stateless tambm,
* apesar de no ser utilizado, pois este tipo de EJB no fica passivo.
*/
public void ejbPassivate() {
}
/**
* Configura o contexto do Session Bean.
* @param sessionContext contexto do SB.
*/
public void setSessionContext(SessionContext sessionContext) {
this.sessionContext = sessionContext;
}
Instncia do EJB
Session Bean
Stateless ainda no
existe
1. Class.newInstance()
2. setSessionContext()
3. ejbCreate()
ejbRemove()
Session Bean
Stateless pronto ou
mantido no pool de
objetos
Execuo dos
mtodos de negcio
import javax.ejb.*;
/**
* Contexto do Session Bean.
*/
private SessionContext sessionContext;
181
/**
* Utilizado pelo container para destruir a instncia do EJB.
*/
public void ejbRemove() {
}
/**
* Utilizado pelo container para ativar o objeto do pool de EJBs.
* Neste momento devem ser recuperados todos os recursos utilizados pelo EJB.
* Isto feito somente para Session Bean do tipo Stateful.
*/
public void ejbActivate() {
}
/**
* Utilizado pelo container para devolver o objeto ao pool de EJBs.
* Neste mtodo devem ser liberados todos os recursos alocados pelo EJB.
* Isto feito somente para Session Bean do tipo Stateful.
*/
public void ejbPassivate() {
}
/**
* Configura o contexto do Session Bean.
* @param sessionContext contexto do SB.
*/
public void setSessionContext(SessionContext sessionContext) {
this.sessionContext = sessionContext;
}
182
/**
* Obtm o valor do atributo name.
* @return valor do atributo name.
*/
public String getName(){
return name;
}
Instncia do EJB
Session Bean Stateful
ainda no existe
1. Class.newInstance()
2. setSessionContext()
3. ejbCreate()
ejbRemove()
ejbPassivate()
Execuo dos
mtodos de negcio
ejbActivate()
184
Captulo 13
Entity Beans
Este captulo apresenta os componentes da plataforma J2EE responsveis por oferecer persistncia aos dados das aplicaes. A persistncia a capacidade de armazenar e recuperar informaes de bancos de dados. Esta torna-se transparente atravs
dos Entity Beans.
185
H ome
Remote
EBExampleHome
EBExample
<<inst antiate>>
create()
findByPrimaryKey()
<<EJBRealizeHome>>
<<EJBRealizeRemote>>
<<EJBEntity>>
EBExampleBean
EJB_Contex t : E nt ityContext
<<EJBPrimaryKey>>
EBExampleBean()
ejbCreate()
ejbPostCreate()
ejbAc tivate()
ejbPassivate()
ejbLoad()
ejbSt ore()
ejbRemove()
setEnt ityContext()
unsetEntityCont ext()
<<EJBPrimaryKey>>
EBExamplePK
hashCode()
equals()
toString()
186
import javax.ejb.*;
/**
* Exemplo de Entity Bean BMP utilizado para mantr os dados em um meio
* persistente e apresentar as operaes sobre os atributos deste EJB.
* Observe que no Entity Bean BMP, todo o cdigo de criao (persistncia do
* objeto), remoo, atualizao etc. deve ser implementado nestes mtodos,
* ficando a cargo do programador definir a melhor forma de fazer isso.
*/
public class EBBMPExampleBean implements EntityBean {
/**
* Contexto do Entity Bean.
*/
EntityContext entityContext;
/**
* Atributo 1 a ser persistido.
*/
java.lang.String field1;
/**
* Atributo 2 a ser persistido.
*/
java.lang.String field2;
187
/**
* Executado pelo container aps a criao do EJB.
* @param untitledField1 campo persistido.
* @throws CreateException exceo na criao do objeto.
*/
public void ejbPostCreate(java.lang.String field1, java.lang.String field2)
throws CreateException {
}
/**
* Executado pelo container para remover o objeto persistido.
* @throws RemoveException
*/
public void ejbRemove() throws RemoveException {
// Deve conter o cdigo de remoo do EJB no meio de persistncia.
}
/**
* Configura o valor do atributo field1.
* @param field1 valor do atributo a ser configurado.
*/
public void setField1(java.lang.String field1) {
this.field1 = field1;
}
188
/**
* Obtm o valor do atributo field1.
* @return valor do atributo field1.
*/
public java.lang.String getField1() {
return field1;
}
/**
* Obtm o valor do atributo field2.
* @return valor do atributo field2.
*/
public java.lang.String getField2() {
return field2;
}
/**
* Implementao do mtodo de seleo do objeto pela sua chave-primria.
* @param field1 chave-primria do EJB.
* @return chave primria do EJB.
* @throws FinderException erro ao localizar o EJB.
*/
public java.lang.String ejbFindByPrimaryKey(java.lang.String field1)
throws FinderException {
/**
* Utilizado para carregar o objeto persistente do meio de persistncia
* e atualizar os dados de sua instncia.
189
/**
* Utilizado pelo container para atualizar os dados do objeto
* no meio de persistncia.
*/
public void ejbStore() {
}
/**
* Utilizado pelo container quando ativa o objeto do pool.
*/
public void ejbActivate() {
}
/**
* Utilizado pelo container quando devolve o objeto ao pool.
*/
public void ejbPassivate() {
}
/**
* Desconfigura o contexto do Entity Bean.
*/
public void unsetEntityContext() {
this.entityContext = null;
}
/**
* Configura o contexto do Entity Bean.
* @param entityContext contexto do Entity Bean.
*/
public void setEntityContext(EntityContext entityContext) {
this.entityContext = entityContext;
}
}
190
Instncia do EJB
Entity Bean BMP
ainda no existe
1. Class.newInstance()
2. setEntityContext()
unsetEntityContext()
ejbHome()
1. ejbCreate()
2. ejbPostCreate()
1. ejbPassivate()
2. ejbLoad()
ejbLoad()
ejbFind()
1. ejbStore()
2. ejbActivate()
ejbRemove()
ejbStore()
Executa os mtodos
de negcio ou
ejbFind()
191
import javax.ejb.*;
/**
* Exemplo de Entity Bean utilizado para mantr os dados em um meio persistente
* e apresentar as operaes sobre os atributos deste EJB.
* No caso do uso de Entity Bean CMP, as operaes de persistncia so
* implementadas pelo prprio container, sendo que o programador no precisa
* se precocupar com estas operaes triviais.
* Para as operaes especficas, como uma consulta com outros parmetros por
* exemplo, esta pode ser definida atravs de EQL no deployment descriptor do
* Entity Bean CMP.
*/
abstract public class EBCMPExampleBean implements EntityBean {
/**
* Contexto do Entity Bean.
*/
private EntityContext entityContext;
/**
* Cria uma instncia do objeto em memria e persiste seus dados.
* @param field1 campo a ser persistido.
* @param field1 campo a ser persistido.
* @return chave nica que identifica o objeto persistido. pode ser null.
* @throws CreateException exceo na criao do objeto.
*/
192
/**
* Executado pelo container para remover o objeto persistido.
* @throws RemoveException
*/
public void ejbRemove() throws RemoveException {
}
/**
* Configura o valor do atributo field1.
* Observe que na especificao EJB2.0, estes mtodos so implementados
* pelo prprio container.
* @param field1 valor do atributo a ser configurado.
*/
public abstract void setField1(java.lang.String field1);
/**
* Configura o valor do atributo field2.
* Observe que na especificao EJB2.0, estes mtodos so implementados
* pelo prprio container.
* @param field2 valor do atributo a ser configurado.
*/
public abstract void setField2(java.lang.String field2);
/**
* Obtm o valor do atributo field1.
* @return valor do atributo field1.
*/
193
/**
* Obtm o valor do atributo field2.
* @return valor do atributo field2.
*/
public abstract java.lang.String getField2();
/**
* Utilizado para carregar o objeto persistente do meio de persistncia
* e atualizar os dados de sua instncia.
*/
public void ejbLoad() {
}
/**
* Utilizado pelo container para atualizar os dados do objeto
* no meio de persistncia.
*/
public void ejbStore() {
}
/**
* Utilizado pelo container quando ativa o objeto do pool.
*/
public void ejbActivate() {
}
/**
* Utilizado pelo container quando devolve o objeto ao pool.
*/
public void ejbPassivate() {
}
/**
* Desconfigura o contexto do Entity Bean.
*/
public void unsetEntityContext() {
this.entityContext = null;
}
194
Instncia do EJB
Entity Bean CMP
ainda no existe
1. Class.newInstance()
2. setEntityContext()
unsetEntityContext()
ejbHome()
1. ejbCreate()
2. ejbPostCreate()
1. ejbPassivate()
2. ejbLoad()
ejbLoad()
ejbFind()
ejbSelect()
1. ejbStore()
2. ejbActivate()
ejbRemove()
ejbStore()
Executa os mtodos
de negcio ou
ejbFind() e ejbSelect()
195
196
Marido
esposa
<ejb-relationship-role-name>EsposaRelationshipRole</ejb-relationship-role<multiplicity>One</multiplicity>
<relationship-role-source>
<description>esposa</description>
<ejb-name>Esposa</ejb-name>
</relationship-role-source>
<cmr-field>
<description>marido</description>
<cmr-field-name>marido</cmr-field-name>
</cmr-field>
</ejb-relationship-role>
<ejb-relationship-role>
<description>marido</description>
name>
<ejb-relationship-role-name>MaridoRelationshipRole</ejb-relationship-role<multiplicity>One</multiplicity>
<relationship-role-source>
197
A tag cmr-field-name configura o nome do campo do EJB nos quais sero criados os
mtodos get e set que estaro disponveis na interface local, caso configuramos a
multiplicidade 1 1. Se fossemos configurar um relacionamento 1 N por exemplo,
deveramos trocar a tag multiplicity para many e acrescentar a tag cmr-field-type como
o exemlo mostra a seguir:
<cmr-field>
<description>esposa</description>
<cmr-field-name>esposa</cmr-field-name>
<cmr-field-type>java.util.Collection</cmr-field-type>
</cmr-field>
Esposa
Marido
marido
198
13.8 EJB-QL
EJB-QL EJB Query Language - ou simplesmente EQL a linguagem portvel utilizada para construir os mtodos de consulta dos componentes EJB Entity Bean CMP de
acordo com a especificao 2.x. Esta linguagem no utilizada para os componentes
EJB Entity Bean BMP, pois os mesmos utilizam a API JDBC, ou outro mecanismo de
persistncia para acesso base de dados.
EQL Queries
Um comando EJB-QL contm trs partes:
Uma clusula SELECT
Uma clusula FROM
Uma clusula opcional WHERE
199
A clusula FROM
A clusula FROM define o domnio de uma consulta. No caso de uma base de dados
relacional, a clusula FROM tipicamente restringe quais tabelas sero consultadas.
Por exemplo:
SELECT OBJECT(o)
FROM X AS o
Aqui estamos declarando uma varivel na clusula FROM. A varivel o pode ser
usada posteriormente em outras clusulas desta mesma consulta. Neste caso estamos
reusando a varivel na clusula SELECT.
Algumas vezes precisamos declarar variveis na clusula FROM que representa um
conjunto de valores:
SELECT OBJECT(a)
FROM X AS o, IN (o.items) a
A clusula WHERE
A clusula WHERE restringe o resultado da consulta, escolhe-se os valores desejados
a partir das variveis declaradas na clusula FROM:
SELECT OBJECT(p)
FROM Pessoa p
WHERE p.nome = ?1
Esta consulta recupera todas as pessoas que possuem o atributo nome igual ao parmetro que ser passado no mtodo. Por exemplo, o mtodo poderia ser construdo
da seguinte forma:
findByNome(String nome)
Para utilizar java.util.Collection na clusula WHERE precisa-se declarar primeiramente na clusula FROM:
SELECT OBJECT(a)
FROM Pessoa AS p, IN(p.parentes a)
WHERE a.filho.name = Pedro
Algumas vezes pode-se declarar mais de uma varavel que representa o mesmo Entity
Bean. Quando fazemos comparaes este artifcio muito til:
200
A clusula SELECT
A clusula SELECT especifica o resultado retornado pela consulta. Por exemplo:
SELECT OBJECT(p)
FROM Pessoa p, IN(o.parentes) a
Como pode-se ver, podemos utlizar o ponto para acessar relacionamentos na clusula SELECT. Este cdigo interpretado para um SQL-padro onde um JOIN feito para
recuperar os dados desejados.
Perceba que neste exemplo no utilizamos a notao Object(), ele apenas utilizado
quando se trata de uma varivel simples que no faz uso do ponto para acessar informaes por meio dos relacionamentos entre Entity Beans.
Outra informao importante que a clusula SELECT no trabalha com
java.util.collection, apenas aceita variveis simples, ou seja:
SELECT r.items
FROM Regra AS r
Voc pode tambm fazer que seu mtodo de busca retorne um java.util.Set que no
permite que valores repetidos sejam inseridos, ao invs do uso de DISTINCT.
A seguir temos um exemplo de como um mtodo definido no arquivo ejb-jar.xml e
pode ser acessado por meio das interfaces Home e/ou LocalHome do EJB. Na interface o mtodo estaria assim:
201
Este mtodo vai retornar todas as pessoas que tem o nome passado como parmetro.
No arquivo ejb-jar-xml temos:
. . .
<query>
<query-method>
<method-name>findByNome</method-name>
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</query-method>
<ejb-ql>
<![CDATA[SELECT OBJECT(a) FROM Pessoa AS a WHERE nome = ?1]]>
</ejb-ql>
<query>
. . .
202
Captulo 14
Message-Driven Beans
A comunicao entre objetos , em geral, sncrona. Neste tipo de comunicao um
objeto somente pode enviar mensagens para outro que esteja ativo. Os componentes
Message-Driven permitem que objetos comuniquem-se de forma assncrona, utilizando filas ou tpicos. Estas filas ou tpicos permitem que objetos emissores enviem
informaes sem que os objetos destino estejam ativos.
203
<<EJBMessage>>
MDBExampleBean
EJB_Context : MessageDrivenContext = null
MDBExampleBean()
ejbCreate()
onMessage()
ejbRemove()
setMessageDrivenContext()
import javax.ejb.*;
import javax.jms.*;
import javax.naming.*;
/**
* Este EJB exemplo do tipo Message-Driven Bean, apresenta os mtodos-padro
* de ciclo de vida ejbCreate() e ejbRemove() e o mtodo onMessage()
* executado no recebimento de uma mensagem.
*/
public class MDBExampleBean implements MessageDrivenBean, MessageListener {
/**
* Contexto do MDB.
*/
private MessageDrivenContext messageDrivenContext;
/**
* Utilizado pelo container para instanciar o EJB.
* @throws CreateException exceo na instanciao do objeto.
*/
public void ejbCreate() throws CreateException {
}
/**
* Utilizado pelo container para remover o EJB.
*/
public void ejbRemove() {
}
204
/**
* Executado no recebimento de uma mensagem para este MDB.
* @param msg mensagem recebida atravs do MOM.
*/
public void onMessage(Message msg) {
try {
// imprime a mensagem recebida
System.out.println(Mensagem recebida: + ((TextMessage)
msg).getText());
} catch (JMSException ex) {
ex.printStackTrace();
System.err.println(Erro ao obter o texto da mensagem: + ex);
}
}
/**
* Configura o contexto do MessageDriven Bean.
* @param messageDrivenContext contexto do MDB.
*/
public void setMessageDrivenContext(MessageDrivenContext messageDrivenContext) {
this.messageDrivenContext = messageDrivenContext;
}
}
205
Instncia do EJB
Message-Driven Bean
ainda no existe
1. Class.newInstance()
2. setMessageDrivenContext()
3. ejbCreate()
ejbRemove()
Message-Driven Bean
no pool de objetos
onMessage()
206
P1
MOM
P2
207
Producer
QUEUE
Consumer
MOM
208
Consumer 1
Producer
TOPIC
Consumer 2
MOM
Consumer 3
/**
* Esta classe exemplo, envia mensagens para um fila (queue)
* para ser consumida por um MDB.
*/
public class TestClient {
// cria a conexo
queueConnection =
queueConnectionFactory.createQueueConnection();
209
// cria o sender
QueueSender queueSender = queueSession.createSender(queue);
/**
* Teste de recebimento de mensagens pelo MDB.
* Recebe uma mensagem do tipo <code>TextMessage</code> e a imprime no console.
*/
public class TestMDB implements MessageDrivenBean, MessageListener {
/**
210
/**
* Instncia o objeto no servidor pelo container.
*/
public void ejbCreate() {
}
/**
* Remove a instncia do objeto no servidor.
*/
public void ejbRemove() {
}
/**
* Configura o contexto do EJB MDB.
* @param ctx contexto do MDB.
*/
public void setMessageDrivenContext(MessageDrivenContext ctx) {
this.ctx = ctx;
}
/**
* Valida a mensagem recebida e a imprime no console.
* @param message mensagem a ser notificada.
*/
public void onMessage(Message message) {
try {
if (message instanceof TextMessage) {
System.out.println(Mensagem recebida pelo MDB =
+ ((TextMessage) message).getText());
}
else {
System.err.println(Mensagem com tipo errado :
+ message.getClass().getName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
211
Captulo 15
Transaes e Segurana
A proposta inicial da API desenvolvida para a plataforma Java a de prover aos desenvolvedores os recursos bsicos de infra-estrutura e permitir que eles pudessem se
concentrar na implementao das regras de negcio de suas aplicaes. Assim, foram
disponibilizadas bibliotecas para trabalhar com colees, com entrada e sada de dados, com recursos de internacionalizao, entre outras.
Esta idia foi utilizada novamente na especificao da plataforma J2EE, com o objetivo de prover implementaes para problemas recorrentes de aplicaes distribudas, agilizando seus tempos de desenvolvimento e permitindo que o foco do desenvolvimento fique nas regras de negcio a serem atendidas, deixando os recursos de
infra-estrutura complexos a cargo dos fabricantes dos containers. Desta forma, h um
aumento significativo nas chances das necessidades dos clientes serem atendidas e,
por consequncia, os sistemas construdos serem bem sucedidos.
Entre a gama de servios previstos na especificao da plataforma J2EE ligados aos
Enterprise JavaBeans, sero abordados dois dos mais usados: transaes e segurana.
O primeiro servio serve para garantir a integridade dos dados, permitindo que falhas
e execues concorrentes no tornem as informaes gerenciadas pela aplicao
inconsistentes. O segundo servio trata da proteo da aplicao com relao ao acesso
no autorizado s funcionalidades disponibilizadas por ela. Ambos so apresentados
neste captulo.
15.1 Transaes
Tipicamente os sistemas provm funcionalidades para seus clientes baseados em uma
massa de dados armazenados em um meio peristente. A integridade das informaes
armazenadas neste repositrio fundamental para o correto funcinamento do sistema e muitas vezes a perda de informaes pode causar prejuzos para seus usurios.
Os problemas relacionados a manuteno da integridade das informaes armazenadas em um meio persistente podem ser causados por fatores fsicos ou lgicos.
212
Dentre os fatores fsicos podemos destacar a falta de energia eltrica durante o processamento de uma funcionalidade que envolva vrias operaes sobre os dados. J
fatores lgicos esto relacionados com erros na programao do acesso concorrente
aos dados, onde alteraes realizadas por um processo podem ser sobrepostas por
outros processos executando de forma concorrente.
Estes problemas so significativamente agravados quando estamos desenvolvendo
em um ambiente distribudo. Uma vez que partes de nossas aplicaes podem ser
executadas em mquinas diferentes, h a chance de uma delas quebrar sem que o
restante da aplicao tenha conhecimento disto, fazendo com que uma operao
realizada pela aplicao seja executada parcialmente, o que pode corromper os dados sendo manipulados. Tambm h a chance de uma infomao ser alterada por
uma parte da aplicao sem que a outra seja notificada, o que tambm ocasiona resultados errneos.
Como soluo a estes problemas, foi desenvolvido o conceito de transaes. Para
tanto feito um agrupamento das operaes realizadas em uma determinada poro
do software em uma unidade denominada transao, que apresenta quatro propriedades fundamentais, chamadas de ACID:
Atomicidade garante a completude da execuo das operaes de uma transao, ou seja, ou todas as operaes de uma transao so executadas ou nenhuma
operao realizada. Caso no seja possvel completar uma operao aps outras
terem sido executadas, deve ser possvel anular o efeito destas ltimas para atender a esta propriedade.
Consistncia garante que o conjunto de operaes que compem uma transao nunca deixem o sistema em um estado inconsistente.
Isolamento garante que a execuo de uma transao no seja afetada pela execuo de outra transao. Esta propriedade especialmente importante quando
h aplicaes concorrentes que acessam os mesmos dados, uma vez que durante
a execuo de uma transao os dados podem ficar temporariamente inconsistentes, levando outras transaes que utilizam estes dados a produzirem resultados incorretos e possivelmente violarem a propriedade de consistncia.
Durabilidade garante que os resultados obtidos em uma transao sejam armazenados em um meio persistente.
Para ilustrar estas propriedades, vamos utilizar como exemplo uma transao bancria de transferncia de fundos de uma conta corrente para outra. Suponha a existncia da seguinte classe responsvel por realizar a transferncia:
213
// ...
public void transferenciaEntreCC(ContaCorrente origem, ContaCorrente destino,
double montante) {
// verifica se h saldo suficiente na conta a ser debitada
if (origem.getSaldo() < montante)
throw
origem.debitar(montante);
destino.creditar(montante);
}
// ...
}
A necessidade da primeira propriedade pode ser logo vista nas duas ltimas operaes do mtodo de transferncia entre contas correntes. Caso logo aps a primeira
operao ser processada ocorra uma queda do sistema, por falta de energia eltrica,
por exemplo, o montante ser reduzido da primeira conta mas no ser creditado na
segunda. Isto significa que o montante iria simplesmente desaparecer, tornando a
base de dados do sistema bancrio inconsistente.
A segunda propriedade diz respeito demarcao dos limites da transao. Ela garante que uma transao conter um mtodo de negcio completo. Assim, no caso
do mtodo de transferncia entre contas correntes, no seria possvel incluir a operao de dbito em uma transao e a de crdito em outra, pois neste caso ao final da
primeira transao o sistema estaria inconsistente.
O isolamento diz respeito a tornar a execuo em paralelo de transaes independentes. Como a consistncia s garantida no trmino de uma transao, possvel
que durante sua execuo o sistema esteja num estado inconsistente (no exemplo
esta situao seria atingida no momento aps a operao de dbito e antes da operao de crdito). Assim, caso uma outra transao seja iniciada enquanto uma primeira
ainda no terminou, possvel que seus resultados no sejam corretos, uma vez que
a premissa da consistncia que o sistema estaria inicialmente consistente.
A ltima propriedade trata da confirmao dos resultados efetuados pelas transaes.
Neste caso, aps a confirmao das operaes, seus resultados so efetivamente armazenados em meios persistentes. Assim, garantido que em caso de falhas no sistema aps o encerramento da transao, seus resultados ainda podero ser vistos aps
o restabelecimento do sistema.
214
Transaes BMT
Transaes BMT (Bean Managed Transactions) ou programadas permitem maior controle por parte do desenvolvedor, pois ele que insere em seu cdigo instrues que
indicam o momento em que a transao foi iniciada, o momento em que ela foi concluda com sucesso ou que ocorreu um erro e a transao deve ser abortada.
As instrues para o controle das transaes so disponibilizadas numa API chamada
JTA (Java Transaction API). Ela permite o acesso transparente aos mais variados gerenciadores de transaes disponveis nos containers. A implementao da Sun para
tal API o JTS (Java Transaction Service).
A comunicao com um gerenciador de transaes se inicia com a obteno de uma
referncia para a interface javax.transaction.UserTransaction, que feita atravs do
contexto do EJB. Esta interface permite enviar comandos para delimitar o incio de
uma transao (begin), concluso com sucesso (commit) ou solicitar que as operaes realizadas sejam descartadas pela ocorrncia de falhas (rollback). Abaixo um
exemplo de uso de uma transao gerenciada pelo bean em um mtodo que realiza a
transferncia de um montante de uma conta corrente para outra.
215
Este tipo de transaes pode ser utilizado apenas Session Beans e Message Driven
Beans. Os Entity Beans exigem um maior controle do container sobre suas aes e
portanto no tem disponvel o gerenciamento de transaes feito por ele prprio.
Transaes CMT
Transaes CMT (Container Managed Transactions) ou declarativas podem ser utilizadas com qualquer tipo de EJB. Neste tipo de transao no h a necessidade de
programao explcita das delimitaes das transaes, esta tarefa efetuada automaticamente pelo prprio container. Para tanto, necessrio informar nos descritores dos EJBs a necessidade de suporte transacional s operaes e como ele deve
gerenci-lo.
Uma vez que no h a necessidade de incluso de cgido especfico para gerncia de
transaes, a flexibilidade de mudana da estratgia de emprego deste recurso muito
maior, pois basta alterar os descritores dos EJBs para atingir este objetivo.
Abaixo est um exemplo de descritor que define a incluso de suporte transacional
num EJB pra gerenciamento de contas bancrias:
216
217
Atributo Transacional
Required
Requires New
Mandatory
NotSupported
Supports
Never
218
Transao do Cliente
Nenhuma
T1
Nenhuma
T1
Nenhuma
T1
Nenhuma
T1
Nenhuma
T1
Nenhuma
T1
Transao do Bean
T2
T1
T2
T2
Exceo
T1
Nenhuma
Nenhuma
Nenhuma
T1
Nenhuma
Exceo
15.2 Segurana
Em uma aplicao J2EE, h duas formas que os clientes devem ser avaliados no acesso ao sistema e aos componentes que ele utiliza. Para um cliente acessar um sistema,
inicialmente ele dever estar autenticado no mesmo. Autenticar um cliente significa
que o sistema deve verificar se o cliente quem ele diz que . Para isso o mesmo
dever fornecer algumas informaes como usurio e senha, ou algum cdigo de
acesso ou algo parecido. O sistema autenticar o usurio e sendo assim, associar o
mesmo a uma identidade de segurana pr estabelecida, tal como um perfil de administrador, coordenador ou atendente por exemplo.
Assim que o usurio autenticado e acessa o sistema, este ltimo dever apresentar
formas de autorizar o usurio a acessar operaes do sistema vlidas para o seu perfil
de usurio. Por exemplo, se o perfil do usurio de atendente, o mesmo no poderia
acessar a operao de relatrios gerenciais.
A autenticao feita antes de realizar as operaes nos EJBs e veremos mais adiante
as formas que podem ser utilizadas para tal. J a autorizao realizada durante a
chamada de mtodos dos EJBs, que permitem ou negam o acesso de determinado
perfil de usurio.
Veremos a seguir uma breve explicao da API JAAS e como utiliz-la
JAAS
JAAS (Java Authenticated and Autorizated Service) apresenta interfaces que possibilitam que usurio sejam autenticados e autorizados em aplicaes J2EE. Com isso, permite que o usurio acesse o sistema e as operaes dele, no importando como
implementado pelo fabricante do servidor J2EE. E assim, o servidor J2EE se encarrega de localizar os dados dos usurios que esto aptos a acessar o sistema, o perfil de
cada um, possibilitando os mesmos de acessarem operaes especficas oferecidas
pela aplicao em questo.
Um usurio poder acessar um sistema e estar autenticado para o mesmo, sendo ele
uma aplicao Web ou uma aplicao standalone. Isso dever ser transparente para o
usurio, sendo que a aplicao J2EE poderia prover as duas interfaces para o usurio
com as mesmas funcionalidades.
Autenticao
Em verses mais antigas da especificao EJB no havia uma API que definia os servios necessrios para operaes de segurana. Com a criao da API JAAS isto foi
possvel e autenticar um usurio ficou mais simples e portvel.
219
</form>
...
220
Autorizao
Estando o cliente autenticado, ele dever ser autorizado a realizar certas operaes
fornecidas pelo sistema, de acordo com o seu perfil de usurio. Para isso, a aplicao
deve estar configurada com security policies ou regras de segurana para cada servio fornecido por seus componentes, isto , para cada mtodo de cada EJB.
A autorizao pode ser apresentada de duas formas: Autorizao Programtica ou
Declarativa. Na Autorizao Programtica o programador deve implementar a verificao de segurana no EJB, isto , deve verificar qual usurio est acessando o servio e validar o mesmo. Na Autorizao Declarativa o container realiza toda a validao
de segurana, no sendo preciso implement-la. Para isso, deve-se configurar no deployment descriptor as propriedades de segurana para cada EJB e para cada mtodo do mesmo.
Em um mundo perfeito, o melhor forma a utilizar a Autorizao Declarativa. Haver
casos que ser necessrio mesclar as duas formas de autorizao, sendo que somente
a declarativa no ser suficiente. Por exemplo, se em uma rede de lojas um usurio
com perfil de gerente pode acessar o servios de obteno de relatrios gerenciais,
sendo somente permitido acessar esses dados das redes de uma determinada praa
(regio de So Paulo, por exemplo), se faz necessrio incluir uma validao programtica da regio da rede de lojas que o gerente em questo atua.
Security Roles
O conceito de security roles simples, mas necessrio para o entendimento do uso
de autorizao. Uma security role um conjunto de identidades de usurios (identity). Para um usurio ser autorizado a realizar uma operao por exemplo, sua identidade dever estar na correta security role (perfil) para a operao em questo. O uso
de security roles interessante, pois o desenvolvedor no precisa especificar o perfil
do usurio no cdigo do EJB.
Autorizao Programtica
Para realizar a autorizao de forma programtica, se faz necessrio obter as informaes do usurio autenticado na implementao do EJB. Isto deve ser feito utilizando
a interface javax.ejb.EJBContext que fornece os mtodos getCallerPrincipal() e isCallerInRole(). Vejamos a seguir os mtodos desta interface.
public interface javax.ejb.EJBContext {
...
public java.security.Principal getCallerPrincipal();
public Boolean isCallerInRole(String roleName);
...
}
221
...
<security-role-ref>
<description>Perfil do usurio=gerente</description>
<role-name>gerente</role-name>
<role-link>manager</role-link>
</security-role-ref>
...
</session>
<assembly-descriptor>
...
<security-role>
<description>Perfil de usurio=gerente</description>
<role-name>manager</role-name>
</security-role>
...
</assembly-descriptor>
</enterprise-beans>
...
222
Autorizao Declarativa
A diferena de utilizar autorizao declarativa ao invs da declarao programtica
que no h a necessidade de programar a autorizao, necessitando somente de configurar o deployment descriptor, definindo para cada EJB a security role a ser utilizada. Pode-se definir uma security role para todos os mtodos do EJB, ou definir uma
especfica para cada mtodo. H a possibilidade de excluir mtodos que no desejase que seja acessado por nenhum perfil de usurio, e isto tambm deve ser feito no
deployment descriptor.
Observe que se alguma operao realizar uma chamada a algum mtodo com um
perfil inadequado, isto , com um perfil que no foi configurado ou definido para o
mtodo, o container lanar um exceo do tipo java.lang.SecurityException.
Vejamos a seguir um exemplo de deployment descriptor, configurando security roles
e as permisses para os mtodos dos EJBs.
...
<enterprise-beans>
<session>
...
<security-role-ref>
<description>Perfil do usurio=gerente</description>
<role-name>gerente</role-name>
</security-role-ref>
...
</session>
<assembly-descriptor>
...
<method-permission>
<role-name>gerente</role-name>
<method>
<ejb-name>EJBTestX</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
...
...
<method-permission>
<role-name>gerente</role-name>
223
</exclude-list>
...
</assembly-descriptor>
</enterprise-beans>
...
Propagao de Segurana
Em uma aplicao J2EE, teremos com certeza casos em que servios de alguns EJBs
utilizam servios de outros. Dependendo da aplicao, poderamos querer que a identidade do usurio (perfil) seja propagado para os mtodos que esto sendo chamados pelos prprios EJB para outros EJBs, ou em vez disso, definir um perfil para executar um determinado mtodo em um EJB especfico.
224
...
<security-identity>
<run-as>
<role-name>gerente</role-name>
</run-as>
</security-identity >
...
</session>
<assembly-descriptor>
...
<security-role>
<description>Perfil de usurio=gerente</description>
<role-name>gerente</role-name>
</security-role>
...
</assembly-descriptor>
</enterprise-beans>
225
Exemplo
Veremos a seguir, um exemplo de mdulo de segurana utilizando a API JAAS. Observe que no provemos uma implementao especfica para o mdulo, sendo o
intuito mostrar somente um esqueleto com os mtodos principais que devem ser
implementados conforme o contrato estabelecido pelas interfaces. Fica a cargo do
leitor implementar os mtodos se desejado.
ExampleLoginModule.java
package com.novatec.book.example.security;
import java.util.*;
import javax.security.auth.*;
import javax.security.auth.spi.*;
import javax.security.auth.login.*;
import javax.security.auth.callback.*;
/**
* Exemplo do mdulo de login para realizar a autenticao do usurio.
* Esta classe no apresenta implementao, somente sendo um ponto de partida
* para a criao de um mdulo de login.
*/
public class ExampleLoginModule implements LoginModule {
/**
* Representa um gurpo de informaes relacionados a uma entidade (cliente).
*/
private Subject subject = null;
/**
* Inicializa o mdulo de login.
* Este mtodo executado pelo contexto de login, aps a sua instanciao,
* com o propsito de inicializar este mdulo com informaes relevantes ao
* seu uso.
* @param subject subject a ser autenticado.
* @param callbackhandler handler utilizado para se comunicar com o cliente.
* @param sharedState estado compartilhado com outros mdulos.
* @param options opes especificadas na configurao do login.
*/
public void initialize(Subject subject, CallbackHandler callbackhandler,
Map sharedState,
Map options) {
this.subject = subject;
}
226
/**
* Utilizado para efetuar o logout do usurio autenticado.
* A sua implementao dever destruir o Principal e Credenciais do subject
(cliente).
* @return veradeiro caso o logout efetue com sucesso, falso caso contrrio.
* @throws LoginException exceo caso o logout falhe.
*/
public boolean logout() throws LoginException {
return true;
}
}
227
ExamplePrincipal.java
package com.novatec.book.example.security;
import java.security.*;
/**
* Representa o usurio a ser autenticado.
*/
public class ExamplePrincipal implements Principal {
/**
* Nome do usurio.
*/
private String name = null;
/**
* Construtor customizado.
* @param name nome do usurio.
*/
public ExamplePrincipal(String name) {
this.name = name;
}
/**
* Obtm o nome do usurio.
* @return nome do usurio.
*/
public String getName() {
return name;
}
/**
* Implementao do mtodo equals.
* Verifica se um objeto igual a este.
* @param obj objeto a ser comparado.
* @return verdadeiro caso o objeto seja igual a este, falso caso contrrio.
*/
public boolean equals(Object obj) {
if ( obj == this )
return true;
228
/**
* Implementao do mtodo hashCode.
* Informa uma chave de hash utilizada para este objeto.
* @return chave de hash.
*/
public int hashCode() {
return name.hashCode();
}
/**
* Retorna uma string com informaes do usurio.
* @return string com informaes do usurio.
*/
public String toString() {
return name;
}
}
ExampleRoleGroup.java
package com.novatec.book.example.security;
import java.util.*;
import java.security.*;
import java.security.acl.*;
/**
* Apresenta o esqueleto para a implementao de um grupo de usurios.
*/
public class ExampleRoleGroup extends ExamplePrincipal implements Group {
/**
* Construtor customizado.
* @param name nome do usurio.
*/
229
/**
* Adiciona o usurio em questo ao grupo.
* @param user usurio a ser adicionado ao grupo.
* @return veradeiro se o usurio foi adicionado com sucesso, falso caso
contrrio.
*/
public boolean addMember(Principal user) {
return true;
}
/**
* Remove o usurio do grupo.
* @param user usurio a ser adicionado ao grupo.
* @return veradeiro se o usurio foi removido com sucesso, falso caso contrrio.
*/
public boolean removeMember(Principal user) {
Object prev = members.remove(user);
return prev != null;
}
/**
* Verifica se o usurio membro do grupo.
* @param member usurio que dever ser verificado se membro.
* @return verdadeiro se o usurio membro, falso caso contrrio.
*/
public boolean isMember(Principal member) {
return true;
}
/**
* Retorna uma lista com os membros do grupo.
* @return lista com os membros do grupo.
*/
public Enumeration members() {
return Collections.enumeration(members.values());
}
}
230
ExampleTest.java
package com.novatec.book.example.security;
import java.util.*;
import javax.rmi.*;
import javax.naming.*;
import java.security.*;
/**
* Implementao de uma ao privilegiada.
* Executada com segurana.
*/
public class ExampleTest implements PrivilegedAction {
/**
* Executa a ao com segurana.
* @return informao retornada pelo mtodo do EJB.
*/
public Object run() {
try {
Context ctx = new InitialContext();
Object obj = ctx.lookup(SecurityExampleTest);
SecurityExampleTestHome home =
(SecurityExampleTestHome) PortableRemoteObject.narrow(obj,
SecurityExampleTestHome.class);
SecurityExampleTest test = home.create();
return test.doIt();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
231
ExampleMain.java
package com.novatec.book.example.security;
import javax.naming.*;
import javax.security.auth.*;
import javax.security.auth.login.*;
}
}
232
Captulo 16
Descobrindo Enterprise JavaBeans
O objetivo deste captulo iniciar o leitor nos aspectos prticos que envolvem a construo de uma aplicao distribuda utilizando os componentes da plataforma J2EE.
Os cdigos-fonte completos se encontram no Captulo 19.
233
234
Observe que o mtodo create() ao ser executado, solicita ao container que crie uma
instncia do EJB SalesSuuportBean. Dessa forma o container cria a instncia do objeto, do tipo EJBObject que encapsula o EJB SalesSupportBean e retorna ao cliente
chamador uma referncia da interface Remote, na qual se tem acesso aos mtodos de
negcios ou servios disponveis para o EJB em questo.
A seguir, observe os mtodos da interface Remote do EJB SalesSupportBean, mtodos de negcio utilizados pelo cliente para calcular o desconto concedido ao produto vendido e clculo das parcelas a serem pagas.
235
236
237
Tambm mantemos no EJB SalesBasketBean os dados do usurio que iniciou a compra, para no final desta, validarmos seus dados e relacionarmos os produtos comprados para um determinado usurio. Observe que existe um objeto do tipo UserVO.
Este objeto utilizado para carregar informaes do usurio em questo.
238
getEjbHome(FACADE_NAME,
A seguir vemos a implementao do mtodo getLocalHome, da classe ServiceLocator, na qual obtido referncia para as interfaces dos EJBs contidos no servidor de
aplicao. Veja que a operao simples, somente realizando um lookup (localizao) do EJB solicitado pelo seu nome JNDI. Para efeito de melhora de desempenho, a
referncia para as interfaces Home solicitadas so armazenadas em um cache e podendo ser utilizadas futuramente em outras chamadas a este mtodo.
239
O EJB tambm apresenta o mtodo de clculo do preo total dos produtos contidos
na cesta. Esta tambm uma operao simples, que consiste em iterar todos os produtos contidos na cesta, acumulando os valores dos produtos e retornando este valor.
240
<ejb-jar>
<enterprise-beans>
<session>
<display-name>SalesBasket</display-name>
<ejb-name>SalesBasket</ejb-name>
<home>com.novatec.book.project.ejb.session.SalesBasketHome</home>
<remote>com.novatec.book.project.ejb.session.SalesBasket</remote>
class>
<ejb-class>com.novatec.book.project.ejb.session.SalesBasketBean</ejb<session-type>Stateful</session-type>
<transaction-type>Container</transaction-type>
</session>
241
O cdigo a seguir apresenta os mtodos de negcio do EJB. Estes mtodos so definidos na interface Local. Iremos detalhar a interface Local UserLocal. So definidos
nesta interface os mtodos getters e setters para o objeto em questo.
242
243
/**
* Cria uma conexo com o banco de dados padro.
* @return conexo do banco de dados.
*/
private Connection getConnection() {
Connection conn = null;
try {
InitialContext ctx = new InitialContext();
conn = (Connection) ctx.lookup(java:/DefaultDS);
} catch (Exception e){
throw new RuntimeException(e.getMessage());
}
return conn;
}
public String ejbCreate(String name, String cpf, String address, String email)
throws CreateException {
try {
connection = getConnection();
try {
PreparedStatement stmt = connection.prepareStatement(
INSERT_QUERY);
244
245
246
O mtodo ejbLoad() executado pelo container quando este deseja carregar os dados do objeto do meio persistente e mant-lo em memria. Tambm no retorna
nenhum valor, somente atualiza os dados do objeto atual. A implementao tambm
trivial realizando as mesmas operaes dos mtodos de persistncia anteriores.
247
O mtodo ejbStore() tambm no apresenta nenhuma complexidade e muito parecido com o mtodo anterior. Este mtodo responsvel por atualizar os dados do
objeto em memria no meio persistente, isto , para cada atributo configurado no
objeto em memria, este objeto executado para manter o sincronismo com os dados persistentes. Observe que este mtodo executa a operao contrria do mtodo
ejbLoad().
248
<local-home>com.novatec.book.project.ejb.entity.impl.UserLocalHome</
<local>com.novatec.book.project.ejb.entity.impl.UserLocal</local>
<ejb-class>com.novatec.book.project.ejb.entity.impl.UserBean</ejb-class>
<persistence-type>Bean</persistence-type>
<prim-key-class>java.lang.String</prim-key-class>
<reentrant>False</reentrant>
</entity>
</enterprise-beans>
249
A interface Local ProductLocal apresenta os mtodos de negcio do EJB. Neste somente declaramos os mtodos getters e setters para o EJB Entity Bean CMP ProductBean. No iremos detalh-los, pois so muito simples.
Logo a seguir apresentamos a implementao da classe de chave primria, utilizada
para o EJB ProductBean. Esta classe tambm no apresenta nenhuma complexidade,
somente apresentando os atributos de chave primria que no caso somente um
identificador.
250
Observe que o mtodo ejbCreate() somente configura os atributos do objeto. A persistncia dos seus dados fica a cargo do container.
id)
Veja tambm que os mtodos de manipulao do objeto tais como ejbRemove(), ejbLoad() e ejbStore() so desprovidos de implementao, ficando tambm a cargo do
container esta tarefa. Os mtodos de negcio tambm no apresentam implementao, mas a diferena para os mtodos de ciclo de vida que devem ser declarados
como abstratos, pois sero implementados pelo prprio container.
251
<persistence-type>Container</persistence-type>
<prim-key-class>java.lang.Integer</prim-key-class>
<reentrant>False</reentrant>
<cmp-version>2.x</cmp-version>
<abstract-schema-name>Product</abstract-schema-name>
<cmp-field>
<field-name>name</field-name>
</cmp-field>
<cmp-field>
<field-name>description</field-name>
</cmp-field>
<cmp-field>
<field-name>price</field-name>
</cmp-field>
<cmp-field>
<field-name>id</field-name>
</cmp-field>
<primkey-field>id</primkey-field>
<query>
<query-method>
<method-name>findAll</method-name>
<method-params/>
</query-method>
<ejb-ql>SELECT OBJECT(p) FROM Product p</ejb-ql>
</query>
</entity>
252
253
<message-driven>
<display-name>UserNotifier</display-name>
<ejb-name>UserNotifier</ejb-name>
<ejb-class>com.novatec.book.project.ejb.mdb.UserNotifierBean</ejb-class>
<transaction-type>Container</transaction-type>
<message-driven-destination>
<destination-type>javax.jms.Queue</destination-type>
</message-driven-destination>
</message-driven>
254
value=off/>
<property name=output
location=build/output/>
<property name=out-classes
location=${output}/classes/>
<property name=out-lib
location=${output}/lib/>
<property name=javadoc
location=${output}/doc/api/>
<property name=packages
location=${output}/packages/>
<property name=lib
location=lib/>
<property name=src
location=src/java/>
<property name=descriptors
location=etc/descriptors/>
255
<jar jarfile=${out-lib}/book-project-ejb.jar
manifest=${descriptors}/book-project-ejb.jar/META-INF/MANIFEST.MF>
<fileset dir=${descriptors}/book-project-ejb.jar/>
<fileset dir=${out-classes}>
<exclude name=**/delegate/**/>
<exclude name=**/client/**/>
</fileset>
</jar>
<copy todir=${out-lib}>
<fileset dir=${lib}/>
</copy>
<mkdir dir=${packages}/>
256
<zip zipfile=${output}/book-project-bin.zip
basedir=${packages}
excludes=${javadoc}/**
encoding=ASCII/>
</target>
<zip zipfile=${output}/Book-project-javadoc.zip
basedir=${javadoc}
encoding=ASCII/>
</target>
</project>
257
258
Captulo 17
Deployment Descriptor
Neste captulo faremos uma breve explicao dos elementos do descritor utilizado
para os mdulos de componentes EJB ejb-jar.xml. Para maiores detalhes sobre este
descritor, consulte a especificao EJB 2.x.
259
Elemento ejb-jar
O elemento raiz do deployment descriptor ejb-jar.xml o elemento <ejb-jar>. A seguir
iremos detalhar seus atributos e elementos.
<ejb-jar>
<description></description>
<display-name></display-name>
<small-icon></small-icon>
<large-icon></large-icon>
<enterprise-beans></enterprise-beans>
<relationships></relationships>
<assembly-descriptor></assembly-descriptor>
<ejb-client-jar></ejb-client-jar>
</ejb-jar>
260
Item
Descrio
<description>
<display-name>
<small-icon>
<large-icon>
<enterprise-beans>
<assembly-descriptor>
<ejb-client-jar>
Elemento enterprise-beans
O elemento <enterprise-beans> define informaes de cada tipo de EJB, tais como,
Session Bean, Entity Bean e Message-Driven Bean, e no possui atributos. A seguir
iremos detalhar seus elementos.
<enterprise-beans>
<session></session>
<entity></entity>
<message-driven></message-driven>
</enterprise-beans>
Sub-elemento session
O sub-elemento <session> define informaes para os EJBs Session Bean contidos no
arquivo de deploy, sendo assim, podemos ter vrias ocorrncias deste elemento. A
sua declarao apresenta alguns atributos e elementos.
<session>
<description></description>
<display-name></display-name>
<small-icon></small-icon>
<large-icon></large-icon>
<ejb-name></ejb-name>
<home></home>
<remote></remote>
<local-home></local-home>
<local></local>
<ejb-class></ejb-class>
<session-type></session-type>
<transaction-type></transaction-type>
<env-entry></env-entry>
<ejb-ref></ejb-ref>
<ejb-local-ref></ejb-local-ref>
<security-role-ref></security-role-ref>
<security-identity></security-identity>
261
Item
Descri0
<description>
<display-name>
<small-icon>
Caminho completo de uma figura que ser utilizada como um cone pelas
ferramentas, para este EJB.
<large-icon>
Caminho completo de uma figura que ser utilizada como um cone pelas
ferramentas, para este EJB.
<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>
Declara referncia para recursos que podem ser utilizados pelos EJBs.
Sub-elemento entity
O sub-elemento <entity> apresenta informaes do EJB Entity Bean e tambm pode
ocorrer mais de uma vez no arquivo de deploy. Alm de apresentar informaes do
EJB, pode definir as querys utilizadas pelo container para um EJB CMP.
<entity>
<description></description>
<display-name></display-name>
262
Item
Descrio
<description>
<display-name>
<small-icon>
<large-icon>
<ejb-name>
<home>
<remote>
<local-home>
<local>
<ejb-class>
263
<prim-key-class>
<reentrant>
<cmp-version>
<primkey-field>
<env-entry>
<ejb-ref>
<ejb-local-ref>
<security-role-ref>
<security-identity>
<resource-ref>
<resource-env-entry>
<query>
Sub-elemento message-driven
O sub-elemento <message-driven> define as informaes do EJB Message-Driven
Bean. Como nos outros casos, o arquivo de deploy pode conter mais de uma ocorrncia deste elemento, isto , no caso de deploy de mais de um EJB. A seguir os seus
atributos e elementos.
<message-driven>
<description></description>
<display-name></display-name>
<small-icon></small-icon>
<large-icon></large-icon>
<ejb-name></ejb-name>
<ejb-class></ejb-class>
<transaction-type></transaction-type>
264
Item
Descrio
<description>
<display-name>
<small-icon>
<large-icon>
<ejb-name>
<ejb-class>
<transaction-type>
<message-selector>
<acknowledge-mode>
<message-driven-destination>
Define o tipo de destino da mensagem que pode ser javax.jms.Queue
ou javax.jms.Topic. Alm de definir a durabilidade do envio da
mensagem que pode ser Durable ou NonDurable.
<env-entry>
<ejb-ref>
<ejb-local-ref>
<security-identity>
<resource-ref>
<resource-env-entry>
265
Elemento relationships
O elemento <relationships> apresenta o relacionamento entre EJBs Entity Bean CMP,
sendo que podem ocorrer nenhum, um ou mais relacionamentos entre EJBs deste
tipo. Define outro elemento, <ejb-relation> no qual so configurados cada relacionamento entre dois EJBs.
<relationships>
<description></description>
<ejb-relation>
<description></description>
<ejb-relation-name></ejb-relation-name>
<ejb-relationship-role>
<description></description>
<ejb-relationship-role-name></ejb-relationship-role-name>
<multiplicity></multiplicity>
<relationship-role-source>
<description></description>
<ejb-name></ejb-name>
</relationship-role-source>
<cmr-field>
<description></description>
<cmr-field-name></cmr-field-name>
<cmr-field-type></cmr-field-type>
</cmr-field>
</ejb-relationship-role>
<ejb-relationship-role>
<description></description>
<ejb-relationship-role-name></ejb-relationship-role-name>
<multiplicity></multiplicity>
<cascade-delete></cascade-delete>
<relationship-role-source>
<description></description>
<ejb-name></ejb-name>
</relationship-role-source>
<cmr-field>
<description></description>
<cmr-field-name></cmr-field-name>
<cmr-field-type></cmr-field-type>
</cmr-field>
</ejb-relationship-role>
266
<ejb-relation>
Sub-elemento <ejb-relation> do elemento <relationships> que define define o relacionamento entre dois EJB Entity Bean CMP.
<description>
<ejb-relation-name>
Nome do relacionamento.
<ejb-relationship-role>
Elemento que deve ser configurado para cada um dos dois EJBs que
possuem o relacionamento.
Sub-elemento ejb-relationship-role
Sub-elemento <ejb-relationship-role> do elemento <ejb-relation> que descreve um regra de
relacionamento dentre dois EJBs.
<description>
<cascade-delete>
<relationship-role-source>
<cmr-field>
Elemento assembly-descriptor
O elemento <assembly-descriptor> define as regras de segurana, a permisso de
acesso (execuo) dos mtodos dos EJBs, atributos de transao para cada mtodo
de cada EJB e a lista dos mtodos excludos do deploy.
<assembly-descriptor>
<security-role>
<description/>
<role-name></role-name>
267
Item
Descrio
<security-role>
<method-permission>
<container-transaction> Define atributos de transao para cada mtodo de cada EJB. Pode
conter um atributo que descreve a transao e deve conter para cada
mtodo o nome do EJB e o nome do mtodo que ser utilizado um tipo
de transao, configurada no elemento <trans-attribute>.
<exclude-list>
268
Captulo 18
API Enterprise JavaBeans
Este captulo apresenta um guia de referncia rpida para a API Enterprise JavaBeans.
Observe que a API da plataforma J2EE muita mais extensa, sendo que esta apresentada neste tpico somente uma parte dela. No visamos tambm explicar em detalhes a API EJB. Para detalhes consulte a documentao oficial da API e a especificao
EJB 2.0.
Iremos apresentar o pacote javax.ejb explicando as suas interfaces e excees.
18.1 Interfaces
EJBContext
A interface EJBContext extendida pelos contextos de cada tipo de EJB, isto , pelas
interfaces SessionContext, EntityContext e MessageDrivenContext. Fornece informaes de segurana, transao e dados sobre as interfaces Home (Local e Remote) do
EJB, sendo possvel utiliz-la para criar, destruir ou localizar um objeto EJB por exemplo.
public interface EJBContext {
EJBHome getEJBHome();
EJBLocalHome getEJBLocalHome();
Properties getEnvironment();
Identity getCallerIdentity();
Principal getCallerPrincipal();
boolean isCallerInRole(Identity role);
boolean isCallerInRole(String roleName);
UserTransaction getUserTransaction() throws IllegalStateException;
void setRollbackOnly() throws IllegalStateException;
boolean getRollbackOnly() throws IllegalStateException;
}
269
EJBHome
Esta interface deve ser extendida pelas interfaces Home (acesso Remoto - Home) dos
componentes EJBs implementados. Ela oferece servios para criao, remoo e localizao de objetos EJB. Oferece informaes sobre o meta-dados do EJB e o handle
do EJB, que pode ser utilizado para futuras chamadas de mtodos ao objeto, sem a
necessidade de realizar a sua localizao por exemplo.
public interface EJBHome extends Remote {
void remove(Handle handle) throws RemoteException, RemoveException;
void remove(Object primaryKey) throws RemoteException, RemoveException;
EJBMetaData getEJBMetaData() throws RemoteException;
HomeHandle getHomeHandle() throws RemoteException;
}
EJBLocalHome
Deve ser extendida pelas interfaces Home (acesso Local - LocalHome) dos componentes EJBs. Apresenta servios de criao, remoo e localizao dos objetos EJB.
public interface EJBLocalHome {
void remove(Object primaryKey) throws RemoveException, EJBException;
}
EJBLocalObject
A interface EJBLocalObject deve ser extendida pela interface Local (acesso Local Remote) para os EJBs que provm acessos locais. Apresenta mtodos para obter referncia para a interface LocalHome e obter a chave-primria (Primary Key) do objeto
caso o mesmo seja um EJB Entity Bean. Alm de prover um mtodo para destruir a
instncia do objeto e um servio que avalia se o objeto atual, isto , o EJBLocalObject
idntico a outro informado.
Quando definir a interface Local para um componente EJB, a mesma deve conter os
mtodos de negcio que estaro disponveis para o cliente local.
public interface EJBLocalObject {
public EJBLocalHome getEJBLocalHome() throws EJBException;
public Object getPrimaryKey() throws EJBException;
public void remove() throws RemoveException, EJBException;
boolean isIdentical(EJBLocalObject obj) throws EJBException;
}
270
EJBMetaData
Permite que o cliente acesse informaes dos metadados do EJB. Esta interface no
muito utilizada, mas pode ser obtida atravs da chamada ao mtodo
ejbHome.getEJBMetaData(). As informaes contidas nesta interface e fornecidas ao
cliente remoto em forma de um objeto serializado, pode ser utilizado para obter dinamicamente informaes sobre o EJB.
public interface EJBMetaData {
EJBHome getEJBHome();
Class getHomeInterfaceClass();
Class getRemoteInterfaceClass();
Class getPrimaryKeyClass();
boolean isSession();
boolean isStatelessSession();
}
EJBObject
Esta interface deve ser extendida pela interface Remote (acesso remoto) dos componentes EJBs. Apresenta uma viso dos servios oferecidos pelo EJB para o cliente
remoto. A interface Remote definida para cada EJB, deve conter as assinaturas dos
mtodos de negcio que o EJB implementa e as quais o cliente remoto ter acesso.
Por esta interface, o cliente pode ter acesso a referncia para a interface Home do
EJB, obter a chave-primria no caso de EJB Entity Bean, remover a instncia do objeto, obter o Handler deste objeto que contm informaes sobre ele e verificar se
algum objeto idntico ao objeto atual.
public interface EJBObject extends Remote {
public EJBHome getEJBHome() throws RemoteException;
public Object getPrimaryKey() throws RemoteException;
public void remove() throws RemoteException, RemoveException;
public Handle getHandle() throws RemoteException;
boolean isIdentical(EJBObject obj) throws RemoteException;
}
271
EnterpriseBean
A interface EnterpriseBean a interface genrica de cada tipo de EJB. Ela extendida
pelas interfaces SessionBean, EntityBean e MessageDrivenBean. Alm de ser serializada utilizada como uma interface marker, isto , informa que a interface realmente um EJB.
public interface EnterpriseBean extends java.io.Serializable {
}
EntityBean
Quando implementamos um EJB EntityBean, devemos implementar esta interface.
Apresenta os mtodos de ciclo de vida do EJB, executados pelo container nos momentos apropriados.
Define os mtodos para configurar e desconfigurar o contexto associado ao EJB Entity Bean, mtodo de remoo da entidade persistente, ativao da entidade caso
tenha sido passivada pelo container, passivao da entidade em caso de falta de recursos ou porque muitos EJBs esto instanciados por exemplo, carrega uma entidade
do meio persistente para a memria quando o container precisa atualizar os dados
do objeto, ou atualiza os dados no meio persistente de acordo com os valores dos
atributos constantes em memria.
Alm destes mtodos, se faz necessrio a implementao do mtodo ejbCreate() j
mencionado anteriormente, o qual ir criar a instncia do objeto em memria e persistir o mesmo.
public interface EntityBean extends EnterpriseBean {
public void setEntityContext(EntityContext ctx) throws EJBException,
RemoteException;
public void unsetEntityContext() throws EJBException, RemoteException;
public void ejbRemove() throws RemoveException, EJBException, RemoteException;
public void ejbActivate() throws EJBException, RemoteException;
public void ejbPassivate() throws EJBException, RemoteException;
public void ejbLoad() throws EJBException, RemoteException;
public void ejbStore() throws EJBException, RemoteException;
}
272
EntityContext
Apresenta a interface especfica do EJBContext para um EJB Entity Bean. Ela associada ao objeto aps a criao da sua instncia.
public interface EntityContext extends EJBContext {
EJBLocalObject getEJBLocalObject() throws IllegalStateException;
EJBObject getEJBObject() throws IllegalStateException;
Object getPrimaryKey() throws IllegalStateException;
}
Handle
Um Handle uma referncia persistente de um componente EJB. Ela implementada
por todos os EJB Handles. Muito til quando a aplicao necessita persistir a referncia para um objeto EJB e recuper-la posteriormente.
public interface Handle extends java.io.Serializable {
public EJBObject getEJBObject() throws RemoteException;
}
HomeHandle
Tal como o Handle uma referncia persistente para a interface Remote de um EJB, a
HomeHandle uma referncia persistente para interface Home de um EJB. Tambm
til para manter a referncia da interface Home de um EJB, persistente em algum
meio e recuper-la posteriomente para acessar a interface Home.
public interface HomeHandle extends java.io.Serializable {
public EJBHome getEJBHome() throws RemoteException;
}
MessageDrivenBean
Esta interface deve ser implementada por cada EJB Message-Driven Bean. Define os
mtodos de ciclo de vida deste tipo de EJB. Observe que estes mtodos no so executados pelos clientes, pois como este componente tem um comportamento de execuo assncrona por meio de mensagens (JMS), os mtodos so executados pelo
container no recebimento de mensagens dos clientes.
273
MessageDrivenContext
Apresenta a interface especfica de EJBContext para um EJB Message-Driven Bean.
Tambm associa o contexto ao EJB, depois que sua instncia criada.
public interface MessageDrivenContext extends EJBContext {
}
SessionBean
Deve ser implementada por todo EJB Session Bean. Apresenta os mtodos do ciclo
de vida do EJB, tais como associao do contexto ao EJB, remoo da instncia do
objeto, ativao e passivao do objeto pelo container, alm de definir o mtodo
ejbCreate() que criar uma instncia do objeto pelo container.
public interface SessionBean extends EnterpriseBean {
void setSessionContext(SessionContext ctx) throws EJBException, RemoteException;
void ejbRemove() throws EJBException, RemoteException;
void ejbActivate() throws EJBException, RemoteException;
void ejbPassivate() throws EJBException, RemoteException;
}
SessionContext
Esta a interface especfica de EJBContext para um EJB Session Bean. Tambm
associada a instncia do objeto aps a sua criao.
public interface SessionContext extends EJBContext {
EJBLocalObject getEJBLocalObject() throws IllegalStateException;
EJBObject getEJBObject() throws IllegalStateException;
}
274
SessionSyncronization
Esta interface pode ser implementada por EJB Session Bean Stateful, quando desejase sincronizar o estado transacional do objeto. Cada mtodo executado a cada etapa das fases de transao.
public interface SessionSynchronization {
public void afterBegin() throws EJBException, RemoteException;
public void beforeCompletion() throws EJBException, RemoteException;
public void afterCompletion(boolean committed) throws EJBException,
RemoteException;
}
18.2 Excees
AccessLocalException
Exceo lanada caso o chamador no possuir acesso para executar o mtodo. Utilizado para objetos locais.
CreateException
Deve ser definida no mtodo de criao da instncia de cada EJB. Ela lanada quando ocorrer uma falha na criao da instncia de um objeto EJB.
DuplicateKeyException
Esta exceo lanada quando no pode-se criar um objeto, pois a sua chave j
existe e est sendo utilizada por outro objeto. Normalmente utilizada no mtodo
create() do EJB Entity Bean.
EJBException
Informa ao objeto chamador que ocorreu uma falha no recupervel, ou um erro
inesperado. lanada quando ocorre erros deste tipo nos mtodos de ciclo de vida
ou nos mtodos de negcio. a nica exceo do pacote javax.ejb que extende a
exceo de runtime - RuntimeException - e no permite ao chamador se recuperar
do erro. As excees NoSuchEntityException, NoSuchObjectLocalException, AccessLocalException, TransactionRequiredLocalException e TransactionRolledbackLocalException extendem esta exceo.
275
FinderException
Deve ser utilizada em todos os mtodos finders nos EJBs Entity Bean. So lanadas
quando um erro de localizao do objeto ocorre.
NoSuchEntityException
lanada pelo container quando em um EJB Entity Bean executado um mtodo,
para o qual no existe o objeto em questo. Pode ser utilizada pelos mtodos de
negcio do EJB e pelos mtodos de ciclo de vida ejbLoad() e ejbStore() de um EJB
Entity Bean.
NoSuchObjectLocalException
Parecida com a exceo NoSuchEntityException, diferindo que esta lanada para
objetos locais que no existem mais.
ObjectNotFoundException
lanada por um mtodo finder, para avisar que um objeto no existe. Deve-se utilizar esta exceo quando um mtodo finder retornar somente um objeto. No caso de
vrios objetos, deve-se retornar uma coleo nula.
RemoveException
A exceo RemoveException lanada quando o container no pode remover a instncia do objeto. utilizada no mtodo ejbRemove().
TransactionRequiredLocalException
Informa que a requisio no encontrou uma transao e a mesma era requerida.
TransactionRolledbackLocalException
Indica que a transao foi marcada com rollback ou estava sendo executado o rollback, mas ocorreu algum erro nesta operao.
276
Captulo 19
Aplicao J2EE Exemplo
A seguir apresentamos o cdigo completo da aplicao exemplo. Esta aplicao consiste de sete EJBs, sendo um para cada tipo de EJB definido pela especificao EJB
2.0. Ento sero:
EJB Session Bean Stateless SalesSupportBean
EJB Session Bean Stateful SalesBasketBean
EJB Entity Bean BMP UserBean
EJB Session Bean Stateless UserSessionFacade
EJB Entity Bean CMP ProductBean
EJB Sesison Bean Stateless - ProductSessionFacade
Message-Driven Bean UserNotifierBean
Alm dos EJBs, tambm fazem parte da aplicao exemplo os objetos que implementam o Design Pattern TransferObjects ProductTO e UserTO e seus respectivos Assewblers ProductTOAssembler e UserTOAssembler, utilizados pelos componentes,
os Business Delegates ProductDelegate e UserDelegate e o ServiceLocator.
Observe que existe um deployment descriptor ejb-jar.xml para cada EJB nesta aplicao exemplo. Isto no necessrio em uma aplicao J2EE no mdulo EJB. Para realizar o deploy desta aplicao em um servidor de aplicao preciso criar um nico
deployment descritor ejb-jar.xml, no qual inclumos todas as informaes de todos os
EJBs contidos em um mdulo da aplicao J2EE em questo. Este arquivo mostrado
no final deste captulo.
Iremos apresentar tambm o arquivo especfico para o servidor de aplicaes JBoss,
utilizado para criar as tabelas do banco de dados utilizado para persistir os objetos da
aplicao. Este arquivo, chamado de jbosscmp-jdbc.xml est mostrado no final deste
captulo tambm. Salientamos que este arquivo no faz parte da especificao J2EE e
um arquivo complementar e de uso exclusivo para o servidor de aplicaes JBoss.
277
import javax.ejb.*;
import java.util.*;
import java.rmi.*;
/**
* Inteface Home, obtm uma referncia para a interface Remote, esta
* ultima que fornece os servios de suporte a venda dos produtos.
*/
public interface SalesSupportHome extends javax.ejb.EJBHome {
/**
* Cria uma referncia remota para o componente <code>SalesSupport</code>.
* @return referncia remota para o componente <code>SalesSupport</code>.
* @throws CreateException se ocorrer erro ao criar a instncia.
* @throws RemoteException outros erros na criao da instncia.
*/
SalesSupport create() throws CreateException, RemoteException;
}
import javax.ejb.*;
import java.util.*;
import java.rmi.*;
/**
* Interface Remote do EJB <code>SalesSupport</code>.
* Apresenta servios de clculo de desconto e parcelas
* para um produto em venda.
*/
278
/**
* Calcula um desconto para o valor informado, de acordo com a percentual
* informada.
* @param value valor a ser calculado o desconto.
* @param perc percentual utilizado para clculo do desconto.
* @return valor do desconto concedido.
* @throws RemoteException se ocorrer erro ao executar o mtodo.
*/
Double calcDiscount(Double value, Double perc) throws RemoteException;
/**
* Clculo o valor das parcelas, de acordo com o valor total informado e com
* a quantidade de vezes tambm informada.
* @param value valor total da venda.
* @param times quantidade de parcelas desejada.
* @return valor de cada parcela.
* @throws RemoteException se ocorrer erro ao executar o mtodo.
*/
Double calcPiece(Double value, Integer times) throws RemoteException;
}
import javax.ejb.*;
/**
* Apresenta os servios para clculo de frete, desconto, valores de parcela
* dependendo da quantidade de vezes que o valor vai ser pago.
* Estes servios so utilizados enquanto estiver sendo realizada a venda
* dos produtos.
*/
public class SalesSupportBean implements SessionBean {
/**
* Contexto do Session Bean.
*/
private SessionContext sessionContext;
279
/**
* Remoo da instncia do objeto pelo container.
*/
public void ejbRemove() {
}
/**
* Utilizado pelo container para ativar o objeto que est passivo.
*/
public void ejbActivate() {
}
/**
* Utilizado pelo container para tornar passivo um objeto ativo.
*/
public void ejbPassivate() {
}
/**
* Configura o contexto do EJB Session Bean.
* @param sessionContext contexto do EJB Session Bean.
*/
public void setSessionContext(SessionContext sessionContext) {
this.sessionContext = sessionContext;
}
/**
* Calcula um desconto para o valor informado, de acordo com a percentual
* informada.
* @param value valor a ser calculado o desconto.
* @param perc percentual utilizado para clculo do desconto.
* @return valor do desconto concedido.
*/
280
class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>SalesSupport</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>
281
import javax.ejb.*;
import java.util.*;
import java.rmi.*;
/**
* Inteface Home, obtm uma referncia para a interface Remote, esta
* ultima que fornece os servios para o carrinho de compras.
*/
public interface SalesBasketHome extends javax.ejb.EJBHome {
/**
* Cria uma referncia remota para o componente <code>SalesBasket</code>.
* @return referncia remota para o componente <code>SalesBasket</code>.
* @throws CreateException se ocorrer erro ao criar a instncia.
* @throws RemoteException outros erros na criao da instncia.
*/
SalesBasket create() throws CreateException, RemoteException;
}
import javax.ejb.*;
import java.util.*;
import java.rmi.*;
import com.novatec.book.project.ejb.to.*;
/**
* Interface Remota da cesta de produtos, apresenta servios que sero utilizados
* na venda dos produtos ao usurio.
282
/**
* Inicia a compra dos produtos para o usurio informado.
* @param user usurio que iniciar a compra dos produtos.
* @throws RemoteException se ocorrer erro ao executar o mtodo.
*/
void initSales(UserTO user) throws RemoteException;
/**
* Finaliza a compra.
* Esta operao persiste os dados da venda, atravs do uso de EJB Entity
* Bean com acesso local e notifica o usurio do sucesso da sua compra.
* @return verdadeiro caso a compra tenha sido realizada com sucesso.
* @throws RemoteException se ocorrer erro ao executar o mtodo.
* @throws Exception exceo na criao do Entity Bean de Produtos.
*/
Boolean finalizeSale() throws Exception, RemoteException;
/**
* Adiciona um produto no carrinho de compras.
* @param product produto a ser inserido no carrinho de compras.
* @throws RemoteException se ocorrer erro ao executar o mtodo.
*/
void addProduct(ProductTO product) throws RemoteException;
/**
* Remove um produto do carrinho de compras.
* @param product produto a ser removido do carrinho de compras.
* @return verdadeiro caso a remoo seja efetivada, falso caso contrrio.
* @throws RemoteException se ocorrer erro ao executar o mtodo.
*/
Boolean removeProduct(ProductTO product) throws RemoteException;
/**
* Calcula o valor dos produtos contidos na cesta e retorna este valor.
* @return valor total do produtos contidos na cesta.
283
/**
* Remove os produtos da cesta de compras.
* @throws RemoteException se ocorrer erro ao executar o mtodo.
*/
void freeBasket() throws RemoteException;
}
import javax.ejb.*;
import java.util.*;
import com.novatec.book.project.ejb.*;
import com.novatec.book.project.ejb.to.*;
import com.novatec.book.project.ejb.entity.*;
import com.novatec.book.project.ejb.entity.impl.ProductPK;
/**
* Apresenta o servio de carrinho, que mantm os produto em venda
* de um determinado usurio.
* Estes produtos so mantidos em uma Map, e podem ser atualizados,
* removidos ou inseridos no carrinho de compras.
* O usurio tambm registrado como proprietrio desta compra.
*/
public class SalesBasketBean implements SessionBean {
/**
* Contexto do Session Bean.
*/
private SessionContext sessionContext;
/**
* Cesta de produtos.
*/
private Map basket;
284
/**
* Usurio dono desta compra.
*/
private UserTO user;
/**
* Criao da instncia deste objeto pelo container.
* @throws CreateException exceo na criao da instncia do EJB.
*/
public void ejbCreate() throws CreateException {
this.basket = new HashMap();
}
/**
* Remoo da instncia do EJB, pelo container.
*/
public void ejbRemove() {
}
/**
* Utilizado pelo container para ativar o objeto que est passivo.
*/
public void ejbActivate() {
}
/**
* Utilizado pelo container para tornar passivo um objeto ativo.
*/
public void ejbPassivate() {
}
/**
* Configura o contexto do EJB Session Bean.
* @param sessionContext contexto do EJB Session Bean.
*/
public void setSessionContext(SessionContext sessionContext) {
this.sessionContext = sessionContext;
}
285
/**
* Finaliza a compra.
* Esta operao persiste os dados da venda, atravs do uso de EJB Entity
* Bean com acesso local e notifica o usurio do sucesso da sua compra.
* @return verdadeiro caso a compra tenha sido realizada com sucesso.
* @throws Exception exceo na criao do Entity Bean de Produtos.
*/
public Boolean finalizeSale() throws Exception {
final String FACADE_NAME = java:comp/env/ejb/productfacade;
ProductSessionFacadeHome localHome = (ProductSessionFacadeHome)
ServiceLocator.getInstance().
ProductSessionFacadeHome.class);
getEjbHome(FACADE_NAME,
/**
* Adiciona um produto no carrinho de compras.
* @param product produto a ser inserido no carrinho de compras.
*/
public void addProduct(ProductTO product) {
this.basket.put(product.getId(), product);
}
286
/**
* Remove um produto do carrinho de compras.
* @param product produto a ser removido do carrinho de compras.
* @return verdadeiro caso a remoo seja efetivada, falso caso contrrio.
*/
public Boolean removeProduct(ProductTO product) {
if (this.basket.remove(product.getId()) != null)
return new Boolean(true);
return new Boolean(false);
}
/**
* Calcula o valor dos produtos contidos na cesta e retorna este valor.
* @return valor total do produtos contidos na cesta.
*/
public Double calcBasketPrice() {
double value = 0;
for (Iterator i = basket.entrySet().iterator(); i.hasNext(); ) {
Map.Entry entry = (Map.Entry) i.next();
value += ((ProductTO) entry.getValue()).getPrice().doubleValue();
}
return new Double(value);
}
/**
* Remove os produtos da cesta de compras.
*/
public void freeBasket() {
this.basket.clear();
}
}
287
class>
<session-type>Stateful</session-type>
<transaction-type>Container</transaction-type>
<ejb-ref>
<description />
<ejb-ref-name>ejb/productfacade</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>com.novatec.book.project.ejb.entity.ProductSessionFacadeHome</
home>
<remote>com.novatec.book.project.ejb.entity.ProductSessionFacade</
remote>
<ejb-link>ProductSessionFacade</ejb-link>
</ejb-ref>
</session>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>SalesBasket</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>
288
/**
* Interface <code>Home</code> utilizada para acesso local.
* Prov os mtodos de criao da entidade usurio e localizao
* do objeto atravs de sua chave primria.
*/
public interface UserLocalHome extends javax.ejb.EJBLocalHome {
/**
* Cria uma referncia local para o componente <code>UserLocal</code>.
* @param name nome do usurio.
* @param cpf cpf do usurio.
* @param address endereo do usurio.
* @param email email do usurio.
* @return referncia local para o componente <code>UserLocal</code>.
* @throws CreateException se ocorrer erro ao criar a instncia.
*/
UserLocal create(String name, String cpf, String address, String email)
throws CreateException;
/**
* Realiza a localizao do objeto pela sua chave primria.
* @param cpf cpf do usurio.
* @return referncia local para o componente <code>UserLocal</code>.
* @throws FinderException exceo em caso de erro ao localizar objeto.
*/
UserLocal findByPrimaryKey(String cpf) throws FinderException;
}
import javax.ejb.*;
import java.util.*;
/**
* Interface <code>Remote</code> utilizada para acesso local e que prov os
* mtodos para configurar e obter os valores dos atributos do usurio.
289
/**
* Obtm o nome do usurio.
* @return nome do usurio.
*/
String getName();
/**
* Obtm o cpf do usurio.
* @return cpf do usurio.
*/
String getCpf();
/**
* Obtm o endereo do usurio.
* @return endereo do usurio.
*/
String getAddress();
/**
* Obtm o email do usurio.
* @return email do usurio.
*/
String getEmail();
/**
* Configura o nome do usurio.
* @param name nome do usurio.
*/
void setName(String name);
/**
* Configura o endereo do usurio.
* @param address endereo do usurio.
*/
void setAddress(String address);
/**
290
import java.rmi.*;
import java.sql.*;
import javax.ejb.*;
import javax.naming.*;
/**
* EJB Entity Bean BMP, responsvel por mantr os dados de usurio
* em um meio persistente.
* <p>
* Apresenta os mtodos de configurao e obteno dos valores dos atributos
* da entidade, criao, remoo, atualizao e localizao da entidade
* no meio de persistncia.
*/
public class UserBean implements EntityBean {
/**
* Contexto do EJB Entity Bean.
*/
private EntityContext entityContext;
/**
* Conexo com o BD.
*/
private transient Connection connection = null;
/**
* Query de insero do objeto no BD.
*/
private final String INSERT_QUERY =
INSERT INTO USER(Name, Cpf, Address, Email) VALUES(?, ?, ?, ?);
291
/**
* Query de remoo do objeto no BD.
*/
private final String DELETE_QUERY = DELETE FROM USER WHERE Cpf = ?;
/**
* Query de obteno do objeto do BD.
*/
private final String SELECT_QUERY =
SELECT Name, Cpf, Address, Email FROM USER WHERE Cpf = ?;
/**
* Query utilizada para obter os objetos dado sua chave primria.
*/
private final String FIND_BY_PK =
SELECT Name, Cpf, Address, Email FROM USER WHERE Cpf = ?;
/**
* Nome do usurio.
*/
private String name;
/**
* CPF do usurio.
*/
private String cpf;
/**
* Endereo do usurio.
*/
private String address;
/**
* Email do usurio.
292
/**
* Utilizado pelo container para criar o objeto usurio.
* @param name nome do usurio.
* @param cpf cpf do usurio.
* @param address endereo do usurio.
* @param email email do usurio.
* @return chave primria da entidade usurio.
* @throws CreateException exceo na criao desta instncia.
*/
public String ejbCreate(String name, String cpf, String address, String email)
throws CreateException {
try {
connection = getConnection();
try {
PreparedStatement stmt = connection.prepareStatement(
INSERT_QUERY);
try {
stmt.setString(1, name);
stmt.setString(2, cpf);
stmt.setString(3, address);
stmt.setString(4, email);
stmt.execute();
} finally {
stmt.close();
}
} finally {
connection.close();
}
} catch (Exception e) {
throw new CreateException();
}
setName(name);
setCpf(cpf);
setAddress(address);
setEmail(email);
return null;
}
293
/**
* Executado aps a criao da instncia.
* Pode ser utilizado para realizar alguma operao neste momento.
* Utilizado para configurar os relacionamentos para o EJB Entity Bean CMP.
* @param name nome do usurio.
* @param cpf cpf do usurio.
* @param address endereo do usurio.
* @param email email do usurio.
* @throws CreateException exceo na criao desta instncia.
*/
public void ejbPostCreate(String name, String cpf, String address, String email)
throws CreateException {
}
/**
* Remoo da instncia do EJB, pelo container.
* @throws RemoveException exceo na remoo do objeto.
*/
public void ejbRemove() throws RemoveException {
try {
connection = getConnection();
try {
PreparedStatement stmt = connection.prepareStatement(
DELETE_QUERY);
try {
stmt.setString(1, this.cpf);
stmt.execute();
} finally {
stmt.close();
}
} finally {
connection.close();
}
} catch (Exception e) {
throw new RemoveException(Error removing element.);
}
}
/**
294
/**
* Configura o cpf do usurio.
* @param cpf cpf do usurio.
*/
public void setCpf(String cpf) {
this.cpf = cpf;
}
/**
* Configura o endereo do usurio.
* @param address endereo do usurio.
*/
public void setAddress(String address) {
this.address = address;
}
/**
* Configura o email do usurio.
* @param email email do usurio.
*/
public void setEmail(String email) {
this.email = email;
}
/**
* Obtm o nome do usurio.
* @return nome do usurio.
*/
public String getName() {
return name;
}
/**
295
/**
* Obtm o endereo do usurio.
* @return endereo do usurio.
*/
public String getAddress() {
return address;
}
/**
* Obtm o email do usurio.
* @return email do usurio.
*/
public String getEmail() {
return email;
}
/**
* Realiza a localizao do objeto pela sua chave primria.
* @param cpf cpf do usurio.
* @return chave primria do objeto em memria.
* @throws FinderException exceo em caso de erro ao localizar objeto.
*/
public String ejbFindByPrimaryKey(String cpf) throws FinderException {
try {
connection = getConnection();
try {
PreparedStatement stmt = connection.prepareStatement(FIND_BY_PK);
try {
stmt.setString(1, cpf);
ResultSet rs = stmt.executeQuery();
296
/**
* Utilizado pelo container para carregar os dados do objeto do meio
* de persistncia para a memria.
*/
public void ejbLoad() {
try {
connection = getConnection();
try {
PreparedStatement stmt = connection.prepareStatement(
SELECT_QUERY);
try {
stmt.setString(1, this.cpf);
ResultSet rs = stmt.executeQuery();
try {
if (rs.next()) {
this.setName(rs.getString(1));
this.setAddress(rs.getString(2));
this.setEmail(rs.getString(3));
297
/**
* Utilizado pelo container para persistir os dados constantes em memria
* para um meio de persistncia.
*/
public void ejbStore() {
try {
connection = getConnection();
try {
PreparedStatement stmt = connection.prepareStatement(
UPDATE_QUERY);
try {
stmt.setString(1, this.name);
stmt.setString(2, this.address);
stmt.setString(3, this.email);
stmt.setString(4, this.cpf);
stmt.execute();
} finally {
stmt.close();
}
} finally {
connection.close();
}
} catch (Exception e) {
throw new EJBException(Error persisting objects.);
}
298
/**
* Utilizado pelo container para ativar o objeto que est passivo.
*/
public void ejbActivate() {
}
/**
* Utilizado pelo container para tornar passivo um objeto ativo.
*/
public void ejbPassivate() {
}
/**
* Desconfigura o contexto do EJB Entity Bean.
*/
public void unsetEntityContext() {
this.entityContext = null;
}
/**
* Configura o contexto do EJB Entity Bean.
* @param entityContext contexto do EJB Entity Bean.
*/
public void setEntityContext(EntityContext entityContext) {
this.entityContext = entityContext;
}
/**
* Cria uma conexo com o banco de dados padro.
* @return conexo do banco de dados.
*/
private Connection getConnection() {
Connection conn = null;
try {
InitialContext ctx = new InitialContext();
javax.sql.DataSource ds = (javax.sql.DataSource) ctx.lookup(
java:/DefaultDS);
conn = ds.getConnection();
299
import javax.ejb.*;
import java.util.*;
import java.rmi.*;
/**
* Intefarce Home, obtm uma referncia para a interface Remote, esta
* ultima que fornece os servios do facade para acesso aos mtodos da
* entidade <code>UserSession</code>.
*/
public interface UserSessionFacadeHome extends javax.ejb.EJBHome {
/**
* Cria uma referncia remota para o componente
* <code>UserSessionFacade</code>.
* @return referncia remota para o componente
* <code>UserSessionFacade</code>.
* @throws CreateException se ocorrer erro ao criar a instncia.
* @throws RemoteException outros erros na criao da instncia.
*/
UserSessionFacade create() throws CreateException, RemoteException;
}
import javax.ejb.*;
import java.util.*;
import java.rmi.*;
import com.novatec.book.project.ejb.to.UserTO;
import java.rmi.RemoteException;
300
/**
* Fornece o servio de Facade para os mtodos da entidade usurio.
*/
public interface UserSessionFacade extends javax.ejb.EJBObject {
/**
* Cria uma entidade usurio dado o seu <code>TransferObject</code>.
* @param userTO <code>TransferObject</code> de usurio.
* @throws RemoteException se ocorrer erro na criao da entidade.
*/
void createUser(UserTO userTO) throws RemoteException;
/**
* Remove a entidade associada chave primria informada.
* @param cpf cpf do usurio.
* @throws RemoteException se ocorrer erro na remoo da entidade.
*/
void removeUser(String cpf) throws RemoteException;
/**
* Remove a entidade cujo <code>TransferObject</code> representa.
* @param userTO <code>TransferObject</code> do usurio.
* @throws RemoteException se ocorrer erro na remoo da entidade.
*/
void removeUser(UserTO userTO) throws RemoteException;
/**
* Atualiza os dados da entidade usurio pelo <code>TransferObject</code>.
* @param userTO <code>TransferObject</code> do usurio.
* @throws RemoteException se ocorrer erro na atualizao da entidade.
*/
void updateUser(UserTO userTO) throws RemoteException;
/**
* Atualiza os dados das entidades contidas na coleo de usurios.
* @param userTOs coleo de <code>TransferObject</code> de usurio.
* @throws RemoteException se ocorrer erro ao atualizar as entidades.
*/
void updateUsers(UserTO[] userTOs) throws RemoteException;
301
/**
* Localiza um usurio dado a sua chave primria.
* @param cpf cpf do usurio.
* @return <code>TransferObject</code> do usurio.
* @throws RemoteException se ocorrer erro ao localizar o produto.
*/
UserTO userFindByPrimaryKey(String cpf) throws RemoteException;
}
import com.novatec.book.project.ejb.ServiceLocator;
import com.novatec.book.project.ejb.entity.impl.UserLocalHome;
import com.novatec.book.project.ejb.ServiceLocatorException;
import com.novatec.book.project.ejb.to.UserTOAssembler;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import javax.ejb.*;
import com.novatec.book.project.ejb.to.UserTO;
import java.rmi.RemoteException;
import com.novatec.book.project.ejb.entity.impl.UserLocal;
import java.util.Collection;
/**
* EJB Session Bean Stateless utilizado como Facade para a entidade usurio.
*/
public class UserSessionFacadeBean implements SessionBean {
/**
* Contexto do Session Bean.
*/
SessionContext sessionContext;
/**
* Referncia local para a interface <code>Home</code> da entidade usurio.
*/
302
/**
* Criao da instncia deste objeto pelo container.
* @throws CreateException exceo na criao da instncia do EJB.
*/
public void ejbCreate() throws CreateException {
}
/**
* Remoo da instncia do EJB, pelo container.
*/
public void ejbRemove() {
}
/**
* Utilizado pelo container para ativar o objeto que est passivo.
*/
public void ejbActivate() {
}
/**
* Utilizado pelo container para tornar passivo um objeto ativo.
*/
public void ejbPassivate() {
}
/**
* Configura o contexto do EJB Session Bean.
* @param sessionContext contexto do EJB Session Bean.
*/
public void setSessionContext(SessionContext sessionContext) {
try {
findUserHome();
} catch (Exception e) {
throw new EJBException(e.getMessage());
}
this.sessionContext = sessionContext;
}
303
/**
* Remove a entidade associada chave primria informada.
* @param cpf cpf do usurio.
* @throws RemoteException se ocorrer erro na remoo da entidade.
*/
public void removeUser(String cpf) throws RemoteException {
try {
UserLocal user = userLocalHome.findByPrimaryKey(cpf);
userLocalHome.remove(user);
} catch (Exception e) {
throw new RemoteException(e.getMessage());
}
}
/**
* Remove a entidade cujo <code>TransferObject</code> representa.
* @param userTO <code>TransferObject</code> do usurio.
* @throws RemoteException se ocorrer erro na remoo da entidade.
*/
public void removeUser(UserTO userTO) throws RemoteException {
304
/**
* Atualiza os dados da entidade usurio pelo <code>TransferObject</code>.
* @param userTO <code>TransferObject</code> do usurio.
* @throws RemoteException se ocorrer erro na atualizao da entidade.
*/
public void updateUser(UserTO userTO) throws RemoteException {
if (userTO != null) {
String cpf = userTO.getCpf();
try {
UserLocal user = userLocalHome.findByPrimaryKey(cpf);
setUserFromUserTO(user, userTO);
} catch (FinderException e) {
throw new RemoteException(e.getMessage());
}
}
}
/**
* Atualiza os dados das entidades contidas na coleo de usurios.
* @param userTOs coleo de <code>TransferObject</code> de usurio.
* @throws RemoteException se ocorrer erro ao atualizar as entidades.
*/
public void updateUsers(UserTO[] userTOs) throws RemoteException {
if (userTOs != null) {
for (int i = 0; i < userTOs.length; i++) {
updateUser(userTOs[i]);
}
}
}
/**
* Localiza um usurio dado a sua chave primria.
* @param cpf cpf do usurio.
* @return <code>TransferObject</code> do usurio.
305
/**
* Configura os atributos do usurio.
* @param userLocal referncia local para a entidade usurio.
* @param userTO <code>TransferObject</code> do usurio.
*/
private void setUserFromUserTO(UserLocal userLocal, UserTO userTO) {
userLocal.setName(userTO.getName());
userLocal.setAddress(userTO.getAddress());
userLocal.setEmail(userTO.getEmail());
}
/**
* Localiza a entidade usurio e configura sua interface home.
* @throws RemoteException se ocorrer erro ao localizar o componente.
*/
private void findUserHome() throws RemoteException {
final String ENTITY_NAME = java:comp/env/ejb/user;
if (userLocalHome == null) {
try {
ServiceLocator locator = ServiceLocator.getInstance();
userLocalHome = (UserLocalHome) locator.getEjbLocalHome(
ENTITY_NAME);
} catch (ServiceLocatorException e) {
throw new RemoteException(e.getMessage());
}
}
}
/**
* Cria um objeto <code>TransferObject</code> do usurio a partir da
306
/**
* Cria uma coleo de <code>TransferObject</code> do usurio a partir da
* coleo das entidades de usurio.
* @param userLocals coleo das entidades de usurio.
* @return coleo de <code>TransferObject</code> do usurio.
*/
private UserTO[] assembleUserTOs(Collection userLocals) {
List list = new ArrayList();
if (userLocals != null) {
Iterator iterator = userLocals.iterator();
while (iterator.hasNext()) {
UserLocal userLocal = (UserLocal) iterator.next();
list.add(assembleUserTO(userLocal));
}
}
UserTO[] returnArray = new UserTO[list.size()];
return (UserTO[]) list.toArray(returnArray);
}
}
<ejb-class>com.novatec.book.project.ejb.entity.UserSessionFacadeBean</
307
local-home>
<local>com.novatec.book.project.ejb.entity.impl.UserLocal</local>
<ejb-link>User</ejb-link>
</ejb-local-ref>
</session>
<entity>
<display-name>User</display-name>
<ejb-name>User</ejb-name>
local-home>
<local-home>com.novatec.book.project.ejb.entity.impl.UserLocalHome</
<local>com.novatec.book.project.ejb.entity.impl.UserLocal</local>
<ejb-class>com.novatec.book.project.ejb.entity.impl.UserBean</ejb-class>
<persistence-type>Bean</persistence-type>
<prim-key-class>java.lang.String</prim-key-class>
<reentrant>False</reentrant>
</entity>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>UserSessionFacade</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
<container-transaction>
<method>
<ejb-name>User</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>
308
EJB Entity Bean CMP ProductBean e EJB Session Bean Stateless ProductSessionFacade
O prximo cdigo apresenta o EJB Entity Bean CMP ProductBean. Este EJB apresenta
tambm as interfaces Local e LocalHome que so respectivamente, ProductLocal e
ProductLocalHome. Em seguida temos a implementao do EJB ProductBean e de
sua chave primria ProductPK. Observe que como definimos este EJB como Entity
Bean CMP, a implementao do EJB ProductBean no apresenta codificao para os
mtodos de persistncia do objeto. Como sabemos, isto feito pelo prprio container do servidor de aplicaes. Alm deste, temos o SessionFacade ProductSessionFacade e por fim apresentamos o deployment descriptor deste EJB.
import javax.ejb.*;
import java.util.*;
/**
* Interface <code>Home</code> utilizada para acesso local.
* Prov os mtodos de criao da entidade produto e localizao
* do objeto atravs de sua chave primria.
*/
public interface ProductLocalHome extends javax.ejb.EJBLocalHome {
/**
* Cria uma referncia local para o componente <code>ProductLocal</code>.
* @param name nome do produto.
* @param description descrio do produto.
* @param price preo do produto.
* @param id chave primria do produto.
* @return chave primria do produto.
* @return referncia local para o componente <code>ProductLocal</code>.
* @throws CreateException se ocorrer erro ao criar a instncia.
*/
ProductLocal create(String name, String description, Double price, Integer id)
throws CreateException;
/**
* Realiza a localizao do objeto pela sua chave primria.
309
/**
* Localiza todos os objetos.
* @return coleo de referncias locais para os componentes do tipo
* <code>ProductLocal</code>.
* @throws FinderException exceo em caso de erro ao localizar os objetos.
*/
Collection findAll() throws FinderException;
}
import javax.ejb.*;
import java.util.*;
/**
* Interface <code>Remote</code> utilizada para acesso local e que prov os
* mtodos para configurar e obter os valores dos atributos do produto.
*/
public interface ProductLocal extends javax.ejb.EJBLocalObject {
/**
* Configura o nome do produto.
* Implementado pelo container para o Entity Bean CMP.
* @param name nome do produto.
*/
void setName(String name);
/**
* Obtm o nome do produto.
* Implementado pelo container para o Entity Bean CMP.
* @return nome do produto.
*/
String getName();
310
/**
* Configura a descrio do produto.
* Implementado pelo container para o Entity Bean CMP.
* @param description descrio do produto.
*/
void setDescription(String description);
/**
* Obtm a descrio do produto.
* Implementado pelo container para o Entity Bean CMP.
* @return descrio do produto.
*/
String getDescription();
/**
* Configura o preo do produto.
* Implementado pelo container para o Entity Bean CMP.
* @param price preo do produto.
*/
void setPrice(Double price);
/**
* Obtm o preo do produto.
* @return preo do produto.
*/
Double getPrice();
/**
* Obtm a chave primria do produto.
* @return chave primria do produto.
*/
Integer getId();
}
import javax.ejb.*;
311
/**
* Contexto do EJB Entity Bean.
*/
private EntityContext entityContext;
/**
* Utilizado pelo container para criar o objeto produto.
* @param name nome do produto.
* @param description descrio do produto.
* @param price preo do produto.
* @param id chave primria do produto.
* @return chave primria do produto.
* @throws CreateException exceo na criao desta instncia.
*/
public ProductPK ejbCreate(String name, String description, Double price,
Integer id)
throws CreateException {
setName(name);
setDescription(description);
setPrice(price);
setId(id);
return null;
}
/**
312
/**
* Remoo da instncia do EJB, pelo container.
* @throws RemoveException exceo na remoo do objeto.
*/
public void ejbRemove() throws RemoveException {
}
/**
* Utilizado pelo container para carregar os dados do objeto do meio
* de persistncia para a memria.
*/
public void ejbLoad() {
}
/**
* Utilizado pelo container para persistir os dados constantes em memria
* para um meio de persistncia.
*/
public void ejbStore() {
}
/**
* Utilizado pelo container para ativar o objeto que est passivo.
*/
public void ejbActivate() {
}
313
/**
* Desconfigura o contexto do EJB Entity Bean.
*/
public void unsetEntityContext() {
this.entityContext = null;
}
/**
* Configura o contexto do EJB Entity Bean.
* @param entityContext contexto do EJB Entity Bean.
*/
public void setEntityContext(EntityContext entityContext) {
this.entityContext = entityContext;
}
/**
* Configura o nome do produto.
* Implementado pelo container para o Entity Bean CMP.
* @param name nome do produto.
*/
public abstract void setName(String name);
/**
* Configura a descrio do produto.
* Implementado pelo container para o Entity Bean CMP.
* @param description descrio do produto.
*/
public abstract void setDescription(String description);
/**
* Configura o preo do produto.
* Implementado pelo container para o Entity Bean CMP.
* @param price preo do produto.
*/
314
/**
* Configura a chave primria do produto.
* @param id chave primria do produto.
*/
public abstract void setId(Integer id);
/**
* Obtm o nome do produto.
* Implementado pelo container para o Entity Bean CMP.
* @return nome do produto.
*/
public abstract String getName();
/**
* Obtm a descrio do produto.
* Implementado pelo container para o Entity Bean CMP.
* @return descrio do produto.
*/
public abstract String getDescription();
/**
* Obtm o preo do produto.
* Implementado pelo container para o Entity Bean CMP.
* @return preo do produto.
*/
public abstract Double getPrice();
/**
* Obtm a chave primria do produto.
* @return chave primria do produto.
*/
public abstract Integer getId();
}
import java.io.*;
315
/**
* Classe que define uma chave primria para a entidade produto.
*/
public class ProductPK implements Serializable {
/**
* Identificador nico do objeto produto.
*/
private Integer id;
/**
* Construtor padro.
*/
public ProductPK() {
}
/**
* Construtor customizado.
* @param id identificador do produto.
*/
public ProductPK(Integer id) {
this.id = id;
}
/**
* Obtm a chave primria Id da entidade produto.
* @return chave primria Id da entidade produto.
*/
public Integer getId() {
return this.id;
}
/**
* Avalia se o objeto informado, igual a este objeto.
* @param obj objeto a ser comparado.
* @return verdadeiro caso o objeto seja igual, falso caso contrrio.
*/
public boolean equals(Object obj) {
if ( this == obj ) {
316
/**
* Chave de Hash, utilizada pelas Maps, para manter este objeto.
* @return chave de hash para este objeto.
*/
public int hashCode() {
int result = 17;
result = 37 * result + id.hashCode();
return result;
}
/**
* Obtm uma descrio textual do objeto.
* @return descrio textual do objeto.
*/
public String toString() {
StringBuffer sb = new StringBuffer(1024);
sb.append([ + id + ]);
return sb.toString();
}
}
import javax.ejb.*;
import java.util.*;
import java.rmi.*;
317
/**
* Interface Home, obtm uma referncia para a interface Remote, esta
* ultima que fornece os servios do facade para acesso aos mtodos da
* entidade <code>ProductSession</code>.
*/
public interface ProductSessionFacadeHome extends javax.ejb.EJBHome {
/**
* Cria uma referncia remota para o componente
* <code>ProductSessionFacade</code>.
* @return referncia remota para o componente
* <code>ProductSessionFacade</code>.
* @throws CreateException se ocorrer erro ao criar a instncia.
* @throws RemoteException outros erros na criao da instncia.
*/
ProductSessionFacade create() throws CreateException, RemoteException;
}
import javax.ejb.*;
import java.util.*;
import java.rmi.*;
import com.novatec.book.project.ejb.to.*;
import com.novatec.book.project.ejb.entity.impl.ProductPK;
import java.rmi.RemoteException;
import com.novatec.book.project.ejb.to.ProductTO;
/**
* Apresenta o Facade para acesso aos mtodos da entidade Produto.
*/
public interface ProductSessionFacade extends javax.ejb.EJBObject {
/**
* Cria uma entidade produto dado o seu <code>TransferObject</code>.
* @param productTO <code>TransferObject</code> de produto.
318
/**
* Remove a entidade associada chave primria informada.
* @param productPK chave primria do produto.
* @throws RemoteException se ocorrer erro na remoo da entidade.
*/
void removeProduct(ProductPK productPK) throws RemoteException;
/**
* Remove a entidade cujo <code>TransferObject</code> representa.
* @param productTO <code>TransferObject</code> do produto.
* @throws RemoteException se ocorrer erro na remoo da entidade.
*/
void removeProduct(ProductTO productTO) throws RemoteException;
/**
* Atualiza os dados da entidade produto pelo <code>TransferObject</code>.
* @param productTO <code>TransferObject</code> do produto.
* @throws RemoteException se ocorrer erro na atualizao da entidade.
*/
void updateProduct(ProductTO productTO) throws RemoteException;
/**
* Atualiza os dados das entidades contidas na coleo de produtos.
* @param productTOs coleo de <code>TransferObject</code> de produto.
* @throws RemoteException se ocorrer erro ao atualizar as entidades.
*/
void updateProducts(ProductTO[] productTOs) throws RemoteException;
/**
* Localiza um produto dado a sua chave primria.
* @param productPK chave primria do produto.
* @return <code>TransferObject</code> do produto.
* @throws RemoteException se ocorrer erro ao localizar o produto.
*/
ProductTO productFindByPrimaryKey(ProductPK productPK) throws RemoteException;
319
import
com.novatec.book.project.ejb.entity.impl.ProductLocalHome;
import com.novatec.book.project.ejb.ServiceLocator;
import com.novatec.book.project.ejb.ServiceLocatorException;
import com.novatec.book.project.ejb.to.ProductTOAssembler;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import javax.ejb.*;
import com.novatec.book.project.ejb.to.ProductTO;
import com.novatec.book.project.ejb.entity.impl.*;
import java.rmi.RemoteException;
import java.util.Collection;
import com.novatec.book.project.ejb.entity.impl.ProductLocal;
import java.util.*;
/**
* Fornece o servio de Facade para os mtodos da entidade produto.
*/
public class ProductSessionFacadeBean implements SessionBean {
/**
* Contexto do Session Bean.
*/
SessionContext sessionContext;
/**
* Referncia local para a interface <code>Home</code> de produto.
320
/**
* Criao da instncia deste objeto pelo container.
* @throws CreateException exceo na criao da instncia do EJB.
*/
public void ejbCreate() throws CreateException {
}
/**
* Remoo da instncia do EJB, pelo container.
*/
public void ejbRemove() {
}
/**
* Utilizado pelo container para ativar o objeto que est passivo.
*/
public void ejbActivate() {
}
/**
* Utilizado pelo container para tornar passivo um objeto ativo.
*/
public void ejbPassivate() {
}
/**
* Configura o contexto do EJB Session Bean.
* @param sessionContext contexto do EJB Session Bean.
*/
public void setSessionContext(SessionContext sessionContext) {
try {
findProductHome();
} catch (Exception e) {
throw new EJBException(e.getMessage());
}
this.sessionContext = sessionContext;
}
321
/**
* Cria uma entidade produto dado o seu <code>TransferObject</code>.
* @param productTO <code>TransferObject</code> de produto.
* @throws RemoteException se ocorrer erro na criao da entidade.
*/
public void createProduct(ProductTO productTO) throws RemoteException {
if (productTO == null) {
return;
}
try {
ProductLocal productLocal = productLocalHome.create(
productTO.getName(),
productTO.getDescription(),
productTO.getPrice(),
productTO.getId());
} catch (CreateException e) {
throw new RemoteException(e.getMessage());
}
}
/**
* Remove a entidade associada chave primria informada.
* @param productPK chave primria do produto.
* @throws RemoteException se ocorrer erro na remoo da entidade.
*/
public void removeProduct(ProductPK productPK) throws RemoteException {
try {
ProductLocal product =
productLocalHome.findByPrimaryKey(productPK.getId());
productLocalHome.remove(product);
} catch (Exception e) {
throw new RemoteException(e.getMessage());
}
}
/**
* Remove a entidade cujo <code>TransferObject</code> representa.
* @param productTO <code>TransferObject</code> do produto.
* @throws RemoteException se ocorrer erro na remoo da entidade.
*/
322
/**
* Atualiza os dados da entidade produto pelo <code>TransferObject</code>.
* @param productTO <code>TransferObject</code> do produto.
* @throws RemoteException se ocorrer erro na atualizao da entidade.
*/
public void updateProduct(ProductTO productTO) throws RemoteException {
if (productTO != null) {
ProductPK productPK =
new ProductPK(productTO.getId());
try {
ProductLocal product = productLocalHome.findByPrimaryKey(
productPK.getId());
setProductFromProductTO(product, productTO);
} catch (FinderException e) {
throw new RemoteException(e.getMessage());
}
}
}
/**
* Atualiza os dados das entidades contidas na coleo de produtos.
* @param productTOs coleo de <code>TransferObject</code> de produto.
* @throws RemoteException se ocorrer erro ao atualizar as entidades.
*/
public void updateProducts(ProductTO[] productTOs) throws RemoteException {
if (productTOs != null) {
for (int i = 0; i < productTOs.length; i++) {
updateProduct(productTOs[i]);
}
}
}
323
/**
* Localiza todos os produtos.
* @return coleo de <code>TransferObject</code> do produto.
* @throws RemoteException exceo em caso de erro ao localizar os produtos.
*/
public Collection productFindAll() throws RemoteException {
try {
Collection products = productLocalHome.findAll();
Collection returnProducts = new ArrayList(products.size());
for (Iterator iter = products.iterator(); iter.hasNext(); ) {
ProductLocal product = (ProductLocal) iter.next();
returnProducts.add(assembleProductTO(product));
}
return returnProducts;
} catch (FinderException e) {
throw new RemoteException(e.getMessage());
}
}
/**
* Configura os atributos da entidade produto.
* @param productLocal referncia local para a entidade produto.
* @param productTO <code>TransferObject</code> de produto.
*/
324
/**
* Localiza a entidade produto.
* @throws RemoteException se ocorrer erro ao localizar a entidade.
*/
private void findProductHome() throws RemoteException {
final String ENTITY_NAME = java:comp/env/ejb/product;
if (productLocalHome == null) {
try {
ServiceLocator locator = ServiceLocator.getInstance();
productLocalHome = (ProductLocalHome) locator.getEjbLocalHome(
ENTITY_NAME);
} catch (ServiceLocatorException e) {
throw new RemoteException(e.getMessage());
}
}
}
/**
* Cria um <code>TransferObject</code> de produto atravs da entidade.
* @param productLocal entidade produto.
* @return <code>TransferObject</code> de produto.
*/
private ProductTO assembleProductTO(ProductLocal productLocal) {
return ProductTOAssembler.createTO(productLocal);
}
/**
* Cria uma coleo de <code>TransferObject</code> de produto atravs da
* coleo de entidades produto.
* @param productLocals entidades produto.
* @return coleo de <code>TransferObject</code> de produto.
*/
private ProductTO[] assembleProductTOs(Collection productLocals) {
List list = new ArrayList();
325
<home>com.novatec.book.project.ejb.entity.ProductSessionFacadeHome</
<remote>com.novatec.book.project.ejb.entity.ProductSessionFacade</
<ejbclass>com.novatec.book.project.ejb.entity.ProductSessionFacadeBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<ejb-local-ref>
<description />
<ejb-ref-name>ejb/product</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<localhome>com.novatec.book.project.ejb.entity.impl.ProductLocalHome</local-home>
<local>com.novatec.book.project.ejb.entity.impl.ProductLocal</local>
<ejb-link>Product</ejb-link>
</ejb-local-ref>
</session>
<entity>
<display-name>Product</display-name>
<ejb-name>Product</ejb-name>
326
<local-home>com.novatec.book.project.ejb.entity.impl.ProductLocalHome</
<local>com.novatec.book.project.ejb.entity.impl.ProductLocal</local>
class>
<ejb-class>com.novatec.book.project.ejb.entity.impl.ProductBean</ejb<persistence-type>Container</persistence-type>
<prim-key-class>com.novatec.book.project.ejb.entity.impl.ProductPK</
prim-key-class>
<reentrant>False</reentrant>
<cmp-version>2.x</cmp-version>
<abstract-schema-name>Product</abstract-schema-name>
<cmp-field>
<field-name>name</field-name>
</cmp-field>
<cmp-field>
<field-name>description</field-name>
</cmp-field>
<cmp-field>
<field-name>price</field-name>
</cmp-field>
<cmp-field>
<field-name>id</field-name>
</cmp-field>
<primkey-field>id</primkey-field>
<query>
<query-method>
<method-name>findAll</method-name>
<method-params />
</query-method>
<ejb-ql>SELECT OBJECT(p) FROM Product p</ejb-ql>
</query>
</entity>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>ProductSessionFacade</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
327
import java.util.*;
import javax.ejb.*;
import javax.jms.*;
import javax.mail.*;
import javax.naming.*;
import javax.mail.internet.*;
import com.novatec.book.project.ejb.to.*;
/**
* Responsvel por notificar o usurio das novas atualizaes do
* estado da venda de seu produto, tais como produto localizado,
* produto enviado, venda finalizada etc.
* O mtodo onMessage() responsvel por receber um mensagem do
* tipo TextMessage e enviar um email para o usurio com esta mensagem.
*/
public class UserNotifierBean implements MessageDrivenBean, MessageListener {
/**
328
/**
* Define o host utilizado para enviar o email.
*/
private static final String HOST =
<aqui_deve_vir_o_host_utilizado_para_enviar_o_email>;
/**
* Instncia o objeto no servidor pelo container.
*/
public void ejbCreate() {
}
/**
* Remove a instncia do objeto no servidor.
*/
public void ejbRemove() {
}
/**
* Valida a mensagem recebida e envia uma notificao ao usurio com
* a mensagem texto recebida como parmentro.
* @param msg mensagem a ser notificada.
*/
public void onMessage(javax.jms.Message msg) {
try {
if (msg instanceof ObjectMessage) {
UserMessage message = (UserMessage) ((ObjectMessage)
msg).getObject();
UserTO user = message.getUser();
this.sendEmail(HOST, user.getEmail(),
Sales Notification, message.getMessage());
}
} catch (Exception ex) {
System.err.println(Error sending email for user. + ex);
}
}
329
// Obtm a sesso
javax.mail.Session session = javax.mail.Session.getDefaultInstance(
props, null);
// Define a mensagem
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(Shop));
message.addRecipient(javax.mail.Message.RecipientType.TO,
new InternetAddress(to));
message.setSubject(subject);
message.setText(text);
// Envia a mensagem
Transport.send(message);
} catch (Exception e) {
throw new Exception(Error sending mail! + e);
}
}
/**
* Configura o contexto do EJB MDB.
* @param messageDrivenContext contexto do MDB.
*/
public void setMessageDrivenContext(MessageDrivenContext messageDrivenContext) {
330
Mensagem : UserMessage.
package com.novatec.book.project.ejb.mdb;
import java.io.*;
import com.novatec.book.project.ejb.to.*;
/**
* Objeto que contm a mensagem a ser entregue para o usurio.
* O usurio tambm definido neste objeto.
*/
public class UserMessage implements Serializable {
/**
* Usurio o qual ser enviado a mensagem.
*/
private UserTO user;
/**
* Mensagem a ser enviada para o usurio.
*/
private String message;
/**
* Construtor padro.
*/
public UserMessage() {
}
/**
* Construtor customizado.
* @param user usurio o qual ser enviado a mensagem.
* @param message mensagem a ser enviada para o usurio.
*/
public UserMessage(UserTO user, String message) {
331
/**
* Obtm a mensagem a ser enviada para o usurio.
* @return mensagem a ser enviada para o usurio.
*/
public String getMessage() {
return message;
}
/**
* Configura a mensagem a ser enviada para o usurio.
* @param message mensagem a ser enviada para o usurio.
*/
public void setMessage(String message) {
this.message = message;
}
/**
* Obtm o usurio o qual ser enviado a mensagem.
* @return usurio o qual ser enviado a mensagem.
*/
public UserTO getUser() {
return user;
}
/**
* Configura o usurio o qual ser enviado a mensagem.
* @param user usurio o qual ser enviado a mensagem.
*/
public void setUser(UserTO user) {
this.user = user;
}
}
332
import javax.ejb.*;
import java.util.*;
import java.rmi.*;
/**
* Inteface Home, obtm uma referncia para a interface Remote, esta
* ultima que fornece os servios de suporte a aplicao exemplo.
333
/**
* Cria uma referncia remota para o componente <code>ProjectSupport</code>.
* @return referncia remota para o componente <code>ProjectSupport</code>.
* @throws CreateException se ocorrer erro ao criar a instncia.
* @throws RemoteException outros erros na criao da instncia.
*/
ProjectSupport create() throws CreateException, RemoteException;
}
import javax.ejb.*;
import java.util.*;
import java.rmi.*;
/**
* Interface Remote do EJB <code>ProjectSupportBean</code>.
* Apresenta servios de suporte para a aplicao exemplo.
*/
public interface ProjectSupport extends javax.ejb.EJBObject {
/**
* Prepara o amibente para a execuo da aplicao exemplo.
* @throws RemoteException se ocorrer erro ao executar o mtodo.
*/
void prepareEnvironment() throws RemoteException;
/**
* Limpa o ambiente de execuo da aplicao exemplo.
* @throws RemoteException se ocorrer erro ao executar o mtodo.
*/
void clearEnvironment() throws RemoteException;
}
334
import java.sql.*;
import java.rmi.*;
import javax.ejb.*;
import javax.naming.*;
/**
* EJB Session Bean Stateless utilizado como servio de suporte para
* a aplicao exemplo.
* <p>
* Prov servios para preparao do ambiente.
*/
public class ProjectSupportBean implements SessionBean {
/**
* Contexto do Session Bean.
*/
private SessionContext sessionContext;
/**
* Criao da instncia deste objeto pelo container.
* @throws CreateException exceo na criao da instncia do EJB.
*/
public void ejbCreate() throws CreateException {
}
/**
* Remoo da instncia do EJB, pelo container.
*/
public void ejbRemove() {
}
/**
* Utilizado pelo container para ativar o objeto que est passivo.
*/
public void ejbActivate() {
}
335
/**
* Utilizado pelo container para tornar passivo um objeto ativo.
*/
public void ejbPassivate() {
}
/**
* Configura o contexto do EJB Session Bean.
* @param sessionContext contexto do EJB Session Bean.
*/
public void setSessionContext(SessionContext sessionContext) {
this.sessionContext = sessionContext;
}
/**
* Prepara o amibente para a execuo da aplicao exemplo.
*/
public void prepareEnvironment() {
System.out.println(Preparing environment.);
try {
InitialContext ctx = new InitialContext();
javax.sql.DataSource ds = (javax.sql.DataSource) ctx.lookup(
java:/DefaultDS);
Connection conn = ds.getConnection();
try {
PreparedStatement stmt = conn.prepareStatement(
CREATE TABLE USER (NAME VARCHAR(40), CPF VARCHAR(30),
+ ADDRESS VARCHAR(50), EMAIL VARCHAR(30),
+ CONSTRAINT PK_USER PRIMARY KEY (CPF) ));
try {
stmt.execute();
} finally {
stmt.close();
}
} finally {
conn.close();
}
} catch (Exception ex) {
throw new EJBException(Error preparing environment. +
336
/**
* Limpa o ambiente de execuo da aplicao exemplo.
*/
public void clearEnvironment() {
System.out.println(Clearing environment.);
try {
InitialContext ctx = new InitialContext();
javax.sql.DataSource ds = (javax.sql.DataSource) ctx.lookup(
java:/DefaultDS);
Connection conn = ds.getConnection();
try {
PreparedStatement stmt = conn.prepareStatement(
DROP TABLE USER);
try {
stmt.execute();
} finally {
stmt.close();
}
} finally {
conn.close();
}
} catch (Exception ex) {
throw new EJBException(Error clearing environment. +
ex.getMessage());
}
System.out.println(Do it.);
}
}
337
class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>ProjectSupport</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>
TransferObject : ProductTO
package com.novatec.book.project.ejb.to;
/**
* Apresenta um <code>TransferObject</code> de Produtos.
* Este VO ser utilizado pelo cliente, para informar os produtos
* selecionados na compra.
*/
public class ProductTO implements java.io.Serializable {
/**
* Identificador do produto.
338
/**
* Nome do produto.
*/
private String name;
/**
* Descrio do produto.
*/
private String description;
/**
* Preo do produto.
*/
private Double price;
/**
* Construtor padro.
*/
public ProductTO() {
}
/**
* Construtor customizado.
* @param id identificador do produto.
* @param name nome do produto.
* @param description descrio do produto.
* @param price preo do produto.
*/
public ProductTO(Integer id, String name, String description,
Double price) {
this.id = id;
this.name = name;
this.description = description;
this.price = price;
}
/**
339
/**
* Configura o identificador do produto.
* @param id identificador do produto.
*/
public void setId(Integer id) {
this.id = id;
}
/**
* Obtm o nome do produto.
* @return nome do produto.
*/
public String getName() {
return name;
}
/**
* Configura o nome do produto.
* @param name nome do produto.
*/
public void setName(String name) {
this.name = name;
}
/**
* Obtm a descrio do produto.
* @return descrio do produto.
*/
public String getDescription() {
return description;
}
/**
340
/**
* Obtm o preo do produto.
* @return preo do produto.
*/
public Double getPrice() {
return price;
}
/**
* Configura o preo do produto.
* @param price preo do produto.
*/
public void setPrice(Double price) {
this.price = price;
}
/**
* Avalia se o objeto informado, igual a este objeto.
* @param obj objeto a ser comparado.
* @return verdadeiro caso o objeto seja igual, falso caso contrrio.
*/
public boolean equals(Object obj) {
if ( this == obj ) {
return true;
}
341
/**
* Chave de Hash, utilizada pelas Maps, para manter este objeto.
* @return chave de hash para este objeto.
*/
public int hashCode() {
int result = 17;
result = 37 * result + id.hashCode();
result = 37 * result + name.hashCode();
result = 37 * result + description.hashCode();
result = 37 * result + price.hashCode();
return result;
}
/**
* Obtm uma descrio textual do objeto.
* @return descrio textual do objeto.
*/
public String toString() {
StringBuffer sb = new StringBuffer(1024);
sb.append([ + id + , + name + , + description
+ , + price + ]);
return sb.toString();
}
}
TransferObject : UserTO
package com.novatec.book.project.ejb.to;
/**
* Apresenta um <code>TransferObject</code> de usurio.
* Contm um identificador para o usurio, nome, endereo e email.
*/
public class UserTO implements java.io.Serializable {
/**
342
/**
* Nome do usurio.
*/
private String name;
/**
* CPF do usurio.
*/
private String cpf;
/**
* Endereo do usurio.
*/
private String address;
/**
* Email do usurio.
*/
private String email;
/**
* Construtor padro.
*/
public UserTO() {
}
/**
* Construtor customizado.
* @param id identificador do produto.
* @param name nome do produto.
* @param cpf cpf do usurio.
* @param address endereo do usurio.
* @param email email do usurio.
*/
public UserTO(Integer id, String name, String cpf, String address,
String email) {
343
/**
* Obtm o endereo do usurio.
* @return endereo do usurio.
*/
public String getAddress() {
return address;
}
/**
* Configura o endereo do usurio.
* @param address endereo do usurio.
*/
public void setAddress(String address) {
this.address = address;
}
/**
* Obtm o email do usurio.
* @return email do usurio.
*/
public String getEmail() {
return email;
}
/**
* Configura o email do usurio.
* @param email email do usurio.
*/
public void setEmail(String email) {
this.email = email;
}
/**
344
/**
* Configura o identificador do usurio.
* @param id identificador do usurio.
*/
public void setId(Integer id) {
this.id = id;
}
/**
* Obtm o nome do usurio.
* @return nome do usurio.
*/
public String getName() {
return name;
}
/**
* Configura o nome do usurio.
* @param name nome do usurio.
*/
public void setName(String name) {
this.name = name;
}
/**
* Obtm o cpf do usurio.
* @return cpf do usurio.
*/
public String getCpf() {
return cpf;
}
/**
345
/**
* Avalia se o objeto informado, igual a este objeto.
* @param obj objeto a ser comparado.
* @return verdadeiro caso o objeto seja igual, falso caso contrrio.
*/
public boolean equals(Object obj) {
if ( this == obj ) {
return true;
}
/**
* Chave de Hash, utilizada pelas Maps, para manter este objeto.
* @return chave de hash para este objeto.
*/
public int hashCode() {
int result = 17;
result = 37 * result + id.hashCode();
result = 37 * result + name.hashCode();
result = 37 * result + cpf.hashCode();
result = 37 * result + address.hashCode();
346
/**
* Obtm uma descrio textual do objeto.
* @return descrio textual do objeto.
*/
public String toString() {
StringBuffer sb = new StringBuffer(1024);
sb.append([ + id + , + name + , + cpf + , + address
+ , + email + ]);
return sb.toString();
}
}
Assembler : ProductTOAssembler
package com.novatec.book.project.ejb.to;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Collection;
import java.util.List;
import com.novatec.book.project.ejb.entity.impl.ProductLocal;
/**
* Fornece <code>TransferObject</code> de Produto.
*/
public class ProductTOAssembler {
/**
* Cria uma <code>TransferObject</code> a partir da referncia
* remota da entidade produto.
* @param productLocal referncia remota da entidade produto.
* @return objeto <code>TransferObject</code> de produto.
*/
public static ProductTO createTO(ProductLocal productLocal) {
ProductTO productTO = new ProductTO();
if (productLocal != null) {
347
/**
* Cria uma coleo de <code>TransferObject</code> do tipo ProductTO.
* @param productLocals coleo de referncias remotas da entidade produto.
* @return coleo de objetos <code>TransferObject</code> ProductTO.
*/
public static ProductTO[] createTOs(Collection productLocals) {
List list = new ArrayList();
if (productLocals != null) {
Iterator iterator = productLocals.iterator();
while (iterator.hasNext()) {
list.add(createTO((ProductLocal) iterator.next()));
}
}
ProductTO[] returnArray = new ProductTO[list.size()];
return (ProductTO[]) list.toArray(returnArray);
}
}
Assembler : UserTOAssembler
package com.novatec.book.project.ejb.to;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Collection;
import java.util.List;
import com.novatec.book.project.ejb.entity.impl.UserLocal;
/**
* Fornece <code>TransferObject</code> de Produto.
*/
public class UserTOAssembler {
348
/**
* Cria uma <code>TransferObject</code> a partir da referncia
* remota da entidade usurio.
* @param userLocal referncia remota da entidade usurio.
* @return objeto <code>TransferObject</code> de usurio.
*/
public static UserTO createTO(UserLocal userLocal) {
UserTO userTO = new UserTO();
if (userLocal != null) {
userTO.setName(userLocal.getName());
userTO.setCpf(userLocal.getCpf());
userTO.setAddress(userLocal.getAddress());
userTO.setEmail(userLocal.getEmail());
}
return userTO;
}
/**
* Cria uma coleo de <code>TransferObject</code> do tipo UserTO.
* @param userLocals coleo de referncias remotas da entidade usurio.
* @return coleo de objetos <code>TransferObject</code> UserTO.
*/
public static UserTO[] createTOs(Collection userLocals) {
List list = new ArrayList();
if (userLocals != null) {
Iterator iterator = userLocals.iterator();
while (iterator.hasNext()) {
list.add(createTO((UserLocal) iterator.next()));
}
}
UserTO[] returnArray = new UserTO[list.size()];
return (UserTO[]) list.toArray(returnArray);
}
}
349
BusinessDelegate : ProductDelegate
package com.novatec.book.project.delegate;
import java.util.Collection;
import com.novatec.book.project.ejb.ServiceLocator;
import com.novatec.book.project.ejb.ServiceLocatorException;
import
com.novatec.book.project.ejb.entity.ProductSessionFacadeHome;
import
com.novatec.book.project.ejb.entity.ProductSessionFacade;
import com.novatec.book.project.ejb.to.ProductTO;
import com.novatec.book.project.ejb.entity.impl.ProductPK;
/**
* Apresenta o <code>Business Delegate</code> para os servios oferecidos
* pelo <code>Facade</code> de usurio.
*/
public class ProductDelegate {
/**
* Referncia para a interface Home do Facade de produto.
*/
private ProductSessionFacadeHome productSessionFacadeHome;
/**
* Referncia para a interface Remote do Facade de produto.
*/
private ProductSessionFacade productSessionFacade;
/**
* Construtor customizado.
* @throws java.lang.Exception se ocorrer erro ao obter as referncias.
*/
public ProductDelegate() throws Exception {
initializeProductSessionFacadeHome();
productSessionFacade = productSessionFacadeHome.create();
}
350
/**
* Cria um produto dado o seu <code>TransferObject</code>.
* @param productTO <code>TransferObject</code> de produto.
* @throws Exception se ocorrer erro na criao do produto.
*/
public void createProduct(ProductTO productTO) throws Exception {
productSessionFacade.createProduct(productTO);
}
/**
* Remove o produto associado chave primria informada.
* @param productPK chave primria do produto.
* @throws Exception se ocorrer erro na remoo do produto.
*/
public void removeProduct(ProductPK productPK) throws Exception {
productSessionFacade.removeProduct(productPK);
}
/**
* Remove o produto cujo <code>TransferObject</code> representa.
* @param productTO <code>TransferObject</code> do produto.
* @throws Exception se ocorrer erro na remoo do produto.
*/
public void removeProduct(ProductTO productTO) throws Exception {
productSessionFacade.removeProduct(productTO);
}
/**
* Atualiza os dados do produto pelo <code>TransferObject</code>.
* @param productTO <code>TransferObject</code> do produto.
* @throws Exception se ocorrer erro na atualizao do produto.
*/
public void updateProduct(ProductTO productTO) throws Exception {
productSessionFacade.updateProduct(productTO);
}
/**
* Atualiza os dados dos produtos contidos na coleo de produtos.
* @param productDtos coleo de <code>TransferObject</code> de produto.
351
/**
* Localiza um produto dado a sua chave primria.
* @param productPK chave primria do produto.
* @return <code>TransferObject</code> do produto.
* @throws Exception se ocorrer erro ao localizar o produto.
*/
public ProductTO productFindByPrimaryKey(ProductPK productPK) throws
Exception {
return productSessionFacade.productFindByPrimaryKey(productPK);
}
/**
* Localiza a coleo de produtos.
* @return coleo de <code>TransferObject</code> do produto.
* @throws Exception se ocorrer erro ao localizar o produto.
*/
public Collection productFindAll() throws Exception {
return productSessionFacade.productFindAll();
}
/**
* Cria referncia para o Facade de produto.
* @throws java.lang.Exception se ocorrer erro ao localizar o componente.
*/
private void initializeProductSessionFacadeHome() throws Exception {
String FACADE_NAME =
ejb/SESSION/com/novatec/book/project/ejb/entity/
ProductSessionFacade;
Class FACADE_CLASS = com.novatec.book.project.ejb.entity.
ProductSessionFacadeHome.class;
if (productSessionFacadeHome == null) {
try {
ServiceLocator locator = ServiceLocator.getInstance();
productSessionFacadeHome = (ProductSessionFacadeHome) locator.
getEjbHome(FACADE_NAME, FACADE_CLASS);
352
BusinessDelegate : UserDelegate
package com.novatec.book.project.delegate;
import com.novatec.book.project.ejb.ServiceLocator;
import com.novatec.book.project.ejb.ServiceLocatorException;
import
com.novatec.book.project.ejb.entity.UserSessionFacadeHome;
import com.novatec.book.project.ejb.entity.UserSessionFacade;
import com.novatec.book.project.ejb.to.UserTO;
/**
* Apresenta o <code>Business Delegate</code> para os servios oferecidos
* pelo <code>Facade</code> de usurio.
*/
public class UserDelegate {
/**
* Referncia para a interface Home do Facade de usurio.
*/
private UserSessionFacadeHome userSessionFacadeHome;
/**
* Referncia para a interface Remote do Facade de usurio.
*/
private UserSessionFacade userSessionFacade;
/**
* Construtor customizado.
* @throws java.lang.Exception se ocorrer erro ao obter as referncias.
*/
public UserDelegate() throws Exception {
353
/**
* Cria um usurio dado o seu <code>TransferObject</code>.
* @param userTO <code>TransferObject</code> de usurio.
* @throws Exception se ocorrer erro na criao do usurio.
*/
public void createUser(UserTO userTO) throws Exception {
userSessionFacade.createUser(userTO);
}
/**
* Remove o usurio associado chave primria informada.
* @param cpf cpf do usurio.
* @throws Exception se ocorrer erro na remoo do usurio.
*/
public void removeUser(String cpf) throws Exception {
userSessionFacade.removeUser(cpf);
}
/**
* Remove o usurio cujo <code>TransferObject</code> representa.
* @param userTO <code>TransferObject</code> do usurio.
* @throws Exception se ocorrer erro na remoo do usurio.
*/
public void removeUser(UserTO userTO) throws Exception {
userSessionFacade.removeUser(userTO);
}
/**
* Atualiza os dados do usurio pelo <code>TransferObject</code>.
* @param userTO <code>TransferObject</code> do usurio.
* @throws Exception se ocorrer erro na atualizao do usurio.
*/
public void updateUser(UserTO userTO) throws Exception {
userSessionFacade.updateUser(userTO);
}
354
355
ServiceLocator
A seguir seguem o ServiceLocator da aplicao e sua exceo especfica.
ServiceLocator
package com.novatec.book.project.ejb;
import javax.rmi.PortableRemoteObject;
import javax.naming.NamingException;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.ejb.EJBHome;
import javax.ejb.EJBLocalHome;
/**
* Apresenta o <code>ServiceLocator</code> utilizado pelas classes para
* localizar EJBs.
*/
public class ServiceLocator {
/**
* Instncia nica do locator.
*/
private static ServiceLocator serviceLocator;
/**
* Instncia nica do contexto.
*/
private static Context context;
/**
* Construtor customizado.
* Impede que seja acessado externamente.
* @throws ServiceLocatorException se ocorrer erro ao obter o contexto
* inicial.
*/
protected ServiceLocator() throws ServiceLocatorException {
context = getInitialContext();
}
356
357
ServiceLocatorException
package com.novatec.book.project.ejb;
/**
* Exceo utilizada pelo <code>ServiceLocator</code>.
*/
public class ServiceLocatorException extends Exception {
358
/**
* Construtor customizado.
* @param message mensagem de erro.
*/
public ServiceLocatorException(String message) {
super(message);
}
}
Descritores Completos
Deployment Descriptor completo da Aplicao Exemplo : ejb-jar.xml
<?xml version=1.0" encoding=UTF-8"?>
<!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-beans>
<session>
<display-name>ProjectSupport</display-name>
<ejb-name>ProjectSupport</ejb-name>
<home>com.novatec.book.project.ejb.session.ProjectSupportHome</home>
<remote>com.novatec.book.project.ejb.session.ProjectSupport</remote>
<ejb-class>
com.novatec.book.project.ejb.session.ProjectSupportBean
</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
<session>
<display-name>SalesBasket</display-name>
<ejb-name>SalesBasket</ejb-name>
<home>com.novatec.book.project.ejb.session.SalesBasketHome</home>
<remote>com.novatec.book.project.ejb.session.SalesBasket</remote>
class>
<ejb-class>com.novatec.book.project.ejb.session.SalesBasketBean</ejb<session-type>Stateful</session-type>
<transaction-type>Container</transaction-type>
<ejb-ref>
<description />
359
<home>com.novatec.book.project.ejb.entity.ProductSessionFacadeHome</
<remote>com.novatec.book.project.ejb.entity.ProductSessionFacade</
<ejb-link>ProductSessionFacade</ejb-link>
</ejb-ref>
</session>
<session>
<display-name>SalesSupport</display-name>
<ejb-name>SalesSupport</ejb-name>
<home>com.novatec.book.project.ejb.session.SalesSupportHome</home>
<remote>com.novatec.book.project.ejb.session.SalesSupport</remote>
class>
<ejb-class>com.novatec.book.project.ejb.session.SalesSupportBean</ejb<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
<session>
<display-name>ProductSessionFacade</display-name>
<ejb-name>ProductSessionFacade</ejb-name>
<home>com.novatec.book.project.ejb.entity.ProductSessionFacadeHome</home>
<remote>com.novatec.book.project.ejb.entity.ProductSessionFacade</remote>
<ejb-class>
com.novatec.book.project.ejb.entity.ProductSessionFacadeBean
</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<ejb-local-ref>
<description />
<ejb-ref-name>ejb/product</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<local-home>
com.novatec.book.project.ejb.entity.impl.ProductLocalHome
</local-home>
<local>com.novatec.book.project.ejb.entity.impl.ProductLocal</local>
<ejb-link>Product</ejb-link>
</ejb-local-ref>
</session>
<session>
360
local-home>
<local>com.novatec.book.project.ejb.entity.impl.UserLocal</local>
<ejb-link>User</ejb-link>
</ejb-local-ref>
</session>
<entity>
<display-name>Product</display-name>
<ejb-name>Product</ejb-name>
local-home>
<local-home>com.novatec.book.project.ejb.entity.impl.ProductLocalHome</
<local>com.novatec.book.project.ejb.entity.impl.ProductLocal</local>
class>
<ejb-class>com.novatec.book.project.ejb.entity.impl.ProductBean</ejb<persistence-type>Container</persistence-type>
<prim-key-class>com.novatec.book.project.ejb.entity.impl.ProductPK</
prim-key-class>
<reentrant>False</reentrant>
<cmp-version>2.x</cmp-version>
<abstract-schema-name>Product</abstract-schema-name>
<cmp-field>
<field-name>name</field-name>
</cmp-field>
<cmp-field>
<field-name>description</field-name>
</cmp-field>
<cmp-field>
<field-name>price</field-name>
</cmp-field>
361
<local-home>com.novatec.book.project.ejb.entity.impl.UserLocalHome</
<local>com.novatec.book.project.ejb.entity.impl.UserLocal</local>
<ejb-class>com.novatec.book.project.ejb.entity.impl.UserBean</ejb-class>
<persistence-type>Bean</persistence-type>
<prim-key-class>java.lang.String</prim-key-class>
<reentrant>False</reentrant>
</entity>
<message-driven>
<display-name>UserNotifier</display-name>
<ejb-name>UserNotifier</ejb-name>
<ejb-class>com.novatec.book.project.ejb.mdb.UserNotifierBean</ejb-class>
<transaction-type>Container</transaction-type>
<message-driven-destination>
<destination-type>javax.jms.Queue</destination-type>
</message-driven-destination>
</message-driven>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>ProjectSupport</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
<container-transaction>
362
363
<jboss>
<enterprise-beans>
<session>
<ejb-name>ProjectSupport</ejb-name>
<jndi-name>ejb/SESSION/com/novatec/book/project/ejb/session/
ProjectSupport</jndi-name>
</session>
<session>
<ejb-name>SalesBasket</ejb-name>
<jndi-name>ejb/SESSION/com/novatec/book/project/ejb/session/
SalesBasket</jndi-name>
<ejb-ref>
<ejb-ref-name>ejb/productfacade</ejb-ref-name>
<jndi-name>
ejb/SESSION/com/novatec/book/project/ejb/entity/
ProductSessionFacade
</jndi-name>
</ejb-ref>
</session>
<session>
<ejb-name>SalesSupport</ejb-name>
<jndi-name>ejb/SESSION/com/novatec/book/project/ejb/session/
SalesSupport</jndi-name>
</session>
<session>
<ejb-name>ProductSessionFacade</ejb-name>
364
365
366
Apndice A
Glossrio
ACID propriedades de segurana. Atomicity Consistency Isolation Durability.
ANT makefile opensource utilizado para compilar e empacotar aplicaes Java.
API Application Program Interface.
BMP Bean Managed Persistence. Estratgia de persistncia utilizada em EJB Entity
Bea, na qual o prprio bean, isto , o programador deve definir a forma de persistncia dos dados do objeto.
BMT Bean Managed Transaction. Transao gerenciada pelo bean.
CMP Container Managed Persistence. Estratgia de persistncia utilizada em EJB
Entity Bean, na qual o prprio container se encarrega de persistir e manter os dados
do objeto.
CMT Container Managed Transaction. Transao gerenciada pelo container.
EAR Enterprise Archive. Utilizado para empacotar aplicaes Java Enterprise.
EJB Enterprise JavaBean. Componente utilizado na arquitetura J2EE.
EJB-QL Enterprise JavaBean Query Language. O mesmo que EQL.
EQL Enterprise Query Language. Utilizado para realizar consultas para EJB Entity
Bean. Tambm conhecida como EJB-QL.
J2SDK Java 2 Software Development Kit.
J2SE Java 2 Standart Edition. API Java para aplicaes standalone.
J2EE Java 2 Enterprise Edition. API Java para aplicao Enterprise.
J2EE SDK J2EE Software Development Kit.
JAR Java Archive. Utilizado para empacotar aplicaes e classes Java standalone.
367
368
Apndice B
Bibliografia
BOOCH G., RUMBAUGH J. JACOBSON I., UML Guia do Referncia. Rio de Janeiro: Editora Campus, 2000.
BLOCH J. Effective Java Programming Language Guide. 1.ed.: Addisson-Wesley,
2002.
CRUPI J.; MALKS D.; ALUR D. Core J2EE Patterns: As melhores prticas e estratgias de design. 1.ed.:Rio de Janeiro: Editora Campus, 2002.
FOWLER M., SCOTT K. UML Essencial. 2.ed.: Porto Alegre: Bookman, 2000.
GAMMA, E.; HELM, R.; JOHNSON R.; VLISSIDES J. Padres de Projeto: Solues
Reutilizveis de Software Orientado a Objetos. Porto Alegre: Bookman, 2002.
HALL M. Core Servlets and Javaserver Pages 1.ed: Prentice Hall, 2001.
TANEMBAUM, A. S. Distributed Operating Systems, Prentice Hall, 1994.
369