realizado por: aníbal manuel e silva couto supervisor ...paf/proj/set2004/i980305 - trabalho...
TRANSCRIPT
Licenciatura em Engenharia Informática Ramo Computadores e Sistemas
Realizado por: Aníbal Manuel e Silva Couto
Supervisor: Engº Orlando Sousa
Porto, Outubro 2004
Licenciatura em Engenharia Informática Ramo Computadores e Sistemas
Realizado por: Aníbal Manuel e Silva Couto nº 980305
Supervisor: Engº Orlando Sousa
Porto, Outubro 2004
AGRADECIMENTOS
Venho por este meio agradecer a todos que me ajudar na realização deste
trabalho, mais particularmente ao meu supervisor (Engº Orlando Sousa), que sempre
deu-me muita força para que terminasse com este projecto, agradecer toda a sua
disponibilidade que sempre demonstrou em ajudar-me quer em dúvidas, quer em novas
coisas que achava que deveriam ser reforçadas neste relatório e para além disso pedir
desculpas pelos sucessivos atrasos na realização deste relatório, mas infelizmente foi
sempre devido a motivos quer de nível profissional ou de nível pessoal.
Por outro lado, quero agradecer a todos os famliliares, mais particularmente aos
meus pais, irmão e namorada por muito me “massacrarem” para que o projecto fosse
entregue devido ao facto de ser a única disciplina que me faltava para terminar a
licenciatura em Engenharian Informática.
I
RESUMO
Este relatório tem como objectivo a explicação de uma forma mais prática da
aplicação no desenvolvimento de aplicações J2EE.
O relatório é constituído pelas seguintes partes: Uma parte inicial que explica a
definição de J2EE, o seu modelo aplicacional, e a sua arquitectura. Seguidamente, são
explicados os containers e os componentes de J2EE da camada de Web e os de
aplicação. Nos componentes Web, vão ser focados os JSP´s e os Java Servlet´s,
explicando a sua definição, estrutura e exemplos práticos da sua utilização.
Relativamente aos componentes da camada de aplicação, vai ser focado os EJB´s, os
seus diferentes tipos, diferenças entre eles, casos práticos e quais as regras para escolher
um tipo de bean.
Depois de explicado a estrutura essencial do J2EE, partimos para um tema muito
importante nas aplicações hoje em dia que é a segurança, aqui vai ser focado o essencial
para construção de uma aplicação de J2EE segura, com exemplos práticos e definições
de os diferentes tipos de segurança. Seguidamente, o tema focado vai ser os outros
processamentos que devem ser salientados no lado do servidor como por exemplo:
JNDI, JavaMail, entre outros.
Para além disto, vou falar das minhas experiencias pessoais com J2EE, visto já
trabalhar com ferramentas que suportam desenvolvimento de aplicações J2EE
(Websphere).
No final da parte técnica deste relatório termino com o exemplo de alguns dos
servidores de J2EE “open-source” disponíveis.
II
SUMÁRIO
AGRADECIMENTOS __________________________________________________I RESUMO____________________________________________________________ II SUMÁRIO__________________________________________________________ III INDÍCE DE FIGURAS ________________________________________________ V ABREVIATURAS E SIGLAS__________________________________________ VI 1. - NOTA INTRODUTÓRIA ___________________________________________ 1 2. - J2EE ____________________________________________________________ 2 2.1 - O que é plataforma J2EE? _________________________________________ 2 2.2 - Vantagens do J2EE _______________________________________________ 3 2.1 – MODELO APLICACIONAL_______________________________________ 4 2.2 - ARQUITECTURA________________________________________________ 6 2.3 - CONTAINERS ___________________________________________________ 6 2.4 - COMPONENTES ________________________________________________ 7 2.4.1 - Componentes J2EE na Camada Web _______________________________ 8 2.4.1.1 - Servlets ______________________________________________________ 8 2.4.1.1.1 - Os meus problemas __________________________________________ 13 2.4.1.2 - Java Server Pages_____________________________________________ 13 2.4.1.2.1 - Os meus problemas __________________________________________ 27 2.4.2 - Componentes de Integração ______________________________________ 28 2.4.3 - Componentes de J2EE na Camada de Aplicação_____________________ 29 2.4.3.1 - EJB’s _______________________________________________________ 29 2.4.3.1.1 - EJB´S – Arquitectura ________________________________________ 29 2.4.3.1.2 - EJB´S – Detalhes sobre o Modelo EJB __________________________ 31 2.4.3.1.3 – Entity Beans _______________________________________________ 37 2.4.3.1.3.1 - Entity Bean - Bean Managed Persistence ______________________ 38 2.4.3.1.3.2 - Entity Bean Bean Container-Managed-Persistence ______________ 42 2.4.3.1.4 – Session Beans ______________________________________________ 53 2.4.3.1.4.1 - Diferenças entre os dois tipos de Session Beans _________________ 54 2.4.3.1.4.2 - Session Beans sem estado____________________________________ 55 2.4.3.1.4.3 - Session Beans com estado ___________________________________ 59 2.4.3.1.5 – Message-Driven Beans _______________________________________ 63 2.4.3.1.6 – Regras para escolher qual o tipo de Bean _______________________ 71 3 - Segurança J2EE __________________________________________________ 73 3.1 - JAAS __________________________________________________________ 73 3.1.1 - Autenticação __________________________________________________ 74 3.1.2 - Autorização ___________________________________________________ 75 3.1.2.1 - Security Roles ________________________________________________ 76 3.1.2.2 - Autorização Programática _____________________________________ 76 3.1.2.3 - Autorização Declarativa _______________________________________ 77 3.1.3 - Propagação de Segurança________________________________________ 79
III
Trabalho de J2EE
Aníbal Manuel e Silva Couto
4 – OUTROS PROCESSAMENTOS SERVER SIDE ______________________ 85 4.1 - JAF E JAVAMAIL ______________________________________________ 85 4.2 - JNDI __________________________________________________________ 85 4.3 - JTA ___________________________________________________________ 86 5 – Servidores J2EE __________________________________________________ 94 5.1 - JBoss __________________________________________________________ 94 5.2 - Jakarta Tomcat _________________________________________________ 95 5.3. – Websphere_____________________________________________________ 97 5.3.1. - Websphere Studio Application Developer __________________________ 97 5.3.2 – Websphere Application Server ___________________________________ 99 6. - CONCLUSÃO __________________________________________________ 100 REFERÊNCIAS BIBLIOGRÁFICAS __________________________________ 101
Pág.IV
INDÍCE DE FIGURAS
Figura 1: Arquitetura da plataforma J2EE________________________________ 5 Figura 2 – Esquema de Classes de Servlets ________________________________ 9 Figura 3 - Ciclo de Vida dos Servlets ____________________________________ 10 Figura 4 – Exemplo Servlet Hello World _________________________________ 12 Figura 5 – Passos de um JSP ___________________________________________ 15 Figura 6 – Resultado de JSP Expressions ________________________________ 20 Figura 7 – Resultado de Declarações JSP ________________________________ 24 Figura 8 – Arquitectura Básica de um EJB ______________________________ 30 Figura 8 – Detalhes do Modelo EJB ____________________________________ 31 Figura 9 – Esquema funcionamento EJB ________________________________ 33 Figura 9 – Vários Tipos de EJB´s e Interfaces Associados___________________ 34 Figura 10 – Funcionamento do desenvolvimento de um EJB ________________ 34 Figura 11 – Diagrama de Classes UML do Entity Bean _____________________ 37 Figura 12 – Estado Entity Bean durante seu processo ______________________ 38 Figura 13 – Ciclo de vida de um Entity Bean BMP. ________________________ 41 Figura 14 – Ciclo de Vida de um Entity Bean CMP ________________________ 44 Figura 15 – Relacionamento Bidirecional do Entity Bean CMP. _____________ 46 Figura 16 – Relacionamentoto Unidireccional Entity Bean CMP. ____________ 48 Figura 17 – Session Beans com estado e sem estado.________________________ 54 Figura 18 – Funcionamento do Session Bean sem estado____________________ 56 Figura 19 – Funcionamento do Session Bean com estado____________________ 61 Figura 20 – Diagrama de Classes UML do Message-Driven Beans. ___________ 63 Figura 21 – Ciclo de Vida de um Message Driven Bean _____________________ 65 Figura 22 – MOM____________________________________________________ 66 Figura 23 – Point-to-Point (Queue). _____________________________________ 68 Figura 24 – Publish/Subscribe (Topic). __________________________________ 69 Figura 25 – JNDI. ____________________________________________________ 86 Figura 26 – Papeis. ___________________________________________________ 89 Figura 27 – Esquema applicação J2EE. __________________________________ 93
V
ABREVIATURAS E SIGLAS
JDBC – Java Database Connectivity
J2EE – Java 2 Enterprise Edition
XML – EXtensible Markup Language
JSP – Java Server Pages
ERP - Enterprise Resource Planning Software
SAP - Systems, Applications, Products in Data Processing
EJB – Enterprise Java Beans
HTML - HyperText Markup Language
JVM – Java Virtual Machine
VI
Trabalho de J2EE
Aníbal Manuel e Silva Couto
1. - NOTA INTRODUTÓRIA
Este trabalho foi realizado no âmbito do Curso de Licenciatura em Engenharia
Informática no Ramo de Computadores e Sistemas no Instituto Superior de Engenharia do
Porto no ano lectivo de 2003/2004.
O desenvolvimento deste trabalho, foi escolhido por meu critério. A escolha do J2EE
para o centro do meu estudo não foi uma escolha aleatória, prendeu-se com o facto, de
querer conhecer muito bem o J2EE, também devido a ter trabalhado com várias vertentes
do J2EE, como JSP´s e Servlets e com o facto de este tema nunca ser abordado durante os
meus 5 anos de curso de Engenharia Informática.
A aplicação deste trabalho tem como seguintes objectivos:
• Aplicar conhecimentos teóricos e teórico práticos;
• Demonstração de exemplos práticos para cada parte teórica exposta;
• Ampliação de conhecimentos de J2EE.
Este trabalho encontra-se divido em várias partes: Por uma parte inicial que foca todas
as partes essenciais do J2EE (arquitectura, modelo, Componentes Web, Componentes de
Aplicação, containers, entre outros), seguindo-se de um tema muito importante hoje em dia
que é a segurança, e terminando com alguns exemplos de servidores de J2EE.
Para a realização deste trabalho contribuíram as orientações do supervisor, alguns
colegas de trabalho, consultas e análise documental e as várias pesquisas bibliográficas.
Concluindo, espero atingir todos os objectivos a que me propus inicialmente, que este
trabalho ajude a compreender melhor esta metodologia. Espero, essencialmente contribuir
para a aquisição de algum conhecimento para quem efectuar a leitura deste trabalho.
Pág.1
Trabalho de J2EE
Aníbal Manuel e Silva Couto
2. - J2EE
As empresas de hoje em dia ganham vantagem competitiva desenvolvendo e
distribuindo software específico que forneça serviços de negócio únicos. Quer sejam
aplicações internas destinadas à produtividade dos funcionários da empresa, ou aplicações
internet para clientes especializados, ou serviços de venda, o rápido desenvolvimento e
distribuição são a chave do sucesso.
Portabilidade e escalabilidade são também factores importantes na viabilidade de uma
solução a longo prazo.
As aplicações multi-camada são difíceis de arquitectar. Estas requerem que uma
variedade de aptidões, recursos, dados e código sejam trazidos para a arquitectura. Num
ambiente heterogéneo de hoje, aplicações empresariais têm de integrar serviços de uma
variedade de empresas vendedoras com um conjunto de modelos de aplicações e outros
padrões. A experiência da indústria mostra que a integração destes recursos pode tomar até
50% do tempo de desenvolvimento de uma aplicação.
Como um padrão único que pode existir em cima de uma grande variedade de sistemas
empresariais – gestão de sistemas de bases de dados, monitorização de transacções e
directórios de serviços – o J2EE quebra a barreira existente entre os sistemas empresariais
actuais. O padrão do J2EE esconde e inclui recursos existentes requeridos pelas aplicações
multi-camada com um modelo de aplicação unificado e baseado em componentes. Isto
possibilita a chegada da próxima geração de componentes, ferramentas, sistemas e
aplicações que preencham os requisitos estratégicos de uma empresa. Com simplicidade,
portabilidade, escalabilidade e integração de sistemas, o J2EE é a plataforma de escolha
para soluções empresariais.
2.1 - O que é plataforma J2EE?
A plataforma Java2 Enterprise Edition ou J2EE é um padrão para o desenvolvimento de
aplicações baseadas em arquitecturas multi-camada distribuídas, construídas utilizando
componentes de modelação. O padrão usa variadas tecnologias, como JDBC, ou CORBA,
e estende as suas funcionalidades com as tecnologias Enterprise JavaBeans (EJB´S),
JavaServlets API, JavaServer Pages e XML. Isto permite que a quem crie aplicações
Pág.2
Trabalho de J2EE
Aníbal Manuel e Silva Couto
empresariais que sejam portáveis entre plataformas e escaláveis, enquanto mantêm
compatibilidade entre tecnologias.
O J2EE estende a linguagem Java através de padrões simples e unificados para
aplicações distribuídas através de um modelo baseado em componentes, especificando
tanto a infra-estrutura para gerir as suas aplicações assim como a API´s para construí-las.
2.2 - Vantagens do J2EE
O J2EE, sendo um padrão de desenvolvimento muito eficaz nos dias de hoje,
apresenta algumas vantagens nas quais se realçam:
• Soluções rápidas;
• Liberdade de escolha;
• Conectividade simplificada;
• Independência do fornecedor;
• Baixo custo de acesso e propriedade;
• Viabiliza o uso de software “open-source”.
Para alem das vantagens em cima descritas penso que também existe necessidade de
salientar alguns factos que têm sido ultimamente referidos:
• Mais de 50% dos novos projetos de sistemas de informação iniciados nos
anos de 2002 e 2003 utilizaram o J2EE;
• Todas as empresas de TI da área “enterprise” têm linhas de produtos focadas
no desenvolvimento e gestão de aplicações J2EE;
• O SAP (líder do mercado ERP) está a ser rescrito como uma aplicação
J2EE.
• 80% dos projetos de sistemas J2EE “estouram” prazos e orçamentos em
pelo menos 50%.
Pág.3
Trabalho de J2EE
Aníbal Manuel e Silva Couto
2.1 – MODELO APLICACIONAL
Graças ao modelo aplicacional J2EE, talvez a coisa mais interessante sobre estas
aplicações é o que elas não fazem. Isto é, as várias complexidades inerentes a aplicações
empresariais – gestão de transacções, gestão do ciclo de vida, pooling de recursos, estão
integradas na plataforma e são fornecidos automaticamente a componentes suportados. A
A implementação de componentes e de aplicações são libertados para se poderem
concentrar na lógica de negócio e interfaces com o utilizador.
Outra vantagem do J2EE é que o modelo aplicacional encapsula as camadas de
funcionalidade em tipos específicos de componentes. A lógica de negócio é encapsulada
em componentes Enterprise JavaBeans (EJB). A interacção com clientes pode ser
apresentada através de HTML puro, applets Java, Java Servlets API, ou tecnologia
JavaServer Pages, ou através de aplicações Java convencionais. Os componentes
comunicam transparentemente utilizando vários padrões: HTML, XML, HTTP, SSL, RMI,
IIOP, entre outros.
Os componentes J2EE reutilizáveis permitem escolhas competitivas para empresas que
implementam este padrão e organizações de tecnologia. O J2EE permite-lhes que
construam aplicações a partir da combinação de componentes padronizados e
comercialmente disponíveis e os seus próprios componentes personalizados. Desde
componentes para aplicações de negócio a soluções verticais completas, é esperado que
uma variedade de componentes padronizados J2EE esteja disponível para utilização “off
the shelf”.
Isto significa que um portal de comércio electrónico poderia ser construído a partir de
uma combinação de componentes EJB “off the shelf” para os comportamentos de carrinho
de compras, componentes EJB especializados para os serviços prestados aos clientes,
desenhos completamente personalizados usando tecnologia JavaServer Pages que
proporcionam um ambiente totalmente único ao portal.
Esta aproximação significa menos tempo de desenvolvimento, melhor qualidade,
aplicações mais fáceis de manter e portabilidade através de uma variedade de plataformas
empresariais. Os benefícios em que isto se traduz são maior produtividade dos
programadores, melhor uso de recursos computacionais e maior retorno dos investimentos
em tecnologia.
Pág.4
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Como se pode verifica, o objectivo do J2EE é especificar uma plataforma com um
modelo de componentes e a infra-estrutura básica (segurança, transacções, acesso a bases
de dados, etc.) para o desenvolvimento de aplicações corporativas. O padrão J2EE da Sun
é composto por:
• A plataforma J2EE: Uma plataforma padrão para alocar aplicações J2EE,
especificada como um conjunto de APIs, especificações e políticas de utilização
das APIs. A arquitetura desta plataforma está apresentada na figura 1.
• O J2EE Compatibility Test Suíte: Um conjunto de testes de compatibilidade
para garantir que um produto J2EE é compatível com o padrão da plataforma
J2EE.
• A implementação de referência J2EE: Uma implementação de referência
para demonstrar as capacidades do J2EE e para prover uma definição operacional
da plataforma J2EE.
• O modelo de programação de aplicações J2EE: Um modelo de programação
padronizado para o desenvolvimento de aplicações multi-camadas.
Figura 1: Arquitetura da plataforma J2EE
A plataforma J2EE foi projectada para disponibilizar o suporte, dos lados do cliente e
também do servidor, ao desenvolvimento de serviços Web, além de suporte a aplicações
empresariais multi-camadas.
Pág.5
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Interacção flexível com o utilizador do J2EE
O J2EE proporciona várias escolhas ao nível da interface gráfica através da intranet de
uma empresa ou através da internet. Os clientes podem estar a utilizar vários computadores
de secretária, portáteis, PDAs, telemóveis, ou outros dispositivos.
As interfaces que corram puramente no lado cliente podem utilizar padrões como
HTML ou applets Java. O suporte para HTML simples significa protótipos mais rápidos, e
suporte para uma variedade muito alargada de clientes. Adicionalmente, o J2EE suporta o
descarregamento automático do plugin Java para adicionar suporte onde este falha. O J2EE
também suporta aplicações cliente escritas em Java convencional. Para a distribuição de
conteúdo dinâmico no lado do servidor, o J2EE suporta tanto a JavaServlets API bem
como a tecnologia JavaServer Pages (JSP). A JavaServlets API possibilita a
implementação rápida de comportamentos no lado do servidor que usem todas as
potencialidades da API Java. A tecnologia JavaServer Pages combina a ubiquidade do
HTML com o poder do scripting no lado do servidor na linguagem de programação Java.
A especificação JSP 1.0 suporta templates estáticos, geração dinâmica de HTML, e
etiquetas (tags) personalizadas.
2.2 - ARQUITECTURA
A arquitectura J2EE tem os três componentes a seguir descritos:
• Componentes – Clientes de Aplicação, Applets, componentes Web,
componentes de negócio.
• Containers – Que tratam da gestão do ciclo de vida dos componentes, que
tratam do suporte “runtime” para componentes.
• Conectores – Contrato entre Containers e Sistemas de Informação e uma
empresa.
2.3 - CONTAINERS
Para compreender completamente a figura 1, é importante explicar os seus elementos
mais externos, ou seja, explicar que toda aplicação Java executa sob um certo ambiente, o
qual se convencionou chamar de container. Por enquanto, imagine-se um container como
Pág.6
Trabalho de J2EE
Aníbal Manuel e Silva Couto
uma JVM, um Class Loader (capaz de procurar classes ao sistema ou na rede e agregá-lo
ao ambiente) e, muito importante, se ele está a ser executado sob a forma de um plugin de
um outro programa. Quando se executa uma aplicação directamente na linha de comandos,
o container liga-se apenas ao sistema operativo nativo (Application Container) e apenas
com esse interage.
Uma applet é um código Java que é trazido da rede e executa dentro de uma página.
Portanto, quando uma applet é executada, o JVM (Java Virtual Machine) funciona como
um plugin da web browser, e para tanto, existe um conjunto de regras que permite ao
browser interagir com a JVM para executar código Java dentro de seu ambiente. Aqui
temos o browser como o Container (Applet Container).
Uma outra possibilidade é um Web Server actuar como Java Container. Isso ocorre para
os Servlets, que são como programas CGI escritos em Java, cujo objectivo é produzir
código HTML para envio ao cliente (web browser), e que para funcionarem devem seguir
determinados padrões que os permite serem activados pelo Web Server. Ou seja, a JVM
funciona como um acesso do web Server, que nesse caso é o seu container (Web
Container).
Observe-se que servlets e JSPs podem ser executados sem um "J2EE server" completo.
Podem executar num servidor Web com suporte especial sem ter suporte a EJB. Por
exemplo: Apache Tomcat, Websphere, JBoss.
Portanto, na figura 1, onde se vê "J2EE Server", podemos ter, na realidade, máquinas
diferentes.
2.4 - COMPONENTES
As aplicações de J2EE são compostas de componentes. Uma definição possível de
componente, é que um componente é uma unidade auto contida de software que pode ser
composta numa aplicação em tempo de design (sem compilação). Neste caso, os
componentes de J2EE, são escritos em linguagem Java.
Pág.7
Trabalho de J2EE
Aníbal Manuel e Silva Couto
2.4.1 - Componentes J2EE na Camada Web
Nestes componentes da camada Web podemos incluir vários módulos, que são os
seguintes e que depois os mais importantes serão descritos com maior pormenor:
• Páginas de HTML/XML estáticas;
• Servlets – Que se tratam de programas em Java que rodam no servidor Web
e que processam pedidos gerando respostas dinâmicas;
• Java Server pages (JSP) - Templates HTML mais fáceis de criar, mas que
contêm "scriplets" (partes de código em Java) para a geração de conteúdo
dinâmico - São convertidas em servlets quando acedidas pela primeira vez;
• JavaBeans – Componentes tradicionais em Java que podem ser usados em
servlets e JSPs;
2.4.1.1 - Servlets
Os servlets são programas escritos em Java que recebem pedidos e geram respostas para
um cliente normalmente utilizando HTTP. Os servlets podem ser comparados aos Applets
na medida em que os servlets estão para os servidores Web assim como os Applets estão
para os Browsers. Os servlets podem ser usados para estender qualquer tipo de aplicação
do modelo pedido-resposta.
A linguagem Java tem as seguintes características:
- Independência de plataforma, ou seja, pode rodar em diferentes plataformas sem
precisar de recompilar ou reescrever código.
- Performance, são eficientes, pois os serviços são carregados para memória uma única
vez e somente, após isso são instanciados. Em comparação com as CGI, os programas a
cada novo pedido uma nova instancia era carregada em memória.
O Java para além disso, também tem as suas vantagens que passo a referir:
• Acesso a base de dados via JDBC;
• Escalabilidade;
• Robustez, na medida em que tem segurança e tolerância a falhas;
• Orientado a Objectos, permite integração com Objectos Distribuídos
(CORBA/RMI);
Pág.8
Trabalho de J2EE
Aníbal Manuel e Silva Couto
A arquitectura dos servlets, utiliza o protocolo HTTP para processar os pedidos.
Relativamente há API do Servlet é definida em dois pacotes o:
• javax.servlet.http (Pedidos HTTP)
• javax.servlet (Genérica para ser adaptada para os demais protocolos baseado
em pedido resposta)
• Todos implementam a interface Servlet
• A maioria estende a classe httpServlet para manipulação de pedidos HTML
Figura 2 – Esquema de Classes de Servlets
Para tudo isto fazer algum sentido os Servlets possuem dois Objectos para interacção
com o HTTP, o ServletRequest (Pedido) e o Servlet Response (Resposta).
O ServletRequest é o que encapsula a comunicação do cliente para o servidor e permite
que o servidor pegue nas informações do cliente. Por sua vez, o ServletResponse é o que
permite que os Servlets enviem informações para o cliente e disponibilizam um Stream de
saída (ServçetOutputStream) que na maioria dos casos são comandos HTML.
Relativamente ao ciclo de vida dos Servlets, ele é controlado pelo container. Quando o
servidor recebe uma requisição ela é repassada para o container que a delega a um servlet.
Pág.9
Trabalho de J2EE
Aníbal Manuel e Silva Couto
O container, primeiro cria a classe em memória, depois cria uma instância da classe Servlet
e por fim, inicializa a instancia invocando o método init(). Depois de o servlet ter sido
inicializado cada pedido é executado num método service(), ou seja, o container, cria um
objecto de Pedido (ServletRequest) e de resposta (ServletResponse) e depois chama o
service passando os objectos como parâmetros. Após a resposta ter sido enviada o objecto
é destruído. Quando o container decidir remover o servlet de memória ele finaliza
chamando o método destroy().
Figura 3 - Ciclo de Vida dos Servlets
Servlets Genéricos
Os Servlets genéricos servem como componentes para serviços tipo pedido-resposta em
geral. Estes servlets não se limitam a serviços http, podem também ser usados para
estender, com componentes reutilizáveis um serviço existente. Normalmente, para correr
em serviços Web, deve-se usar Servlets HTTP.
Para escrever um servlet Genérico estende GenericServlet e implementar o seu método
service(), por exemplo:
import javax.servlet.*; import java.io.*; public class Generico extends GenericServlet { public void service ( ServletRequest request, ServletResponse response) throws IOException {
Pág.10
Trabalho de J2EE
Aníbal Manuel e Silva Couto
PrintWriter out = response.getWriter(); out.println("Hello, World!"); out.close(); } }
Para efectuar a inicialização de um servlet genérico deve-se sobrepor init(config) com
instruções que serão realizadas para inicializar um servlet. Por exemplo:
public void init(ServletConfig config) throws ServletException { String dirImagens = config.getInitParameter("imagens"); if (dirImagens == null) { throw new UnavailableException("Configuração incorreta!"); } }
Quando um servlet container decide remover um servlet da memória, ele chama o seu
método destroy(), em que este método serve para libertar recursos e fazer outras tarefas de
“limpeza”. Por exemplo:
public void destroy() { banco.close(); banco =null; }
O servlet normalmente só é destruído quando todos os seus métodos service()
terminaram (ou depois de um timeout).
Servlets que estendem da classe HttpServlet
A classe HttpServlet estende os métodos service para distinguir entre as solicitações
típicas recebidas de um navegador de Web Cliente. Os dois tipos mais comuns de
solicitação de http são o GET e POST. Uma solicitação GET, procura informações do
servidor e uma solicitação POST envia os dados para o servidor.
Cada chamada para o doGet ou doPost para um HttpServlet recebe um objecto que
implementa a interface HttpServletRequest. O servidor Web executa o servlet, cria um
objecto HttpServletRequest e passa para o método service do servlet, que por sua vez, o
passa para doGet ou doPost.
Pág.11
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Exemplo:
Figura 4 – Exemplo Servlet Hello World
Este exemplo, devolve uma página com a frase “HelloWorld”. Para se realizar a
servlet, a primeira coisa e criar uma classe que estende de HttpServlet.
Razões para se utilizar os Java Servlets:
• Eficiente: O código de inicialização do servlet é executado apenas a
primeira vez que ele é carregado pelo Servidor Web;
• Persistente: servlets podem manter estados entre as requisições de cliente
pois uma vez que ele é carregado, permanece e reside em memória enquanto
serve as pedidos dos clientes.
• Portável: como são desenvolvidos em Java, eles são portáveis, podendo ser
executados em diferentes sistemas operativos sem a necessidade de recodificação;
Pág.12
Trabalho de J2EE
Aníbal Manuel e Silva Couto
• Robustos: por se utilizarem todas as definições do JDK, os servlets são
aplicações robustas, pois podem tratar excepções de uma maneira muito eficiente,
como qualquer outra aplicação Java.
• Extensível: por serem orientados a objectos, os servlets podem utilizar
características como a herança e polimorfismo, permitindo a criação de objectos
mais apropriados às necessidades da aplicação.
• Seguros: servlets rodam no lado do servidor, herdando as características de
segurança providas pelo Servidor Web.
2.4.1.1.1 - Os meus problemas
Para a construção de um servlet existe a necessidade de saber programa em Java,
saber utilizar bastante bem as variaveis disponiveis (Request e Response). Para além disto,
dentro do Servlets, dentro do Request, temos acesso a várias variáveis que existe
necessidade de realçar, como por exemplo: a session, em que aqui conseguimos a aceder às
cookies da página, todos os atributos da página, entre outros.
A construção de um Java Servlet, não é muito complexa, apenas tem de ser
efectuada de uma forma simples, porque normalmente, um servlet serve para efectuar o
reencaminhamento para um determinado Jsp, para definir determinadas variáveis da
página, para escrever código HTML na página que vai ser carregada, apesar que não achar
que isto nunca deve ser efectuado, porque não se trata de um código aceitavel. È preferível
ter um jsp e fazer response.foward (jspname).
Um dos problemas dos Servlets é que existe necessidade de eles serem
configurados no servidor, para serem executados.
2.4.1.2 - Java Server Pages
Os Java Server Pages (Jsp), são uma tecnologia utilizada para servir o conteúdo
dinâmico para o utilizador, usando lógica e dados do lado do servidor. Os Java Server
Pages, juntamente com os Servlets e EJB podem ser usados para desenvolver aplicações
Web eficientes, escaláveis e seguras rapidamente.
Pág.13
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Os JSP´s são uma especificação da Sun Microsystems, sendo uma tecnologia para o
desenvolvimento de aplicações WEB, criando paginas chamadas dinamicamente,
semelhante ao Active Server Pages (ASP), tendo porém a vantagem da portabilidade da
plataforma que podem ser executados em outros sistemas alem dos da Microsoft e da
compilação das páginas permitindo que se processem muito mais rápido. Permite também
a que quem desenvolve os sites produzir aplicações que permitam acesso nativo às mais
diversas bases de dados graças a tecnologia JDBC (Java Database Connectivity), acesso a
ficheiros de texto, a obtenção de informações a partir de formulários, a obtenção de
informações sobre o visitante e sobre o servidor entre diversas coisas.
Para quem tem algum conhecimento de Java Servlets, verá que o JSP não oferecem
nada que não possa ser conseguido com os Servlets puros. O JSP, entretanto, oferece a
vantagem de ser facilmente codificado, facilitando assim a manutenção e elaboração de
uma página dinâmica. Para além desta vantagem, esta tecnologia permite separar a parte da
programação lógica, da programação visual, facilitando o desenvolvimento de aplicações
mais robustas, onde o programador e o designer podem trabalhar no mesmo projecto, mas
de uma forma independente. Por fim, outras características do JSP são o facto de produzir
conteúdos que podem ser reutilizados.
Ao nível do funcionamento do JSP, inicialmente o cliente faz uma requisição de uma
página JSP através de um Browser, esta página então será processada pelo servidor, se for
a primeira vez, esta página JSP é transformada num programa Java (conhecido como um
Servlet) este é compilado e gerando um bite-bite (conhecido por .class) e a partir deste é
gerada uma pagina HTML que é enviada de volta ao browser do cliente, a partir da
segunda vez que esta mesma pagina for acedida é verificado apenas se existiram mudanças
na pagina ou não, se não ocorreram o bytecode é chamado para gerar a página de HTML.
A figura a seguir representada ilustra todo o funcionamento dos JSP:
Pág.14
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Figura 5 – Passos de um JSP
Passos descritos da figura:
a. Todo o processo começa quando o cliente faz uma solicitação de uma
página de JSP, nesse momento, é enviado um objecto do tipo request para o
WebServer.
b. O Servidor Web localiza e envia a acção para a página de JSP.
c. E verificando as mudanças nesta, se for a primeira vez é criado um
programa Java Servlet.
d. O programa Java Servlet é compilado e transformado em um ByteCode
(.class)
e. Esta class pode ser auxiliado por pacotes .jar que carregam os JavaBeans.
f. Durante a montagem da página HTML podem ocorrer também solicitações
a Bases de dados.
g. A página HTML é gerada.
h. Invocações de TAG´s Personalizadas são transformadas neste momento em
TAG´s comuns para a geração final.
i. A página final padrão HTML é enviada de volta para o servidor.
j. Que a devolve para o cliente que fez a sua solicitação.
Elementos de Scripting do JSP
Podemos escrever o HTML convencional da maneira normal, utilizando ferramentas de
construção de páginas familiares. Então envolve o código para as partes dinâmicas em tags
especiais, muitas das quais começam com <% e terminam com %>. Por exemplo, aqui está
uma secção de uma página JSP que resulta em "Bom dia Maria da Silva" em uma URL
http://host/welcome.jsp?nome=Maria+da+Silva:
Pág.15
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Bom dia <%= request.getParameter("nome") %>
Separar HTML estático do conteúdo dinâmico fornece vários benefícios sobre os
servlets, e a abordagem usada em JSP oferece muitas vantagens sobre tecnologias
concorrentes tais como ASP, PHP ou ColdFusion. As vantagens resumem-se basicamente
a dois factos: - JSP é amplamente suportado e desta forma não prende o utilizador a um
sistema operacional ou servidor web particular e dá ao utilizador acesso total à tecnologia
Java e de servlets.
O processo de tornar acessível as páginas JSP na Web é muito mais simples do que com
os servlets. Assumindo que temos um servidor web que suporta JSP, dá-nos ao seu ficheiro
uma extensão .jsp e simplesmente coloca-o em qualquer lugar que normalmente
colocaríamos uma página Web: sem compilações, sem pacotes e sem ajustar configurações
adicionais. Contudo, embora o nosso ambiente pessoal não precise de configurações
especiais, o servidor ainda tem que ser ajustado para aceder a servlets e ficheiros de classe
do JSP e o compilador Java. Para detalhes, veja a documentação do seu servidor.
Como já referi, a página JSP é automaticamente convertida para um servlet
convencional, com o HTML estático sendo jogado no fluxo de saída associado com o
método service do servlet. Esta tradução é feita normalmente na primeira vez que a página
é requisitada. Para garantir que o primeiro utilizador real não tenha um atraso relativo
quando a página JSP for traduzida para um servlet e compilada, os clientes podem
requisitar a página, mesmo depois de colocá-la no servidor. Muitos servidores web também
permitem que se defina ligação de forma que uma URL que parece referenciar um ficheiro
HTML realmente aponta para um servlet ou para uma página JSP.
Ao lado do HTML regular, há três principais tipos de construções do JSP que se coloca
uma página: elementos de scripting, directivas e acções. Elementos de scripting permitem
que se especifique código Java que irá fazer parte do servlet resultante, directivas permitem
que se controle toda a estrutura do servlet, e acções permitem que se especifique
componentes existentes que devem ser usadas e que controlam o comportamento da
“engine” do JSP. Para simplificar os elementos de scripting, temos acesso a várias
variáveis pré-definidas, tal como o request no trecho de código mostrado abaixo.
Elementos de scripting são tratados neste capítulo.
Pág.16
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Elementos de scripting do JSP permitem que se insira código dentro do servlet que será
gerado de uma página JSP. Existem três formas:
1. Expressões da forma <%= expression %>, que são avaliadas e inseridas
dentro da saída do servlet.
2. Scriptlets da forma &1lt;% code %>, que são inseridos dentro do método
_jspService do servlet (chamado por service)
3. Declarações da forma <%! code %>, que são inseridas dentro do corpo da
classe do servlet, fora de qualquer método existente.
Texto Modelo
Em muitos casos, uma grande parte da sua página JSP consiste apenas de HTML estático,
conhecido como texto modelo. Em quase todos os casos, este HTML e semelhante com
HTML normal, segue todas as mesmas regras de sintaxe, e é simplesmente "passado" para
o cliente pelo servlet criado para manipular a página. Este código HTML pode ser criado
por quaisquer ferramentas que normalmente utilizamos para construir páginas Web (Front
Page, Home Site, Notepad, ...).
Existem duas pequenas excepções para a regra "texto modelo é simplesmente passado para
o cliente". Primeiro, se quisermos ter <% na saída, precisamos de colocar <\% no texto
modelo. Segundo, se quisermos que um comentário apareça na página JSP mas não
apareça no documento resultante, usa-se
<%-- JSP Comment --%>
Comentários HTML da forma
<!-- HTML Comment -->
São passados para o HTML resultante normalmente.
Expressões JSP
Uma expressão JSP é usada para inserir valores directamente na saída. Ela tem a
seguinte forma:
<%= Java Expression %>
A expressão é avaliada, convertida para uma string, e inserida na página. Esta avaliação
é efectuada em tempo de execução (quando a página é requisitada) e assim tem acesso total
Pág.17
Trabalho de J2EE
Aníbal Manuel e Silva Couto
há informações sobre a requisição. Por exemplo, a linha de código a seguir mostra a
data/hora em que a página foi requisitada:
Hora Actual: <%= new java.util.Date() %>
Variáveis Pré-Definidas
Para simplificar essas expressões, podemos usar algumas variáveis pré-definidas. Destas
variáveis, as mais importantes são:
• request, o HttpServletRequest dos servlets
• response, o HttpServletResponse
• session, o HttpSession associado com a requisição (a menos que
desabilitado com o atributo session da diretiva page)
• out, o PrintWriter usado para enviar a saída para o cliente
Aqui está um exemplo:
Endereço do Host: <%= request.getRemoteHost() %>
Utilização Expressões como Valores de Atributos
Como veremos depois, o JSP inclui vários elementos que utilizam sintaxe XML para
especificar vários parâmetros. Por exemplo, o exemplo a seguir passa "Mário" para o
método setFirstName do objecto ligado à variável author.
Muitos atributos requerem que o valor seja uma string fixa envolvida ou por aspas
simples ou por aspas duplas, como no exemplo acima. Alguns poucos atributos, entretanto,
permitem que se utilize uma expressão JSP que é executado e compilada durante a
requisição. O atributo value de jsp:setProperty é um destes, assim o código seguinte é
perfeitamente legal:
A Tabela 1 lista os atributos que permitem um valor em tempo de requisição como neste
exemplo.
Nome do Elemento Nome(s) do(s)
Pág.18
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Atributo(s)
jsp:setProperty name
value
jsp:include page
jsp:forward page
jsp:param value
Tabela 1: Atributos que permitem Expressões JSP
Exemplo
A listagem 1 dá um exemplo de página JSP; a Figura 1 mostra o resultado. Note que
incluímos tags Meta e um link para um style sheet na secção HEAD da página HTML. É
uma boa prática incluir esses elementos, mas há duas razões pelas quais eles são
frequentemente omitidos das páginas geradas por servlets normais. Primeiro, com servlets,
é tedioso gerar as instruções println necessárias. Com JSP, entretanto, o formato é mais
simples e podemos fazer uso das opções de reuso de código na sua ferramenta de
construção de HTML usual. Segundo, os servlets não podem usar a forma mais simples de
URLs relativas uma vez quer diretórios de servlets não são mapeados para URLs da
mesma maneira que são as URLs para páginas web normais. Páginas JSP, por outro lado,
são instaladas na hierarquia de páginas web normais no servidor, e URLs relativas são
resolvidas apropriadamente. Assim, as style sheets e páginas JSP podem ser mantidos
juntos no mesmo directório.
<HTML> <HEAD> <TITLE>JSP Expressions</TITLE> <META NAME="keywords" CONTENT="JSP,expressions,JavaServer,Pages,servlets"> <META NAME="description" CONTENT="Um rápido exemplod e expressões JSP."> <LINK REL=STYLESHEET HREF="JSP-Styles.css" TYPE="text/css"> </HEAD>
Pág.19
Trabalho de J2EE
Aníbal Manuel e Silva Couto
<BODY> <H2>JSP Expressions</H2> <UL> <LI>Hora Atual: <%= new java.util.Date() %> <LI>Seu hostname: <%= request.getRemoteHost() %> <LI>Seu ID de sessão: <%= session.getId() %> <LI>O parâmetro <CODE>testParam</CODE>: %= request.getParameter("testParam") %> </UL> </BODY> </HTML>
Figura 6 – Resultado de JSP Expressions
Scriptlets JSP
Se fizermos algo mais complexo do que inserir uma simples expressão, scriptlets JSP
permitem que se insira código arbitrário dentro do método _jspService do servlet (que é
chamado por service). Scriptlets tem a seguinte forma: <% Java Code %>
Pág.20
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Scriptlets tem acesso às mesmas variáveis definidas automaticamente que as expressões
(request, response, session, out, etc.). Assim, por exemplo, se quisermos exibir algo na
página resultante, usaríamos a variável out, como está apresentado: <% String queryData = request.getQueryString(); out.println("Dados GET anexados: " + queryData); %>
Neste exemplo particular, poderíamos ter obtido o mesmo efeito mais facilmente
utilizado a seguinte expressão JSP: a
Dados GET anexados: <%= request.getQueryString() %>
De um modo geral, as scriptlets podem efectuar várias tarefas que não podem ser feitas
apenas com expressões. Essas tarefas incluem ajustar cabeçalhos e códigos de estado para
a resposta, invocar efeitos como escrever no servidor um log ou actualizar uma base de
dados, ou executar código, ou outras construções complexas. Por exemplo, o seguinte
código especifica que a página corrente é enviada para o cliente no formato texto, e não
como HTML (que é o default). <% response.setContentType("text/plain"); %>
É importante notar que se pode ajustar cabeçalhos de resposta ou códigos de estado em
vários locais dentro de uma página JSP, mesmo que esta capacidade pareça violar a regra
que diz que este tipo de dado precisa ser especificado antes que qualquer conteúdo do
documento seja enviado para o cliente. Ajustar cabeçalhos e códigos de estado é permitido
porque os servlets que resultam das páginas JSP usam um tipo especial de PrintWriter que
armazena o documento antes de enviá-lo. Este buffer pode ser alterado.
Como um exemplo de código que é muito complexo para uma expressão JSP, o código
a seguir descrito apresenta uma página JSP que usa o parâmetro de requisição bgColor para
ajustar a cor de fundo da página.
<HTML> <HEAD> <TITLE>Teste de Cor</TITLE> </HEAD> <% String bgColor = request.getParameter("bgColor");
Pág.21
Trabalho de J2EE
Aníbal Manuel e Silva Couto
boolean hasExplicitColor; if (bgColor != null) { hasExplicitColor = true; } else { hasExplicitColor = false; bgColor = "WHITE"; } %> <BODY BGCOLOR="<%= bgColor %>"> <H2 ALIGN="CENTER">Teste de Cor</H2> <% if (hasExplicitColor) { out.println("O utilizador forneceu a cor de fundo " + bgColor + "."); } else { out.println("Utilizando a cor de fundo default WHITE. " + "Forneça o atributo request bgColor. Tente " + "uma cor padrão, um valor RRGGBB, ou veja " + "se seu browser suporta nomes de cor X11."); } %> </BODY> </HTML>
Usando Scriptlets com Estruturas Condicionais
Um outro uso de scriptlets é para incluir condicionalmente HTML padrão e construções
JSP. A chave para esta abordagem é o fato de que o código dentro de um scriptlet é
inserido dentro do método _jspService do servlet resultante exactamente como ele é
escrito, e qualquer HTML estático antes ou depois de um scriptlet é convertido para
instruções print. Isto significa que scriptlets não precisam conter instruções Java
completas, e blocos deixados abertos podem afectar o HTML estático ou o JSP fora dos
scriptlets. Por exemplo, considere-se o seguinte pedaço de código JSP, que contem HTML
e scriptlests misturados.
<% if (Math.random() < 0.5) { %> Have a <B>nice</B> day! <% } else { %> Have a <B>lousy</B> day! <% } %>
Pág.22
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Quando convertido para um servlet por uma engine JSP, este código resultará em algo
similar ao seguinte:
if (Math.random() < 0.5) { out.println("Tenha um <B>bom</B> dia!"); } else { out.println("Tenha um <B>mau</B> dia!"); }
Sintaxe Especial para Scriptlets
Há duas construções especiais que precisamos de conhecer. Primeiro, se usarmos os
caracteres “%>” dentro de um scriptlet, coloca-se “%\>”. Segundo, o equivalente XML de
<% código %> é
<jsp:scriptlet>
Code
</jsp:scriptlet>
Declarações JSP
Uma declaração JSP permite que se defina métodos ou campos que são inseridos dentro
do corpo principal da classe do servlet (fora do método _jspService que é chamado por
service para processar a requisição). Uma declaração tem a seguinte forma: <%! Java Code
%>
Já que declarações não geram saídas, elas geralmente são usadas em conjunto com
expressões JSP ou scriptlets. Por exemplo, aqui está um fragmento de JSP que imprime o
número de vezes que a página actual foi requisitada desde que o serviço foi iniciado (ou a
classe do servlet foi alterada e recarregada). Fazer múltiplas requisições ao mesmo servlet,
resulta apenas em múltiplas threads chamando o método service de uma única instância do
servlet. Elas não dão origem na criação de múltiplas instâncias do servlet excepto
possivelmente quando o servlet implementa SingleThreadModel. Assim, variáveis de
instância (campos) de um servlet são partilhados por múltiplos pedidos e accessCount,
logo abaixo, não tem que ser declarado como estático.
<%! private int accessCount = 0; %>
Acessos à página desde a inicialização do servidor:
Pág.23
Trabalho de J2EE
Aníbal Manuel e Silva Couto
<%= ++accessCount %>
A seguir é mostrado a página JSP completa; a figura a seguir mostra o resultado.
<HTML> <HEAD> <TITLE>JSP Declarations</TITLE> <META NAME="author" CONTENT="Marty Hall"> <META NAME="keywords" CONTENT="JSP,declarations,JavaServer,Pages,servlets"> <META NAME="description" CONTENT="A quick example of JSP declarations."> <LINK REL=STYLESHEET HREF="JSP-Styles.css" TYPE="text/css"> </HEAD> <BODY> <H1>JSP Declarations</H1> <%! private int accessCount = 0; %> <H2>Accesses to page since server reboot: <%= ++accessCount %></H2> </BODY> </HTML>
Figura 7 – Resultado de Declarações JSP
Sintaxe Especial da Declaração
Pág.24
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Como com os scriptlets, se quisermos usar os caracteres %>, coloca-se %\>. Finalmente,
note que o equivalente XML de é
<jsp:declaration>
Código
</jsp:declaration>
Variáveis Pré-Definidas
Para simplificar código em expressões JSP e scriptlets, possuímos oito variáveis
definidas automaticamente, algumas vezes chamadas de objectos implícitos. Como
declarações JSP resultam em código que aparece fora do método _jspService, essas
variáveis não estão acessíveis em declarações. As variáveis disponíveis são request,
response, out, session, application, config, pageContext e page.
Request - Esta variável é o HttpServletRequest associado com a requisição; dá ao
utilizador acesso aos parâmetros da requisição, o tipo da requisição (por exemplo,
GET ou POST) e os cabeçalhos HTTP recebidos (por exemplo, cookies).
Resumidamente, se o protocolo na requisição é outro que não o HTTP, a requisição
deve ser uma subclasse de ServletRequest diferente de HttpServletRequest.
Contudo, poucos servidores JSP suportam actualmente servlets não-HTTP.
Response - Esta variável é o HttpServletResponse associado com a resposta para o
cliente. Note-se que se o fluxo de saída for bufferizado normalmente, pode-se
ajustar códigos de estado do HTTP e cabeçalhos de resposta nas páginas JSP,
mesmo que a configuração dos cabeçalhos ou dos códigos de estado não sejam
permitidos em servlets quando alguma saída já tiver sido enviada para o cliente.
Out - Este é o PrintWriter usado para enviar saída para o cliente. Entretanto, para
tornar o objecto response útil, esta é a versão bufferizada de PrintWriter chamada
JspWriter. O utilizador pode ajustar o tamanho do buffer através do uso do atributo
buffer da directiva page (veja o atributo buffer). Note-se também que out é usado
quase exclusivamente em scriptlets, uma vez que expressões JSP são colocadas
automaticamente no fluxo de saída e assim raramente é preciso usar out
explicitamente.
Pág.25
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Session - Esta variável é o objecto HttpSession associado com a requisição. Lembre
que sessões são criadas automaticamente. Uma excepção é se o utilizador usar o
atributo session da directiva page para desligar as sessões. Neste caso, tentar
referenciar a variável session causará erros no momento em que a página JSP for
traduzida para um servlet.
Application - Esta variável é o ServletContext que, nos servlets, é obtido através do
método getServletConfig().getContext(). Servlets e páginas JSP podem armazenar
dados persistentes no objecto ServletContext em vez de usar variáveis de instância.
ServletContext tem os métodos setAttribute e getAttribute que permitem que se
armazene dados arbitrariamente associados com chaves específicas. A diferença
entre armazenar dados em variáveis de instâncias e armazená-las em ServletContext
é que o ServletContext é partilhado por todos os servlets na servlet engine (ou na
aplicação Web, se servidor suportar esta capacidade).
Config - Esta variável é o objecto ServletConfig para esta página.
PageContext - O JSP introduziu uma nova classe chamada PageContext para
disponibilizar um ponto centralizado para armazenar dados compartilhados. A
variável pageContext armazena o valor do objecto PageContext associado com a
página actual.
Page - Esta variável é simplesmente um sinónimo para “this” e não é muito útil na
linguagem de programação Java. Ele foi criado como um atalho para quando a
linguagem de scripting for diferente do Java.
A Diretiva Page do JSP
Um comando “diretive” do JSP afecta toda a estrutura do servlet que resulta da página
JSP. Os modelos a seguir mostram as duas possíveis formas para directivas. Aspas simples
podem ser substituídas por aspas duplas nos valores dos atributos, mas as aspas nunca
podem ser omitidas. Para obter aspas dentro do valor de um atributo, preceda-as com uma
barra invertida, usando \' para ' e \" para ".
<%@ directive attribute="value" %>
<%@ directive attribute1="value1"
Pág.26
Trabalho de J2EE
Aníbal Manuel e Silva Couto
attribute2="value2"
...
attributeN="valueN" %>
Em JSP, há três tipos de diretivas: page, include e taglib. A diretiva page permite que se
controle a estrutura do servlet importando classes, personalizando a superclasse do servlet,
ajustando o tipo do conteúdo, entre outras coisas. Uma directiva page pode ser colocada
em qualquer lugar dentro do documento; A segunda directiva, include, permite que se
insira um ficheiro dentro da classe do servlet na hora em que o ficheiro JSP for traduzido
para um servlet. Uma directiva include deve ser colocada no documento na posição em que
se quer que o ficheiro seja inserido; O JSP 1.1 introduz uma terceira directiva, taglib, que
pode ser usada para definir tags de marcação personalizadas;
A directiva page permite que se defina um ou mais dos seguintes atributos: import,
contentType, isThreadSafe, session, buffer, autoflush, extends, info, errorPage, isErrorPage
e language.
O Atributo import
O atributo import da directiva page permite que se especifique os pacotes que devem ser
importados pelo servlet para o qual a página JSP vai ser traduzida. Se não se especificar
explicitamente alguma classe para importar, o servlet importa java.lang.*, javax.servlet.*,
javax.servlet.jsp.*, javax.servlet.http.* e possivelmente algumas entradas especificadas
pelo servidor. Nunca se escreve código JSP que confie em classes especificadas pelo
servidor sendo importadas automaticamente. O uso do atributo import segue uma das
formas abaixo:
<%@ page import="package.class" %>
<%@ page import="package.class1,...,package.classN" %>
Por exemplo, a directiva a seguir significa que todas as classes no pacote java.util
devem estar disponíveis para uso sem explicitar os identificadores do pacote.
<%@ page import="java.util.*" %>
2.4.1.2.1 - Os meus problemas
A construção dos Java Server Pages, hoje em dia a sua construção não é muito
complexa, na medida em que cada vez existem mais editores em que ajudam à sua
Pág.27
Trabalho de J2EE
Aníbal Manuel e Silva Couto
construção. Os JSP´s tem uma vantagem muito forte que é o facto de permitirem incluir
directamente código Java que invoque um determinado acesso a bases de dados ou efectuar
outro código, mas por outro lado apresenta uma grande desvantagem que é o facto de ser
muito lento quando se corre a primeira vez. Para alem disso, caso se trate de uma aplicação
de grande escala torna-se um grande problema, pois então, para resolver este problema,
existe uma ferramenta, o jspbatchcompiler que permite efectuar a compilação dos JSP
todos à cabeça sem necessidade de serem corridos num browser ou outro local, e então
assim quando corremos a nossa aplicação, como os nossos JSP´s não vão ser compilados a
aplicação é bem mais rápida.
Existe necessidade de referir, que os JSP´s, mal exista uma modificação, nem que
seja dar um espaço dentro do JSP ele é comupilado novamente.
Desde quando trabalho com JSP´s, verifico que o JSP que apesar de ser lento é
muito eficaz, porque permite efectuar quase tudo: inserir código HTML, inserir código
DHTML, colocar código Java, entre outros.
2.4.2 - Componentes de Integração
Para componentes de integração temos os seguintes exemplos:
• JDBC (Java Database Connectivity): Mecanismo de acesso a dados via
Drivers JDBC ou pontes JDBC-ODBC;
• J2EE Connector: Fabricantes de sistemas tipo ERP, CRM, etc fornecem
drivers para utilização de funcionalides;
• JMS (Java Message Service): Comunicação Síncrona/Assíncrona através de
filas de mensagens. Facilita a comunicação com Mainframes;
• JNI (Java Native Interface): Possibilita a chamada de funções C/C++ a
partir do Java.
• Java IDL: Integração com componentes de outras linguagens através de
CORBA
Pág.28
Trabalho de J2EE
Aníbal Manuel e Silva Couto
2.4.3 - Componentes de J2EE na Camada de Aplicação
2.4.3.1 - EJB’s
Os Enterprise JavaBeans (EJB) são especificamente usados para resolver
problemas da camada de negócio. O padrão EJB é uma arquitetura de componentes que
podem ser implantados em num ambiente distribuído. É especificado um contracto entre os
componentes e os servidores de aplicação, de modo que um componente EJB possa ser
inserido em qualquer servidor de aplicações que suporte EJB. Os EJB também referidos
como enterprise beans, segundo a Sun (2002), são escaláveis, transacionais e multi-
utilizador.
As carateristicas desejáveis para um EJB são:
Redução da complexidade dos sistemas;
Maior reutilização dos componentes;
Facilidade de alteração de componentes;
Maior portabilidade e interoperabilidade;
Distribuição do processamento;
Centralização da forma de gerir os EJB´s e do control do mesmo.
2.4.3.1.1 - EJB´S – Arquitectura
Relativamente à arquitectura de um EJB, esta baseia-se num EJB Container que roda
num EJB Server e intercepta as chamadas ao Bean feitos pelos Clientes:
• O cliente nunca acede a um cliente diferente;
• Vários "Wire Protocols" podem ser usados pelos clientes
o Default: Remote Method Invocation (RMI)
Na camada de aplicação, temos vários serviços de suporte (ou Middleware), que são os
seguintes:
• Persistência de componentes e acesso a dados;
• Gestão de transacções distribuídas;
• Directory/Naming;
o Para encontrar serviços, componentes, etc.
• Segurança;
Pág.29
Trabalho de J2EE
Aníbal Manuel e Silva Couto
• Tolerância a falhas com Failover;
• Disponibilizar escalabilidade com truques para aumentar a performance;
o Balanço de carga;
o Resource pooling;
Exemplo: Conexões aos SGBDs;
o Multithreading;
• Monitoring, logging;
Normalmente, o EJB Container implementa os serviços automáticos, e em termos de
Design Pattern, é uma combinação de Proxy (controla o acesso ao Bean, ex. Segurança) e
adiciona uma funcionalidade ao Bean.
Relativamente ao EJB Server, este permite que vários containers executem e
implementa outros serviços, não transparentes como por exemplo: Naming, Segurança,
Serviços de Transacção, entre outros.
Na imagem a seguir é representado a arquitectura básica de um EJB.
Figura 8 – Arquitectura Básica de um EJB
Pág.30
Trabalho de J2EE
Aníbal Manuel e Silva Couto
2.4.3.1.2 - EJB´S – Detalhes sobre o Modelo EJB
O modelo EJB, é um modelo cujo o objectivo principal é ajudar os programadores a
desevolverem objectos para a camada de aplicação de uma forma simples e que possam ser
reutilizaveis de um forma simples e eficaz. A imagem a seguir representada o Modelo EJB
na sua totalidade, desde a parte de cliente até à base de dados.
Figura 8 – Detalhes do Modelo EJB
A interface Home e o Home Object têm definido os seguintes parâmetros:
• Interface de Factory para criar, localizar e remover instâncias de Beans;
• O Developer de Beans define esta interface;
• O Home Object implementa a interface Home;
• Implementa todos os serviços do ciclo de vida do Bean;
• Os Beans não são acedidos directamente;
• Apenas o container (Home Object e EJBObject) acede os Beans;
• O Home Object é automaticamente construído pelas ferramentas do
Container Provider a partir da interface especificada;
Pág.31
Trabalho de J2EE
Aníbal Manuel e Silva Couto
• O Home Object deve ser localizado pelo cliente através dos serviços de
Naming (JNDI) do EJB Server;
Por sua vez, a interface Remote e EJBObject tem as seguintes especificações:
• Especifica os Business Methods do Bean;
• O cliente acede o EJBObject e este interpõe a funcionalidade desejada,
persistência, transacção, segurança, gere o estado), e acede o Bean;
• Quem realmente implementa a interface Remote é o EJBObject, não o Bean;
• O EJBObject é gerado automaticamente pelas ferramentas do Container
Provider a partir da interface especificada;
O EJB (Enterprise Java Bean) é um modelo de componentes baseado na tecnologia de
objectos distribuídos. As arquitecturas de objectos distribuídos são compostas por três
partes:
• Servidor de Objectos (instância do objecto)
• Skeleton (“interface” do objecto no servidor”)
• Stub (“interface” do obejcto no cliente)
O Stub e Skeleton fazem com que o servidor de objectos (residente na camada de
negócios) pareça executar localmente na máquina do cliente.
Rede Camada de negócios
Cliente
2. comunica método invocado
1. cliente invoca um método
Skeleton
Servidor de objectos
Stub Loop de invocação remota de métodos
3. invoca no servidor 5. retorno do
resultado 4. comunica valor retornado
Pág.32
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Figura 9 – Esquema funcionamento EJB
A função do Stub é implementar a interface com os mesmos métodos do negócio do
objecto mas tais métodos não tem a lógica de negócio. Para além disto, implementa
operações de rede para encaminhar solicitações e receber respostas do Skeleton.
Por sua vez, o Skeleton analisa o pedido do Stub para descobrir qual o método a ser
invocado, invoca o método no servidor de objectos, e retorna o resultado para o Stub.
Os componentes de um Enterprise Java Bean, são os seguintes:
• São objectos Java;
• São escaláveis e reutilizáveis;
• Implementam a interface javax.ejb.EnterpriseBean
• Interagem com clientes remotos através de um objecto de comunicação, que
implementam a interface javax.Ejb.EJBObject;
• Possuem homes para serem utilizadas, que implementam a interface
javax.ejb.EJBHome;
• Podem ter home e objectos de comunicação optimizados para interagir com
clientes locais (javax.ejb.LocalHome e javax.ejb.LocalObject)
Normalmente, para o desenvolvimento de um EJB, é necessário definir os seguintes
items:
• Descritor de Deployment: Ficheiro de XML com informações sobre o bean
(tipo de persistência, atributos de transacção, etc.);
• Classe enterprise bean: implementa os métodos definidos nas classes;
• Interfaces: para acesso remoto é preciso ter as interfaces local e local home.
• Classes de ajuda: classes de lançamento de excepções e outras.
Nesta imagem são ilustrados todos os tipos de EJB´s, e as classes de Java que derivam:
Pág.33
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Figura 9 – Vários Tipos de EJB´s e Interfaces Associados
Como deve funcionar o desenvolvimento de EJB’s é ilustrado na figura seguinte:
Figura 10 – Funcionamento do desenvolvimento de um EJB
A figura acima ilustra o cliente a efectuar uma conexão a um servidor JNDI, onde
existem objectos de utilizadores, impressoras e computadores. Os objectos de utilizadores
poderiam, por exemplo, ter informações da password, último acesso, grupo etc. Vários
clientes na rede podem requisitar essas informações, por exemplo, as informações de
autenticações de utilizadores poderia estar contido na árvore JNDI.
Os EJB´s podem ser de três tipos, mas neste quadro a seguir representado vão ser
focados os dois essenciais, os Session Bean e os Entity Beans:
Pág.34
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Característica Session Bean Entity Bean
O que o Bean
representa
• Uma conversação eficaz com
um cliente
• Pode ser considerado uma
extensão do cliente que o criou
• Pode aceder a uma base de
dados usando JDBC ou
acedendo um Entity Bean
• Dão uma visão OO de um BD
• Representam dados numa base
de dados e os métodos que
agem sobre os dados
• Num SGBDR, cada Bean
poderia representar um registo
de uma tabela, por exemplo
Tempo de
vida
• Igual ao tempo de vida do
cliente. Existe somente durante
uma sessão cliente/servidor·
(curto espaço de tempo)
• Persiste tanto quanto os dados
de uma base de dados (longo
espaço de tempo)
Atributos
• Representam o estado da
conversação. Este estado é
mantido entre chamadas a
métodos mas não depois que a
sessão acaba
• Representam dados de uma
base de dados (colunas de uma
tabela, por exemplo)
Persistência·
(além da sessão)
• O Bean trata da sua própria
persistência
• É gerida automaticamente pelo
Container
Partilha • Um único Bean por cliente
• Acesso partilhado entre
clientes
• Container gere a
“concorrência”
Criação • No início de uma sessão
• Identificado usando uma chave
primária
• A criação de um novo Bean
insere dados numa base de
dados
Durabilidade • Não sobrevive a um crash de
servidor
• Sobrevive a um crash de
servidor
Transacção • Pode ser "transaction-aware", se • Transaccional
Pág.35
Trabalho de J2EE
Aníbal Manuel e Silva Couto
2.4.3.1.3 – Entity Beans
Os Entitys Beans, modelam objectos do mundo real, conceitos de negócio que podem
ser expressos por nomes (fabricante, peça,etc) e geralmente tem um estado persistente na
base de dados. Existem dois tipos de Entity Beans:
• Bean-Managed Persistence (BMP) – As chamadas são efectuadas para
carregar e guardar o estado do Bean e para estabelecer o relacionamento entre
Beans.
• Container-Managed Persistence (CMP) – É um container gere o estado do
Bean. Neste caso não é necessário qualquer código de SQL, todo o acesso é
efectuado pelo Container.
Na figura em baixo representado é ilustrado o diagrama de classes dos Entity Beans
num diagrama de UML.
Figura 11 – Diagrama de Classes UML do Entity Bean
Pág.37
Trabalho de J2EE
Aníbal Manuel e Silva Couto
A figura a seguir ilustra o estado de um Entity Bean durante o seu processo:
Figura 12 – Estado Entity Bean durante seu processo
Deve-se utilizar o EJB do tipo Entity Bean quando seu estado precisa ser persistente
como já disse anteriormente. Se a instância do EJB não estiver activa ou se o servidor de
aplicações for abaixo, pode-se recuperar o estado do mesmo, pois estará persistente na base
de dados. O que torna os Entity Beans diferentes dos Session Beans é que em primeiro
lugar o estado do Entity Bean é salvo através de um mecanismo de persistência, possuindo
também uma chave primária que o identifica.
2.4.3.1.3.1 - Entity Bean - Bean Managed Persistence
Utilizando esta estratégia, a codificação das chamadas de acesso à base de dados estão
na classe de negócio do EJB e são responsabilidade de quem desenvolve. Então, para os
métodos de busca (métodos utilizados para encontrar Entity Beans na base de dados) e para
os métodos de criação, remoção e actualização dos Entity Beans, devem-se codificar os
comandos responsáveis por realizar estas operações.
O Entity Bean BMP - Bean de Entidade com Persistência que é gerida pelo Bean -
oferece a quem desenvolve a flexibilidade de desenvolver as operações de persistência de
dados que em alguns casos, podem ser dificeis de implementar pelo container.
Esta estratégia demora mais tempo de desenvolvimento e alguns autores sugerem que se
utilize a estratégia de persistência CMP (ContainerManagedPersistence), que será vista a
seguir.
Pág.38
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Entity Bean BMP: EBBMPExampleBean. package com.book.example.ejb.entity; import javax.ejb.*; // Observe-se que no Entity Bean BMP, todo o código de criação (persistência do // objecto), remover, atualização etc. deve ser implementado nestes métodos, // 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; // Cria uma instância do objecto em memória e persiste os dados. // @param field1 campo a ser persistido. // @param field1 campo a ser persistido. // @return chave única que identifica o objecto persistido. pode ser null. // @throws CreateException exceção na criação do objecto. public java.lang.String ejbCreate(java.lang.String field1, java.lang.String field2) throws CreateException { // deve conter o código de persistência dos atributos do EJB. setField1(field1); setField2(field2); return null; } // Executado pelo container após a criação do EJB. // @param untitledField1 campo persistido. // @throws CreateException exceção na criação do objecto. public void ejbPostCreate(java.lang.String field1, java.lang.String field2) throws CreateException { } // Executado pelo container para remover o objecto persistido. // @throws RemoveException public void ejbRemove() throws RemoveException { // Deve conter o código de remoção do EJB no meio de persistência. } // Configura o valor do atributo field1. // @param field1 valor do atributo a ser configurado. public void setField1(java.lang.String field1) { this.field1 = field1; } // Configura o valor do atributo field2. // @param field2 valor do atributo a ser configurado. public void setField2(java.lang.String field2) {
Pág.39
Trabalho de J2EE
Aníbal Manuel e Silva Couto
this.field2 = field2; } // Obtém o valor do atributo field1. // @return valor do atributo field1. public java.lang.String getField1() { return field1; } // Obtém o valor do atributo field2. // @return valor do atributo field2. public java.lang.String getField2() { return field2; } // Implementação do método de selecção do objecto pela sua chave-primária. // @param field1 chave-primária do EJB. // @return chave primária do EJB. // @throws FinderException erro ao localizar o EJB. public java.lang.String ejbFindByPrimaryKey(java.lang.String field1) throws FinderException { return null; } // Utilizado para carregar o objecto persistente // e actualizar os dados de sua instância. public void ejbLoad() { } // Utilizado pelo container para actualizar os dados do objecto public void ejbStore() { } // Utilizado pelo container quando activa o objecto do pool. public void ejbActivate() { } // Utilizado pelo container quando devolve o objecto 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; } }
Pág.40
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Ciclo de vida de um Entity Bean Bean Managed Persistence
A figura a seguir representa o ciclo de vida dos Entity Beans BMP. Todos os métodos
são invocados pelo container para o bean. Para criar um novo Entity Bean é utilizado o
método create e para removê-lo é necessário executar o método remove. Pode-se carregar
um Entity Bean usando os métodos de busca do entity bean (finders, ejbFind methods).
Quando o bean é activado, ele carrega o dado do meio de persistência e quando é
desactivado, persiste os dados no meio de persistência.
Figura 13 – Ciclo de vida de um Entity Bean BMP.
Pág.41
Trabalho de J2EE
Aníbal Manuel e Silva Couto
2.4.3.1.3.2 - Entity Bean Bean Container-Managed-Persistence
Entity Beans CMP (Bean de Entidade com Persistência Gerida pelo Container)
oferecem mais rapidez e facilidade no desenvolvimento de objectos persistentes pois quem
desenvolve não precisa escrever os comandos para persistir e manipular os dados.
O container encarrega-se de realizar estas operações e retornar os valores desejados.
Ele faz isso para as operações triviais, como inserção do objecto, remoção, actualização
e selecção pela chave primária (create, remove, store e findByPrimaryKey
respectivamente).
Para as operações específicas de consulta a objectos com persistência, é necessário o
uso de uma linguagem de consulta conhecida como EQL (EJB Query Language). Os
detalhes desta linguagem serão vistos a seguir.
Estas operações devem ser definidas no ficheiro de deploy do componente (ejb-jar.xml)
utilizando-se de EQL para cada operação desejada. Neste ficheiro definem-se os campos
que serão persistidos e os relacionamentos entre Entity Beans.
Exemplo Entity Bean CMP: EBCMPExampleBean.
package com.book.example.ejb.entity; import javax.ejb.*; // Exemplo de Entity Bean utilizado para mantêr os dados em um meio persistente // e apresentar as operações sobre os atributos deste EJB. // No caso do uso de Entity Bean CMP, as operações de persistência são // implementadas pelo próprio container, sendo que o programador não precisa // se precocupar com estas operações triviais. // Para as operações específicas, como uma consulta com outros parâmetros por // exemplo, esta pode ser definida através de EQL no deployment descriptor do // Entity Bean CMP. abstract public class EBCMPExampleBean implements EntityBean { // Contexto do Entity Bean. private EntityContext entityContext; // Cria uma instância do objecto em memória e persiste seus dados. // @param field1 campo a ser persistido. // @param field1 campo a ser persistido. // @return chave única que identifica o objecto persistido. pode ser null. // @throws CreateException exceção na criação do objecto. public java.lang.String ejbCreate(java.lang.String field1, java.lang.String field2) throws CreateException {
Pág.42
Trabalho de J2EE
Aníbal Manuel e Silva Couto
setField1(field1); setField2(field2); return null; } // Executado pelo container após a criação do EJB. // @param untitledField1 campo persistido. // @throws CreateException exceção na criação do objecto. public void ejbPostCreate(java.lang.String field1, java.lang.String field2) throws CreateException { } // Executado pelo container para remover o objecto persistido. // @throws RemoveException public void ejbRemove() throws RemoveException { } // Configura o valor do atributo field1. // Observe que na especificação EJB2.0, estes métodos são implementados // pelo próprio 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 especificação EJB2.0, estes métodos são implementados // pelo próprio container. // @param field2 valor do atributo a ser configurado. public abstract void setField2(java.lang.String field2); // Obtém o valor do atributo field1. // @return valor do atributo field1. public abstract java.lang.String getField1(); // Obtém o valor do atributo field2. // @return valor do atributo field2. public abstract java.lang.String getField2(); // Utilizado para carregar o objecto persistente do meio de persistência // e atualizar os dados de sua instância. public void ejbLoad() { } // Utilizado pelo container para atualizar os dados do objecto // no meio de persistência. public void ejbStore() { } // Utilizado pelo container quando ativa o objecto do pool. public void ejbActivate() { } // Utilizado pelo container quando devolve o objecto ao pool. public void ejbPassivate() { } // Desconfigura o contexto do Entity Bean. public void unsetEntityContext() { this.entityContext = null; }
Pág.43
Trabalho de J2EE
Aníbal Manuel e Silva Couto
// Configura o contexto do Entity Bean. // @param entityContext contexto do Entity Bean. public void setEntityContext(EntityContext entityContext) { this.entityContext = entityContext; } }
Ciclo de Vida de um Entity Bean CMP
A Figura 14, representa o ciclo de vida do Entity Bean CMP. Ele é praticamente o
mesmo de um Entity Bean BMP, sendo que a única diferença é que pode-se chamar o
método ejbSelect(), tanto nos beans que estão no pool quanto nos que estão activos.
Figura 14 – Ciclo de Vida de um Entity Bean CMP
Pág.44
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Relacionamento de um Entity Bean CMP
Um entity bean pode-se relacionar com outro, como um relacionamento entre duas
tabelas de uma base de dados relacional. A implementação de um relacionamento para
entity beans BMP é feita por meio da codificação na classe de negócio do EJB, enquanto
para os entity beans CMP o container encarrega-se de oferecer os mecanismos de
relacionamento através dos elementos de relacionamento definidos no deployment
descriptor.
Relationship fields – Campos de relacionamento de um CMP
Um relationship field é equivalente a uma chave estrangeira numa tabela de uma base
de dados relacional e identifica um entity bean através do relacionamento.
Relacionamentos entre entity beans CMP
Existem quatro tipos de relacionamentos:
1 – 1: Cada instância de um entity bean pode-se relacionar com uma única instância de
outro entity bean. Por exemplo, um entity bean marido tem um relacionamento 1-1 com o
entity bean esposa, supondo que esta relação ocorra numa sociedade onde não é permitido
a poligamia.
1 – N: Uma instância de um entity bean pode-se relacionar com múltiplas instâncias de
outro entity bean. O entity bean gerente, por exemplo, tem um relacionamento 1-N com o
entity bean empregado, ou seja, um gerente pode ter vários empregados sob seu comando.
N – 1: Múltiplas instâncias de um entity bean podem-se relacionar com apenas uma
instância de outro entity bean. Este caso é o contrário do relacionamento 1-N, ou seja, o
entity bean empregado tem um relacionamento N-1 com o entity bean gerente.
N – M: Instâncias de entity beans podem-se relacionar com múltiplas instâncias de
outro entity bean. Por exemplo, numa universidade cada disciplina tem vários estudantes e
cada estudante pode estar matriculado em várias disciplinas, então o relacionamento entre
os entity beans disciplina e estudante é de N-M.
Pág.45
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Direccionamento em relacionamentos entre entity beans CMP
Um relacionamento entre entity beans pode ser bidirecional ou unidirecional. Num
relacionamento bidirecional cada entity bean tem um campo (relationship field) que
referencia outro entity bean. Através deste campo um entity bean pode aceder o objecto
relacionado. Num relacionamento unidirecional, apenas um entity bean tem o campo
referenciando outro entity bean. As consultas em EJBQL, que vai ser falado mais à frente,
podem navegar através destes relacionamentos. A direcção dos relacionamentos determina
quando a consulta pode navegar de um entity bean para outro.
Sendo um relacionamento bidirecional as consultas EJBQL podem navegar nas duas
direcções acedendo outros entity beans através dos campos de relacionamento. A tag cmr-
field-name no ficheiro ejbjarxml define o nome do campo do relacionamento e na classe
abstracta do entity CMP teremos os respectivos métodos abstractos get e set relacionados a
este campo. Os tipos que um método get como este retorna são o tipo da interface local do
objecto relacionado sendo um relacionamento X-1, caso o relacionamento seja X-N, o tipo
retornado pode ser ou java.util.Collection ou java.util.Set.
Sempre que tivermos campos de relacionamento no entity bean não devemos invocar o
seu método set no ejbCreate, ele deve ser invocado no método ejbPostCreate ou através
dos métodos set e get que estiverem disponíveis na interface local.
Exemplo relacionamento bidirecional:
Figura 15 – Relacionamento Bidirecional do Entity Bean CMP.
Neste caso podemos ver que os dois entity beans podem navegar e aceder às
informações sobre o entity bean relacionado, só para visualizar iremos agora mostrar como
ficariam as configurações no deployment descriptor.
Pág.46
Trabalho de J2EE
Aníbal Manuel e Silva Couto
<ejb-relation> <ejb-relation-name>esposa-marido</ejb-relation-name> <ejb-relationship-role> <description>esposa</description> <ejb-relationship-role-name>EsposaRelationshipRole</ejb-relationship-role-name> <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> <ejb-relationship-role-name>MaridoRelationshipRole</ejb-relationship-role-name> <multiplicity>One</multiplicity> <relationship-role-source> <description>marido</description> <ejb-name>Marido</ejb-name> </relationship-role-source> <cmr-field> <description>esposa</description> <cmr-field-name>esposa</cmr-field-name> </cmr-field> </ejb-relationship-role> </ejb-relation>
Na verdade não será necessário escrever todo este código xml para criarmos os
relacionamentos pois existem ferramentas que fazem isto por nós, mas nós devemos ter a
ideia de como funciona e o que é configurado neste ficheiro.
A tag cmr-field-name configura o nome do campo do ejb no qual serão criados os
métodos get e set que estarão disponíveis na interface local, caso configuramos a
multiplicidade 1-1, se fossemos configurar 1-N, por exemplo deveríamos trocar a tag
multiplicity para many e acrescentaríamos a tag cmr-field-type como o exemplo mostra a
seguir:
<cmr-field> <description>esposa</description> <cmr-field-name>esposa</cmr-field-name>
Pág.47
Trabalho de J2EE
Aníbal Manuel e Silva Couto
<cmr-field-type>java.util.Collection</cmr-field-type> </cmr-field>
Neste caso nós podemos escolher se o tipo retornado será java.util.Collection ou
java.util.Set.
Figura 16 – Relacionamento Unidireccional Entity Bean CMP.
Aqui temos um relacionamento unidirecional onde apenas a esposa pode encontrar o
marido, o marido não é capaz de recuperar informações das mulheres por meio do
relacionamento. Neste caso a tag cmr-field no deployment descriptor ejb-jar.xml não estará
configurada no lado em que definimos o relacionamento do lado do EJB marido.
<ejb-relation-name>esposa-marido</ejb-relation-name> <ejb-relationship-role> <description>esposa</description> <ejb-relationship-role-name>EsposaRelationshipRole</ejb-relationship-role-name> <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> <ejb-relationship-role-name>MaridoRelationshipRole</ejb-relationship-role-name> <multiplicity>One</multiplicity> <relationship-role-source> <description>marido</description>
Pág.48
Trabalho de J2EE
Aníbal Manuel e Silva Couto
<ejb-name>Marido</ejb-name> </relationship-role-source> </ejb-relationship-role> </ejb-relation>
EJB-QL
É a linguagem potável utilizada para construir os métodos de consulta dos EJB’s CMP
de acordo com a especificação 2.0. Esta linguagem não é utilizada para os EJB’s BMP,
pois os mesmos utilizam a API JDBC, ou outro mecanismo de persistência para acesso à
base de dados.
Devemos utilizar EQL para implementar os métodos de busca de Entity Beans CMP
que não sejam a partir de sua chave primária (findByPrimaryKey), pois este já é oferecido
automaticamente pelo container.
Um comando EJBQL contém três partes:
• Uma cláusula SELECT
• Uma cláusula FROM
• Uma cláusula opcional WHERE
A cláusula FROM define o domínio de uma consulta, indica qual parte de uma base de
dados que iremos consultar. No caso de uma base de dados relacional, a cláusula FROM
tipicamente restringe quais tabelas serão consultadas. Por exemplo:
SELECT OBJECT(o) FROM X AS o
Aqui estamos a declarar uma variável na cláusula FROM. Esta variável pode ser usada
posteriormente em outras cláusulas desta mesma consulta, neste caso estamos a reusar a
variável na cláusula SELECT.
Algumas vezes precisamos declarar variáveis na cláusula FROM que representa um
conjunto de valores:
SELECT OBJECT(a) FROM X AS o, IN (o.items) a
Pág.49
Trabalho de J2EE
Aníbal Manuel e Silva Couto
A frase X AS o declara a variável o que representa os entity beans X, e a frase
IN(o.items) a declara a variável a que representa uma colecção de itens do entity Bean X.
Então AS é usado quando a variável declarada representa um único valor e IN é usado
quando a variável representa uma colecção de valores.
A cláusula WHERE restringe o resultado da consulta, nós escolhemos os valores
desejados a partir das variáveis declaradas na cláusula FROM:
SELECT OBJECT(p) FROM Pessoa p WHERE p.nome = ?1
Esta consulta recupera todas as pessoas que possuem o atributo nome igual ao
parâmetro que será passado no método. Por exemplo, o método poderia ser construído da
seguinte forma:
findByNome(String nome)
Para utilizar collections na cláusula WHERE nós precisamos de declara-la
primeiramente na cláusula FROM:
SELECT OBJECT(a) FROM Pessoa AS p, IN(p.parentes a) WHERE a.filho.name = ‘Pedro’
Algumas vezes podemos declarar mais de uma variável que representa o mesmo entity
bean. Quando fazemos comparações isto é muito útil:
SELECT OBJECT(o1) FROM Pessoa o1, Pessoa o2 WHERE o1.idade > o2.idade AND o2.nome = ‘João’
A cláusula SELECT especifica o resultado retornado pela consulta. Por exemplo:
SELECT OBJECT(o) FROM Pessoa p, IN(o.parentes) a
Pág.50
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Na consulta são definidas duas variáveis p e a, a cláusula select determina qual deve ser
seleccionada. Neste exemplo a consulta retorna todos os produtos em todas as regras que
contem itens:
SELECT l.produtos FROM REGRA as r, IN(r.items) l
Podemos utilizar o ponto para aceder relacionamentos na cláusula SELECT. Este
código é interpretado para um SQLpadrão onde um JOIN é feito para recuperar os dados
desejados.
Perceba-se que neste exemplo não utilizamos a notação Object(), ele é apenas utilizado
quando se trata de uma variável simples que não faz uso do ponto para aceder a
informações por meio dos relacionamentos entre entity beans. Outra informação
importante é que a cláusula where não trabalha com collections, apenas aceita variáveis
simples, ou seja:
SELECT r.items FROM Regra AS r Esta query não está correta, a forma correta é: SELECT Object(a) FROM Regra AS r, IN(r.items) a
Para filtrar as informações, ou seja, não recuperar informações repetidas é utilizado o
filtro DISTINCT:
SELECT DISTINCT l.produtos FROM REGRA AS r, IN(r.items)
Podemos também fazer que seu método de busca retorne um java.util.Set que não
permite que valores repetidos sejam inseridos.
Agora a seguir temos um exemplo de como um método é definido no ficheiro ejb-jar-
xml pode ser acedido por meio das interfaces Home e/ou localHome do EJB. Na interface
o método estaria assim:
public java.util.Collection findByNome(String nome) throws FinderException,
Pág.51
Trabalho de J2EE
Aníbal Manuel e Silva Couto
RemoteException ;
Este método vai retornar todas as pessoas que tem o nome passado como parâmetro. No
ficheiro 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> . . .
Pág.52
Trabalho de J2EE
Aníbal Manuel e Silva Couto
2.4.3.1.4 – Session Beans
Os Session Beans são uma extensão da aplicação do cliente, responsável pela
administração de tarefas e processos. Executa uma tarefa para o cliente. Modelam
interacções, mas não tem um estado persistente. Um session bean representa um cliente no
servidor J2EE: para se aceder a uma aplicação no servidor, o cliente invoca os métodos de
um session bean. Similar a uma sessão interactiva: tem apenas um cliente, não é persistente
e termina quando o cliente encerra a interacção. Há dois tipos de Session Beans: Stateful
Session Beans (session beans com estado); Stateless Session Beans (session beans sem
estado).
Nos Session Beans com estado (Stateful Session Bean), este estado é igual aos valores
das variáveis de instância, que representam o estado de uma única sessão cliente-bean
(chamado estado conversacional, pois o cliente interage com o bean) o estado do bean
contém dados de um cliente específico. O estado existe durante a duração da sessão
cliente-bean, o container EJB pode gravá-lo em memória secundária.
Os Session Beans sem estado (Stateless Session Bean) têm as seguintes características:
• Não mantém um estado conversacional para um cliente em particular,
durante a invocação de um método;
• As variáveis da instância podem conter um estado, que é descartado quando
o método termina;
• Pode suportar diversos clientes (um de cada vez): o container EJB pode
atribui-lo a qualquer cliente;
• Melhor escalabilidade e performance que os session beans com estado;
• Nunca podem ser gravados em memória secundária;
Pág.53
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Figura 17 – Session Beans com estado e sem estado.
2.4.3.1.4.1 - Diferenças entre os dois tipos de Session Beans
Característica Stateful Session
Bean Stateless Session Bean
Gerência de estado
• È gerido
automaticamente pelo
Container
(Activation, Passivation)
• Não há estado a ser gerido
• Bean pode sair da memória sem salvar
qualquer coisa (não há "Passivation")
• Beans podem ser alocados de um "pool"
Responsabilidades
• Estado
conversacional pode ser
mantido no Bean
• O cliente tem que manter qualquer estado
necessário
Performance • Mais pesado • Extremamente “leve”
Pág.54
Trabalho de J2EE
Aníbal Manuel e Silva Couto
2.4.3.1.4.2 - Session Beans sem estado
No exemplo que a seguir vai ser apresentado, o objectivo é efectuar uma aplicação de
conversão de moedas. A conversão será efectuada por um Session Bean sem estado, já que
apenas precisamos fazer um processamento simples de transformação de números.
Em primeiro lugar, vamos ter uma classe, Converter.java em que aqui vão ser
especificados os “business methods” do Bean.
import javax.ejb.EJBObject; import java.rmi.RemoteException; import java.math.*; public interface Converter extends EJBObject { public BigDecimal dollarToYen(BigDecimal dollars) throws RemoteException; public BigDecimal yenToEuro(BigDecimal yen) throws RemoteException; }
Seguidamente, teremos a interface home onde serão definidos métodos usados pelo
cliente para criar, remover ou localizar um EJB. Esta home ConverterHome.java apenas
conterá um único método de criação que retorna um objecto do tipo da interface remota.
import java.io.Serializable; import java.rmi.RemoteException; import javax.ejb.CreateException; import javax.ejb.EJBHome; public interface ConverterHome extends EJBHome { Converter create() throws RemoteException, CreateException; }
Após ter a home criada, passamos para a sua implementação. Nesta classe
ConverterBean.java, todos os métodos prometidos pela classe remota devem ser
implementados.
import java.rmi.RemoteException; import javax.ejb.SessionBean; import javax.ejb.SessionContext; import java.math.*; public class ConverterBean implements SessionBean { BigDecimal yenRate = new BigDecimal("121.6000"); BigDecimal euroRate = new BigDecimal("0.0077"); public BigDecimal dollarToYen(BigDecimal dollars) { BigDecimal result = dollars.multiply(yenRate);
Pág.55
Trabalho de J2EE
Aníbal Manuel e Silva Couto
return result.setScale(2,BigDecimal.ROUND_UP); } public BigDecimal yenToEuro(BigDecimal yen) { BigDecimal result = yen.multiply(euroRate); return result.setScale(2,BigDecimal.ROUND_UP); } public ConverterBean() {} public void ejbCreate() {} public void ejbRemove() {} public void ejbActivate() {} public void ejbPassivate() {} public void setSessionContext(SessionContext sc) {} } // ConverterBean
Neste caso, existe a necessidade de observar que o ConverterBean.java não implementa
a interface remota, quem vai realmente implementá-la é o container. Os clientes EJB não
acedem directamente. Para além disto, observámos que muitos métodos de “callback”
estão vazios.
Figura 18 – Funcionamento do Session Bean sem estado
Pág.56
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Cliente
Neste caso, poderemos ter dois tipos de clientes, o Application Client e um Web Client,
neste exemplo a seguir representado, será apresentado um Web Client, este código está
num index.jsp.
<%@page import="Converter,ConverterHome,javax.ejb.*, javax.naming.*, javax.rmi.PortableRemoteObject, java.rmi.RemoteException, java.math.*" %> <%! private Converter converter = null; public void jspInit() { try { InitialContext ic = new InitialContext(); Object objRef = ic.lookup("java:comp/env/ejb/TheConverter"); ConverterHome home = (ConverterHome)PortableRemoteObject.narrow(objRef, ConverterHome.class); converter = home.create(); } catch (RemoteException ex) { System.out.println("Couldn't create converter bean."+ ex.getMessage()); } catch (CreateException ex) { System.out.println("Couldn't create converter bean."+ ex.getMessage()); } catch (NamingException ex) { System.out.println("Unable to lookup home: "+ "TheConverter "+ ex.getMessage()); } } public void jspDestroy() { converter = null; } %> <html> <head> <title>Converter</title> </head> <body bgcolor="white"> <h1><b><center>Converter</center></b></h1> <hr> <p>Enter an amount to convert:</p> <form method="get"> <input type="text" name="amount" size="25"> <br> <p> <input type="submit" value="Submit"> <input type="reset" value="Reset"> </form> <%
Pág.57
Trabalho de J2EE
Aníbal Manuel e Silva Couto
String amount = request.getParameter("amount"); if ( amount != null && amount.length() > 0 ) { BigDecimal d = new BigDecimal (amount); %> <p><%= amount %> dollars are <%= converter.dollarToYen(d) %> Yen. <p><%= amount %> Yen are <%= converter.yenToEuro(d) %> Euro. <% } %> </body> </html>
Para isto ser efectuado necessitamos de efectuar 3 passos:
• Localizar a home interface
• Criar uma instância de um EJB
• Chamar um Business Method deste EJB
De uma forma sintetizada, quando falamos em localizar a home interface falamos em,
criar em primeiro lugar um contexto de JNDI, depois obtém-se um objecto ligado ao nome,
neste caso, ejb/TheConverter. Finalmente, convertemos o objecto ao tipo correcto
ConverterHome, isto é efectuado de uma forma muito similar a um “cast” em Java mas
envolvendo objectos remotos.
Relativamente, a criar uma instância de um EJB, isto é efectuado da seguinte maneira
no exemplo: Converter currencyConverter = home.create();
Claro que isto ao ser efectuado é invocado o método ConverterBean.ejbCreate();
Partindo agora para o 3º passo, o de chamar um Business Method do EJB é feito da
seguinte forma no exemplo anteriormente apresentando:
converter.dollarToYen(new BigDecimal(amount)).
Na realidade, aqui vamos chamar o método do container e este chama o método do
objecto remoto (instancia de EJB).
Pág.58
Trabalho de J2EE
Aníbal Manuel e Silva Couto
2.4.3.1.4.3 - Session Beans com estado
Para efectuar uma demonstração de um EJB com estado, vai ser dado um exemplo de
um cesto de compras CartEJB. Para tal ser efectuado, o bean especifico terá de ter as
seguintes funcionalidades básicas: Adicionar um livro, Remover um livro e por fim
examinar o conteúdo de um determinado livro. Então teremos que ter:
• Uma interface Home (CartHome);
• Uma interface Remote (Cart);
• Uma classe de implementação (CartBean);
Na classe a seguir representado, na Remote interface (Cart) serão apresentados os
Business Objects.
import java.util.*; import javax.ejb.EJBObject; import java.rmi.RemoteException; public interface Cart extends EJBObject { public void addBook(String title) throws RemoteException; public void removeBook(String title) throws BookException, RemoteException; public Vector getContents() throws RemoteException; }
Na home interface (CartHome), serão definidos todos os métodos de criação que serão
invocados pelo cliente remoto.
import java.io.Serializable; import java.rmi.RemoteException; import javax.ejb.CreateException; import javax.ejb.EJBHome; public interface CartHome extends EJBHome { Cart create(String person) throws RemoteException, CreateException; Cart create(String person, String id) throws RemoteException, CreateException; }
De seguida será apresentada a classe de implementação, que para tal ser efectuado será
necessário obedecer a determinadas regras:
Implementar a interface SessionBean;
A classe deve ser "public" (devido à instrospecção do Java);
Pág.59
Trabalho de J2EE
Aníbal Manuel e Silva Couto
A classe não pode ser abstract ou final;
Para cada método create na interface Home, a classe de implementação deve
implementar um método ejbCreate;
Essa classe não implementa a Remote interface;
Não é chamada pelo cliente;
Só é chamada pelo container;
Implementa os Business Methods da Remote Interface;
Contém um construtor público sem parâmetro;
Não deve definir o método finalize;
import java.util.*; import javax.ejb.*; public class CartBean implements SessionBean { String customerName; String customerId; Vector contents; public void ejbCreate(String person) throws CreateException { if (person == null) { throw new CreateException("Null person not allowed."); } else { customerName = person; } customerId = "0"; contents = new Vector(); } public void ejbCreate(String person, String id) throws CreateException { ejbCreate(person); IdVerifier idChecker = new IdVerifier(); if (idChecker.validate(id)) { customerId = id; } else { throw new CreateException("Invalid id: " + id); } } public void addBook(String title) { contents.add(title); } public void removeBook(String title) throws BookException { boolean result = contents.remove(title); if (result == false) {
Pág.60
Trabalho de J2EE
Aníbal Manuel e Silva Couto
throw new BookException(title + " not in cart."); } } public Vector getContents() { return contents; } public CartBean() {} public void ejbRemove() {} public void ejbActivate() {} public void ejbPassivate() {} public void setSessionContext(SessionContext sc) {} }
Na imagem seguinte é demonstrado como vai ser executado o processo em causa. Aqui
verifica-se que existem vários métodos de callback que serão invocados pelo container em
momentos apropriados. Para se entender quando os callbacks são chamados, existe
necessidade de examinar a figura abaixo que apresenta o ciclo de vida de um Stateful
Session Bean.
Figura 19 – Funcionamento do Session Bean com estado
Relativamente ao cliente que vai efectuar a invocação da classes e métodos em cima
referidos, temos o seguinte exemplo:
Pág.61
Trabalho de J2EE
Aníbal Manuel e Silva Couto
import java.util.*; import javax.naming.Context; import javax.naming.InitialContext; import javax.rmi.PortableRemoteObject; public class CartClient { public static void main(String[] args) { try { Context initial = new InitialContext(); Object objref = initial.lookup("java:comp/env/ejb/SimpleCart"); CartHome home = (CartHome)PortableRemoteObject.narrow(objref, CartHome.class); Cart shoppingCart = home.create("Duke DeEarl","123"); shoppingCart.addBook("The Martian Chronicles"); shoppingCart.addBook("2001 A Space Odyssey"); shoppingCart.addBook("The Left Hand of Darkness"); Vector bookList = shoppingCart.getContents(); Iterator enumer = bookList.iterator(); while (enumer.hasNext()) { String title = (String) enumer.next(); System.out.println(title); } shoppingCart.removeBook("Alice in Wonderland"); shoppingCart.remove(); System.exit(0); } catch (BookException ex) { System.err.println("Caught a BookException: " + ex.getMessage()); System.exit(0); } catch (Exception ex) { System.err.println("Caught an unexpected exception!"); ex.printStackTrace(); System.exit(1); } } }
Pág.62
Trabalho de J2EE
Aníbal Manuel e Silva Couto
2.4.3.1.5 – Message-Driven Beans
Os Message-Driven Beans são um tipo de componentes EJB que recebem mensagens
por meio de um JMS (Java Message Service).
Enquanto tradicionalmente os outros Beans são acedidos através de interfaces
(RMIIIOP) com acesso síncrono, os MessageDriven Beans, também conhecidos pela sigla
MDB, são utilizados por meio de mensagens, com acesso assíncrono.
Isso se dá por meio de um middleware orientado a mensagens (MOM), localizado entre
o cliente, Message Producer, e o bean, Message Consumer. Este middleware recebe
mensagens de um ou mais clientes e envia as mensagens para os Beans destino.
JMS é a API utilizada para receber as mensagens dos clientes e enviar as mensagens aos
MessageDriven Beans.
O estado do objecto é muito simples e semelhante a um EJB Session Bean Stateless que
não mantêm o estado para um cliente em particular. Quando enviamos uma mensagem
para invocarmos um MessageDriven Bean, o estado das suas variáveis mantêm-se apenas
durante a invocação. Quando o processamento requerido é finalizado o estado não é retido.
São componentes que não estão associados a um cliente específico e, portanto,
implementam comportamentos que atendem a necessidade de muitos clientes.
Figura 20 – Diagrama de Classes UML do Message-Driven Beans.
Um exemplo de um Message Driven-Beans pode ser o seguinte:
package com.book.example.ejb.mdb; import javax.ejb.*; import javax.jms.*;
Pág.63
Trabalho de J2EE
Aníbal Manuel e Silva Couto
import javax.naming.*; // Este EJB exemplo do tipo Message-Driven Bean, apresenta os métodos-padrão // de ciclo de vida ejbCreate() e ejbRemove() e o método 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 exceção na instanciação do objecto. public void ejbCreate() throws CreateException { } // Utilizado pelo container para remover o EJB. public void ejbRemove() { } // Executado no recebimento de uma mensagem para este MDB. // @param msg mensagem recebida através 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; } }
Deve-se utilizar EJB MessageDriven Bean quando se necessita de operações
assíncronas sendo executadas no servidor (container).
Observe-se que para realizarmos um processamento em paralelo no servidor sem o uso
de MessageDriven Bean, era necessário o uso de Threads em EJB Session Bean Stateless.
Esta prática, não é aconselhada pela própria Sun MicroSystems Inc., pois recai em
vários problemas, sendo um deles a falta de controlo dessas execuções por parte do
container, perdendo assim as facilidades e ganhos que o container oferece.
Pág.64
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Para corrigir este problema, foi criado o EJB MessageDrive Bean que pode ter várias
instâncias de um mesmo componente sendo executados em paralelo, para realizar a mesma
operação.
Ciclo de vida de um Message-Driven Bean
Na figura 21 é representado o ciclo de vida do MessageDriven Bean. O seu ciclo é bem
simples comparado aos outros beans, pois o container instancia um determinado número de
beans e mantendo-os no pool de acordo com as necessidades e removidas quando o
container decidir, da mesma forma que o Session Bean Stateless. Assim que uma
mensagem é recebida pelo JMS, ela é redireccionada para um bean específico, para que
seja tratada.
Figura 21 – Ciclo de Vida de um Message Driven Bean
Pág.65
Trabalho de J2EE
Aníbal Manuel e Silva Couto
O que é e para que serve o JMS?
Antes de falarmos a respeito de JMS, devemos entender o conceito de Messaging (envio
de mensagens). Messaging pode ser entendido pela troca de mensagens entre duas
aplicações, programas ou componentes. Um cliente pode enviar mensagens para um ou
mais receptores, que também pode retornar uma outra mensagem, ou executar algum
método de negócio. Utilizando este recurso, o receptor de mensagens não precisa estar
disponível no mesmo momento que o cliente enviou a mensagem, podendo ser consumida,
ou recebe-la posteriormente, isto é, no momento em que seu serviço estiver activo. Assim,
o cliente que envia a mensagem e o receptor da mensagem devem somente conhecer bem o
formato da mensagem, com os dados que ela carrega.
Para fazer uso destes recursos na linguagem Java, foi criada uma API conhecida como
JMS – Java Messaging Service. Esta API fornece serviços que permitem a criação, envio,
recepção e leitura de mensagens. O importante a saber é que um cliente cria uma
mensagem e a envia utilizando esta API. Um receptor de mensagens, receberá esta
mensagem através de um MessageOrientedMiddleware ou MOM. Alguns conceitos muitos
usados nas referências a JMS são produtores e consumidores de mensagem (producers /
consumers), para designar um cliente como um produtor de mensagens e um componente
EJB MessageDriven Bean por exemplo, como um consumidor de mensagens.
O caminho percorrido pela mensagem é bem simples. Vamos ver isso na figura abaixo,
na qual o produtor envia a mensagem, que é recepcionada pelo MOM e a seguir
redireccionada para o consumidor corretor. Observa-se na figura, que o produtor também
pode ser um consumidor de mensagens e que o consumidor de mensagens também pode
ser um produtor.
Figura 22 – MOM
Pág.66
Trabalho de J2EE
Aníbal Manuel e Silva Couto
A arquitectura JMS é composta por cinco partes que são: Provedor JMS, que
implementa as interfaces definidas na API JMS e fornece recursos para administrar este
serviço; os clientes JMS que podem ser programas ou componentes que agem como
produtores e consumidores de mensagens; as mensagens propriamente ditas que são
objectos que transportam os dados do cliente para o receptor; os objectos de administração
do serviço JMS que são utilizados pelos clientes para enviar as mensagens; e os clientes
nativos que são clientes que usam produtos de Messaging nativos e não da API JMS.
A seguir são apresentados detalhar os dois tipos de colocação de mensagens de modo a
entender as diferenças entre eles.
• PointtoPoint
• Publish/Subscribe.
Mensagens Point-To-Point (Queue)
O conceito de mensagens PointToPoint – PTP – é de colocar numa fila (Queue) as
mensagens para serem consumidas. Os produtores enviam as mensagens para uma
determinada fila (Queue), que são consumidas por um destinatário. Assim que receber a
mensagem, o destinatário avisa ao MOM que a mensagem foi recebida e processada
correctamente (sinal de acknowledge). A fila armazena todas as mensagens que são
enviadas, até o momento que são consumidas pelos receptores, ou até o momento que
forem expiradas.
Observe-se ainda, que vários consumidores de mensagens (muitas instâncias do mesmo
consumidor) podem consumir mensagens do MOM. Este recurso normalmente é
disponibilizado e gerido pelo servidor de aplicações para processamento de mensagens em
paralelo.
O cliente pode enviar mensagens para o MOM, mesmo sem existir nenhum consumidor
de mensagens activo naquele momento.
Pág.67
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Figura 23 – Point-to-Point (Queue).
Mensagens Publish/Subscribe (Topic)
No uso de publish/subscribe – Publica/Inscreve – os clientes enviam a mensagem para
um tópico (topic). Os consumidores registam-se nos tópicos que lhes são convenientes e
são notificados da chegada de uma nova mensagem.
Os consumidores podem somente consumir mensagens que foram colocadas depois de
se terem registrado (inscrito) no MOM, isto é, as mensagens enviadas pelos clientes antes
disto, não podem ser consumidas por eles. Neste caso, cada mensagem pode ter mais de
um tipo de consumidor.
Se algum cliente enviar uma mensagem para um tópico que não possuem nenhum
consumidor registrado, esta mensagem não será entregue. Após o consumidor se registar,
as mensagens que chegam ao MOM são notificadas aos consumidores, que fornece estas
mensagens a eles.
Por haver uma dependência muito grande do tempo em que o consumidor deve estar
activo enquanto o cliente envia a mensagem, os consumidores podem fazer registos
duráveis (DURABLE) e receber mensagens enviadas enquanto eles não estão activos. Isto
permite a facilidade de uma fila, com a diferença de consumo de mensagens por diversos
tipos de consumidores.
Pág.68
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Figura 24 – Publish/Subscribe (Topic).
Exemplo:
A seguir é apresentado um exemplo simples do envio de mensagens por um cliente
TextClient e o recebimento das mensagens por um MessageDriven Bean TestMDB.
Teste de envio de mensagens: TestClient import javax.jms.*; import javax.naming.*; // Esta classe exemplo, envia mensagens para um fila (queue) // para ser consumida por um MDB. public class TestClient { public static void main(String[] args) { QueueConnection queueConnection = null; try { // cria o contexto Context ctx = new InitialContext(); // localiza a connection factory QueueConnectionFactory queueConnectionFactory = (QueueConnectionFactory) ctx.lookup(“java:comp/env/jms/ MyQueueConnectionFactory”); // localiza a queue (fila) Queue queue = (Queue) ctx.lookup(“java:comp/env/jms/QueueName”); // cria a conexão queueConnection = queueConnectionFactory.createQueueConnection(); // cria a sessão da conexão QueueSession queueSession = queueConnection.createQueueSession(false,
Pág.69
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Session.AUTO_ACKNOWLEDGE); // cria o sender QueueSender queueSender = queueSession.createSender(queue); // cria a mensagem e as envia TextMessage message = queueSession.createTextMessage(); for (int i = 0; i < 3; i++) { message.setText(“Mensagem nr: “ + (i+1)); System.out.println(message.getText()); queueSender.send(message); } } catch (Exception e) { e.printStackTrace(); System.exit(1); } finally { // fecha a conexão if (queueConnection != null) { try { queueConnection.close(); } catch (JMSException e) {} } System.exit(0); } } }
MessageDriven Bean : TestMDB import javax.ejb.*; import javax.naming.*; import javax.jms.*; // 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 { // Contexto do Message-Drive Bean. private transient MessageDrivenContext ctx = null; // Instância o objecto no servidor pelo container. public void ejbCreate() { } // Remove a instância do objecto no servidor. public void ejbRemove() { } // Configura o contexto do EJB MDB. // @param ctx contexto do MDB. public void setMessageDrivenContext(MessageDrivenContext ctx) { this.ctx = ctx; }
Pág.70
Trabalho de J2EE
Aníbal Manuel e Silva Couto
// 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(); } } }
2.4.3.1.6 – Regras para escolher qual o tipo de Bean
• Uso de Entity Beans
o Quando o estado do Business Object deve ser armazenado de forma
persistente e o comportamento do objecto tem a ver basicamente com o
acesso ao estado;
o Para permitir acesso concorrente por múltiplos clientes, quando o
estado não é específico a um cliente;
o Para representar uma única linha lógica de um BD;
o Para permitir robustez. Se os dados de um cliente devem permanecer
quando uma sessão de cliente acabou ou depois de um crash de servidor,
tem de se usar os Entity Beans;
• Uso de Stateful Session Bean
o Para manter estado específico a um cliente (estado conversacional).
Não há partilha com outros clientes;
o Para representar objectos não persistentes (objectos com curto tempo
de vida e que não precisam permanecer depois de uma sessão ou após um
crash de servidor);
o Para representar o workflow entre Business Objects (para
administrar as interacções entre Business Objects);
Pág.71
Trabalho de J2EE
Aníbal Manuel e Silva Couto
• Uso de Stateless Session Bean
o Para modelar serviços reutilizáveis (prevendo um serviço genérico
para os clientes, sem manter dados específicos de um cliente);
o Para fornecer alto desempenho (o cliente terá que manter o estado, se
necessário);
o Para operar sobre múltiplas linhas lógicas de um BD (para
representar uma visão compartilhada de dados fixos);
o Para fornecer uma visão dos dados (quando se foge do modelo OO e
todos os dados necessários são fornecidos na entrada e todos os resultados
retornados no fim do procedimento);
• Business Logic deve estar nos Session Beans
o Para escalabilidade, -> Stateless Session Beans;
o O uso de Stateful Beans deve ser minimizado;
• Para acesso a BD, -> Entity Beans para:
o Ter uma visão OO dos dados;
o Não ter que tratar de aspectos transaccionais, de persistência, de
segurança, etc.
• Fazer com que o cliente aceda apenas Session Beans
o Esconda os Entity Beans atrás de Session Beans;
o Por quê?
Para possibilitar armazenar estado transaccional o que não
deve ser feito em Entity Beans;
o Se existirem aspectos transaccionais não triviais a considerar, eles
podem ser tratados no Session Bean (escrito por um especialista) e o
Application Developer não vai ter que saber nada sobre transacções;
o Melhora a integridade dos Bases de dados, já que o Application
Developer não vai manipular o BD directamente. Ele só usaria Session
Beans;
Pág.72
Trabalho de J2EE
Aníbal Manuel e Silva Couto
3 - Segurança J2EE
Numa aplicação J2EE, há duas formas que os clientes devem ser avaliados no acesso ao
sistema e aos componentes que ele utiliza. Para que um cliente possa aceder a 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 informações como o utilizador e password, ou algum código de acesso ou algo
parecido. O sistema autenticará o utilizador e sendo assim, associará o mesmo a uma
identidade de segurança pré-estabelecida, tal como um perfil de administrador ou
coordenador por exemplo.
Assim que o utilizador é autenticado e acede ao sistema, este último deverá apresentar
formas de autorizar o utilizador a aceder a operações do sistema válidas para o seu perfil de
utilizador. Por exemplo, se o perfil do utilizador é de visualização, o mesmo não poderia
efectuar operações de criação, modificação e eliminação de dados.
A autenticação é feita antes de realizar as operações nos EJBs e veremos mais adiante as
formas que podem ser utilizadas para tal. Já a autorização é realizada durante a chamada de
métodos dos EJBs, que permitem ou negam o acesso de determinado perfil de utilizador.
Veremos a seguir uma breve explicação da API JAAS e como utilizá-la.
3.1 - JAAS
O JAAS (Java Authenticated and Autorizated Service) apresenta interfaces que
possibilitam que utilizadores sejam autenticados e autorizados em aplicações J2EE. Com
isso, permite que o utilizador aceda ao sistema e operações dele, não importando como é
implementado pelo fabricante do servidor J2EE. Deste modo, o servidor J2EE encarrega-se
de localizar os dados dos utilizadores que estão aptos a aceder ao sistema, o perfil de cada
um, possibilitando os mesmos de acederem a operações específicas oferecidas pela
aplicação em questão.
Um utilizador poderá aceder a um sistema e estar autenticado para o mesmo, sendo ele
uma aplicação Web ou uma aplicação “standalone”. Isso deverá ser transparente para o
Pág.73
Trabalho de J2EE
Aníbal Manuel e Silva Couto
utilizador, sendo que a aplicação J2EE poderia fornecer as duas interfaces para o utilizador
com as mesmas funcionalidades.
3.1.1 - Autenticação
Em versões mais antigas da especificação EJB não havia uma API que definia os
serviços necessários para operações de segurança. Com a criação da API JAAS isto foi
possível e autenticar um utilizador ficou mais simples e portável.
Com foi dito anteriormente, um utilizador poderá aceder a um sistema por uma interface
Web ou standalone, sendo que a aplicação deverá prover os mesmos recursos para o
utilizador. Em interfaces standalone, a autenticação parece ser mais simplista, tendo a
aplicação que utilizar a API JAAS para autenticar o utilizador, a partir das informações
fornecidas pelo mesmo.
Em interfaces Web isto também é necessário, sendo que o utilizador também deverá
fornecer informações como utilizador e password para o servidor Web que irá verificar a
autenticidade da informação. Para fazer isso, o navegador poderá apresentar quatro formas
de realizar uma autenticação que são: Basic Authentication (Autenticação Básica),
FormBased Authentication (Autenticação baseada em Formulários), Digest
Authentication (Autenticação com Mensagem Alterada) e Certificate Authentication
(Autenticação com Certificado Digital).
Basic Authentication - O browser apresenta uma página de login e fornece ao servidor
o utilizador e password para a autenticação. Esta página depende do browser que está a
utilizar.
FormBased Authentication - A aplicação fornece uma página HTML (que poderá ser
gerada por um JSP, por exemplo) com um formulário no qual o cliente informaria o
utilizador e password. Para isso, há um padrão utilizado pela API JAAS.
... <form method=”post” action=”j_secutiry_check”> Utilizador: <input type=”text” name=”j_username”> Senha: <input type=”password” name=”j_password”>
Pág.74
Trabalho de J2EE
Aníbal Manuel e Silva Couto
</form> ...
Digest Authentication - Para este tipo de autenticação é usado um algoritmo para
converter o utilizador e password num texto ilegível à leitura, dificultando que utilizadores
mal intencionados descubram estas informações. Esta informação é passada ao servidor
que utilizando o mesmo algoritmo, autentica o cliente em questão.
Certificate Authentication - O servidor recebe do cliente um certificado digital pelo
qual será autenticado. Assim que o cliente é autenticado pela aplicação, o mesmo estará
associado a uma identidade ou perfil, que será propagado por toda a aplicação e utilizado
pelo servidor para a execução dos métodos dos EJBs, isto é, o seu perfil será utilizado na
sua autorização.
3.1.2 - Autorização
Estando o cliente autenticado, ele deverá ser autorizado a realizar certas operações
fornecidas pelo sistema, de acordo com o seu perfil de utilizador. Para isso, a aplicação
deve estar configurada com “security policies” ou regras de segurança para cada serviço
fornecido por seus componentes, isto é, para cada método de cada EJB.
A autorização pode ser apresentada de duas formas: Autorização Programática ou
Declarativa. Na Autorização Programática o programador deve implementar a verificação
de segurança no EJB, isto é, deve verificar qual utilizador que está a aceder ao serviço e
validar o mesmo. Na Autorização Declarativa o container realiza toda a validação de
segurança, não sendo preciso implementá-la.
Para isso, deve-se configurar no deployment descriptor as propriedades de segurança
para cada EJB e para cada método do mesmo.
Num mundo perfeito, a melhor forma a utilizar é a Autorização Declarativa. Haverá
casos que será necessário juntar as duas formas de autorização, sendo que somente a
declarativa não será suficiente. Por exemplo, se numa rede de lojas um utilizador com
perfil de gerente pode aceder aos serviços de obtenção de relatórios de gerentes, sendo
somente permitido aceder a esses dados das redes de uma determinada local, é necessário
Pág.75
Trabalho de J2EE
Aníbal Manuel e Silva Couto
incluir uma validação programática da região da rede de lojas que o gerente em questão
actua.
3.1.2.1 - Security Roles
O conceito de security roles é simples, mas necessário para o entendimento do uso de
autorização. Uma security role é um conjunto de identidades de utilizadores (identity). Para
um utilizador ser autorizado a realizar uma operação por exemplo, a sua identidade deverá
estar na correcta security role (perfil) para a operação em questão. O uso de security roles é
interessante, pois quem desenvolve não precisa especificar o perfil do utilizador no código
do EJB.
3.1.2.2 - Autorização Programática
Para realizar a autorização de forma programática, é necessário obter as informações do
utilizador autenticado na implementação do EJB. Isto deve ser feito utilizando a interface
javax.ejb.EJBContext que fornece os métodos getCallerPrincipal() e isCallerInRole().
Vejamos a seguir os métodos desta interface.
public interface javax.ejb.EJBContext { ... public java.security.Principal getCallerPrincipal(); public Boolean isCallerInRole(String roleName); ... }
O método getCallerPrincipal() fornece informações do utilizador actual, autenticado no
sistema. Este método retorna o objecto java.security.Principal no qual se pode obter
informações importantes do utilizador, utilizadas para a sua autorização.
O método isUserInRole(String roleName) verifica se o utilizador actual está dentro de
uma security role específica. Desta forma, pode-se realizar a autorização para um
determinado serviço do EJB de forma programática.
Vejamos a seguir um exemplo de deployment descriptor, configurando secutiry roles e
links para as security roles reais. Esta última propriedade pode ser configurada, pois em
Pág.76
Trabalho de J2EE
Aníbal Manuel e Silva Couto
tempo de desenvolvimento o programador pode definir uma security role dentro do seu
código e depois no momento da instalação do sistema, a security role real tem um nome
diferente, então cria-se um link para o nome correcto.
... <enterprise-beans> <session> ... <security-role-ref> <description>Perfil do utilizador=gerente</description> <role-name>gerente</role-name> <role-link>manager</role-link> </security-role-ref> ... </session> <assembly-descriptor> ... <security-role> <description>Perfil de utilizador=gerente</description> <role-name>manager</role-name> </security-role> ... </assembly-descriptor> </enterprise-beans> ...
3.1.2.3 - Autorização Declarativa
A diferença de utilizar autorização declarativa ao invés da declaração programática é
que não há a necessidade de programar a autorização, necessitando somente de configurar
o deployment descriptor, definindo qual para cada EJB a security role a ser utilizada. Pode-
se definir uma security role para todos os métodos do EJB, ou definir uma específica para
cada método.
Observe-se que se alguma operação realizar uma chamada a algum método com um
perfil inadequado, isto é, com um perfil que não foi configurado ou definido para o
método, o container lançará uma excepção do tipo java.lang.SecurityException.
Vejamos a seguir um exemplo de deployment descriptor, configurando security roles e
as permissões para os métodos dos EJBs.
Pág.77
Trabalho de J2EE
Aníbal Manuel e Silva Couto
... <enterprise-beans> <session> ... <security-role-ref> <description>Perfil do utilizador=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> <method> <ejb-name>EJBTestY</ejb-name> <method-name>calc</method-name> </method> <method> <ejb-name>EJBTestY</ejb-name> <method-name>go</method-name> </method> <method> <ejb-name>EJBTestY</ejb-name> <method-name>getAccount</method-name> </method> <method> <ejb-name>EJBTestY</ejb-name> <method-name>doTransfer</method-name> <method-params>Integer</method-params> <method-params>Integer</method-params> <method-params>Integer</method-params> </method> ... </method-permission> <description>Este método não sera executado</description> <method> <ejb-name>EJBTestY</ejb-name> <method-name>cleanFunds</method-name>
Pág.78
Trabalho de J2EE
Aníbal Manuel e Silva Couto
</method> <exclude-list> </exclude-list> ... </assembly-descriptor> </enterprise-beans> ...
3.1.3 - Propagação de Segurança
Numa aplicação J2EE, teremos com certeza casos em que serviços de alguns EJBs
utilizam serviços de outros. Dependendo da aplicação, poderíamos querer que a identidade
do utilizador (perfil) seja propagado para os métodos que estão a ser chamados pelos
próprios EJB para outros EJBs, ou em vez disso, definir um perfil para executar um
determinado método em um EJB específico.
Imagine-se uma situação em que um cliente acede a um serviço de cálculo de um certo
imposto para a venda de um produto. Chamaremos este como serviço doXXX do EJB A.
Este método chamaria outro método do EJB B, o método doYYY. Podemos definir na
aplicação, que este último método execute com a identidade de quem invoca, isto é, utilize
a mesma identidade do cliente que chamou o método doXXX do EJB A. Ou ainda
poderíamos definir que o método doYYY do EJB B rodasse com uma nova identidade,
definida pela aplicação. Essas duas opções podem ser configuradas no deployment
descriptor da aplicação. Vejamos um exemplo a seguir:
<enterprise-beans> <session> <ejb-name>A</ejb-name> ... <security-identity> <use-caller-identity/> </security-identity > ... </session> <session> <ejb-name>B</ejb-name> ... <security-identity> <run-as> <role-name>gerente</role-name>
Pág.79
Trabalho de J2EE
Aníbal Manuel e Silva Couto
</run-as> </security-identity > ... </session> <assembly-descriptor> ... <security-role> <description>Perfil de utilizador=gerente</description> <role-name>gerente</role-name> </security-role> ... </assembly-descriptor> </enterprise-beans>
Exemplo: Veremos a seguir, um exemplo de módulo de segurança utilizando a API JAAS.
ExampleLoginModule.java package com.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 módulo de login para realizar a autenticação do utilizador. // Esta classe não apresenta implementação, somente sendo um ponto de partida // para a criação de um módulo de login. public class ExampleLoginModule implements LoginModule { // Representa um gurpo de informações relacionados a uma entidade (cliente). private Subject subject = null; // Inicializa o módulo de login. // Este método é executado pelo contexto de login, após a sua instancia, // com o propósito de inicializar este módulo com informações 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 módulos. // @param options opções especificadas na configuração do login. public void initialize(Subject subject, CallbackHandler callbackhandler, Map sharedState, Map options) { this.subject = subject; } // Este método é utilizado para autenticar o utilizador. // @return verdadeiro se a autenticação se realizar com sucesso, // falso caso contrário. // @throws LoginException exceção ao tentar autenticar o utilizador. public boolean login() throws LoginException {
Pág.80
Trabalho de J2EE
Aníbal Manuel e Silva Couto
// Deve autenticar o utilizador e senha do cliente que está tentando acesso // Isso pode ser feito por ficheiro de properties, LDAP, banco etc. } // Utilizado para realizar o commit da autenticação. // @return verdadeiro se obtiver sucesso no commit, falso caso contrário. // @throws LoginException caso falhe o commit. public boolean commit() throws LoginException { return true; } // Utilizado par abortar o processo de autenticação. // Chamado pelo contexto de login se a autenticação falhar. // @return verdadeiro caso haja sucesso no abort, falso caso contrário. // @throws LoginException caso falhe no abort. public boolean abort() throws LoginException { return true; } // Utilizado para efetuar o logout do utilizador autenticado. // A sua implementação deverá destruir o Principal e // Credenciais do subject (cliente). // @return veradeiro caso o logout efetue com sucesso, falso caso contrário. // @throws LoginException exceção caso o logout falhe. public boolean logout() throws LoginException { return true; } } ExamplePrincipal.java package com.book.example.security; import java.security.*; // Representa o utilizador a ser autenticado. public class ExamplePrincipal implements Principal { // Nome do utilizador. private String name = null; // Construtor customizado. // @param name nome do utilizador. public ExamplePrincipal(String name) { this.name = name; } // Obtém o nome do utilizador. // @return nome do utilizador. public String getName() { return name; } // Implementação do método equals. // Verifica se um objecto é igual a este. // @param obj objecto a ser comparado. // @return verdadeiro caso o objecto seja igual a este, falso caso contrário.
Pág.81
Trabalho de J2EE
Aníbal Manuel e Silva Couto
public boolean equals(Object obj) { if (obj == this) return true; if (! (obj instanceof ExamplePrincipal)) return false; return name.equals(((ExamplePrincipal) obj).getName()); } // Implementação do método hashCode. // Informa uma chave de hash utilizada para este objecto. // @return chave de hash. public int hashCode() { return name.hashCode(); } // Retorna uma string com informações do utilizador. // @return string com informações do utilizador. public String toString() { return name; } } ExampleRoleGroup.java package com.book.example.security; import java.util.*; import java.security.*; import java.security.acl.*; // Apresenta o esqueleto para a implementação de um grupo de utilizadores. public class ExampleRoleGroup extends ExamplePrincipal implements Group { // Construtor customizado. // @param name nome do utilizador. public ExampleRoleGroup(String name) { // implementação do construtor... } // Adiciona o utilizador em questão ao grupo. // @param user utilizador a ser adicionado ao grupo. // @return veradeiro se o utilizador foi adicionado com sucesso, // falso caso contrário. public boolean addMember(Principal user) { return true; } // Remove o utilizador do grupo. // @param user utilizador a ser adicionado ao grupo. // @return veradeiro se o utilizador foi removido com sucesso, // falso caso contrário. public boolean removeMember(Principal user) { Object prev = members.remove(user); return prev != null; }
Pág.82
Trabalho de J2EE
Aníbal Manuel e Silva Couto
// Verifica se o utilizador é membro do grupo. // @param member utilizador que deverá ser verificado se é membro. // @return verdadeiro se o utilizador é membro, falso caso contrário. 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()); } } ExampleTest.java package com.book.example.security; import java.util.*; import javax.rmi.*; import javax.naming.*; import java.security.*; // Implementação de uma acção privilegiada. // Executada com segurança. public class ExampleTest implements PrivilegedAction { // Executa a ação com segurança. // @return informação retornada pelo método 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(); } } } ExampleMain.java package com.book.example.security; import javax.naming.*; import javax.security.auth.*; import javax.security.auth.login.*; public class ExampleMain { public static void main(String[] args) throws Exception { LoginContext loginContext = new LoginContext(“ExampleTest”); loginContext.login();
Pág.83
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Subject subject = loginContext.getSubject(); ExampleTest exampleTest = new ExampleTest(); Subject.doAs(subject, action); } }
Pág.84
Trabalho de J2EE
Aníbal Manuel e Silva Couto
4 – OUTROS PROCESSAMENTOS SERVER SIDE
Se o processamento em aplicações WEB ocorre do lado do servidor é conveniente
pensar garantir escalabidade, manifestada em termos de disponibilidade e desempenho.
Uma solução óbvia é aumentar a capacidade do servidor. Infelizmente o custo do servidor
cresce exponencialmente com o aumento do desempenho, de modo que duplicar o
desempenho implica em quadruplicar o preço, por exemplo. Ainda assim o problema da
disponibilidade é difícil de tratar com um só servidor.
A solução é ter mais de um servidor. Na prática, distribuir a aplicação entre muitos
servidores, de modo que parte dos objectos execute em cada máquina e o perfil delas se
mantenha dentro de um horizonte de custos razoável. Como distribuir a aplicação é,
portanto, a questão fundamental, mas que ocorre sobre diversas formas; por exemplo:
como é que objectos em um servidor criam ou encontram objectos em outros servidores? O
que acontece se a conexão entre servidores cai no meio de uma comunicação entre eles?
Como amenizar o custo de criação de objectos em servidores remotos? Como é que
objectos podem ser mapeados como tabelas de uma base de dados?
4.1 - JAF E JAVAMAIL
O JAF (JavaBeans Activation Framework) e o JavaMail. São implementações de
suporte ao envio e para receber e-mails em Java, apenas isso. O JavaMail é o principal e o
JAF serve para determinar os tipos de uns dados a partir de um conjunto de dados. Por
exemplo, observando um stream de bits, determinar que se trata de uma imagem JPEG.
Isso é importante porque pode determinar correctamente o tipo de dados anexo num e-mail
e simplificar o processo de renderização nos programas de e-mail ou browsers.
4.2 - JNDI
Mesmo que não saibamos, ainda, como distribuir os objectos entre múltiplas máquinas,
é importante saber como um objecto descobre em que máquina um outro objecto está
executando ou pode ser executado. Pensemos por analogia: como é que o browser web
descobre onde está localizado o servidor: www.j2ee.com? Através do DNS (Domain Name
System), certo? O browser pergunta a um servidor de DNS que, sozinho ou
cooperativamente com outros servidores, conhece o endereço IP de cada máquina na
Pág.85
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Internet e responde à pergunta. Claro que cada máquina deve ser verificada junto a algum
servidor de DNS. Este esquema funciona bem para mapear nomes para endereços IP com a
vantagem de ser possível mudar o IP de servidores sem impacto nos clientes, que só
conhecem o nome, embora a comunicação seja por IP.
No mundo Java esse mesmo mecanismo é utilizado com o objectivo de oferecer
mapeamento entre: nomes de objectos e máquinas que os contêm, nomes de bases de dados
e máquinas que os implementam. Um servidor de JNDI (Java Naming and Directory
Interface) é o elemento utilizado para identificar responsáveis por serviços Java, e isso dá-
lhe a capacidade de responder a perguntas de clientes por esses serviços.
No caso de objectos distribuídos, o requerido pelo cliente é descobrir que máquina
dispõe de um determinado objecto; ao servidor do objecto cabe registrá-lo. Um servidor
JNDI é o elo entre eles.
Figura 25 – JNDI.
4.3 - JTA
Num ambiente distribuído, aspectos como falhas na rede ou dependência entre
operações sobre objectos, que se comportam como uma transacção (atomicidade,
consistência, isolamento e durabilidade) tornam-se fundamentais. O JTA (Java Transaction
Architecture) especifica uma interface padrão para aplicações utilizarem um serviço de
suporte transaccional. Uma implementação específica é denominada JTS (Java Transaction
Service).
Pág.86
Trabalho de J2EE
Aníbal Manuel e Silva Couto
A forma como são geridas as transacções é mais conhecido no contexto de bases de
dados, contudo o seu uso no contexto de aplicações distribuídas é mais amplo. Os objectos
que são postos debaixo de uma transacção e fazem chamadas de métodos que contêm
acções sobre uma base de dados têm essas mesmas acções commited ou rollbacked em
função do que for definido para a transacção.
Exemplo de uso de JTA:
public void transferenciaEntreContasCorrentes(ContaCorrente origem, ContaCorrente destino, double montante) { javax.transaction.UserTransaction ut = sessionContext.getUserTransaction(); try { ut.begin(); origem.debitar(montante); destino.creditar(montante); ut.commit(); } catch (Exception ex) { try { ut.rollback(); } catch (Exception rbex) { rbex.printStackTrace(); } throw new RuntimeException(ex); } }
Pág.87
Trabalho de J2EE
Aníbal Manuel e Silva Couto
5 - DESENVOLVIMENTO DE APLICAÇÕES J2EE: PAPEIS, COMPOSIÇÃO E
DEPLOYMENT
Da forma mais concisa o quanto possível, vou tentar explicar o que é demais essencial
para construção de aplicações J2EE.
Para desenvolver aplicações J2EE, deve-se:
• Desenvolver componentes de aplicação
• Compor os componentes em módulos
o Adicionando outros recursos e um Deployment Descriptor
• Compor módulos em aplicações
• Deployment da aplicação
o Instalação e customização da aplicação, incluindo seus módulos
• Observe que o deployment de módulos é feito e não de componentes
o Isso vai contra as definições normais de componente
o Porém, temos de pensar num módulo como sendo um ficheiro
podendo conter mais de um componente
o Exemplo: um módulo (ficheiro) que contenha vários EJBs
Papeis
Devido à construção de aplicações com a composição de componentes, temos novos
papeis a considerar
Pág.88
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Figura 26 – Papeis.
J2EE Server Provider
• Fornece o Middleware contendo os serviços não automáticos (Naming
usando JNDI, Transacções usando JTS, ...)
• O J2EE Server deve ser capaz de aceitar vários EJB Containers e Web
Containers
• J2EE Servers podem ser construídos em cima de
o SGBDR
o SGBDOO
o Monitores de Transacção
o Web Application Servers
o etc.
• Exemplos: IBM WebSphere, BEA WebLogic, Sun iPlanet, Oracle
Application Server, JBoss
o Devem ser especialistas em Gerência de Translações Distribuídas,
Objectos Distribuídos, etc.
Pág.89
Trabalho de J2EE
Aníbal Manuel e Silva Couto
EJB/Web Container Provider
Fornece o software para receber componentes e fornecer os serviços automáticos.
Alguma ferramenta deve fornecer a geração automática dos Containers (que obedecem à
interface dos Beans ou Web components, já que interceptam as chamadas), no final das
contas, um Container é um monte de classes em Java geradas automaticamente.
Deve também se registrar-se junto ao serviço de Naming para que os clientes possam
achar objectos que obedeçam às interfaces desejadas. Os containers correm dentro do J2EE
Server e/ou no servidor Web e/ou na máquina cliente.
Como não há (ainda) padronização de interface entre o J2EE Server e os Containers,
quem é fornecedor de servidores também fornece os Containers. Exemplos: IBM, BEA,
Sun, Oracle.
Application Component Developer
Um programador produz EJBs e Web components. Os EJBs capturam o Business Logic
reutilizável da empresa. Sendo reutilizável, vale a pena colocar num Bean.
Pode ser um programador da empresa cliente ou de uma empresa especializada em
construir EJBs.
Deployer
• Faz tudo que tem a ver com o ambiente run-time final
• Um técnico da empresa cliente final
• Vai instalar os Beans e Web components no J2EE Server e configurá-los no
ambiente run-time
o Através do Deployment Descriptor
o Usando Programação Declarativa
• Não precisa saber Java, nem o Business Logic
• Deve saber quais são os bases de dados, os utilizadores, etc.
• O que é configurado:
o O nome dos Beans, Web components
o Os nomes das interfaces dos Beans, Web components
o Valores de timeout de sessão
Pág.90
Trabalho de J2EE
Aníbal Manuel e Silva Couto
o Lista de campos mantidos pelo container (persistência automática)
o Access Control List para segurança
o Controlo de Transacções (Not Supported, Supported, Required,
Requires-New, Bean-Managed, ...)
o Transaction Isolation Level (Serializable, Read Uncommitted, Read
Committed, Repeatable Read)
Application Developer
• Junta todos os tiers para criar a aplicação final
• Escreve a aplicação usando Componentes prontos
• A aplicação pode envolver:
o Aplicação console em Java
o Applet
o Servlet
o Aplicação CORBA
o Controle ActiveX (usando o bridge COM-CORBA)
• Quem desenvolve preocupa-se mais com a funcionalidade de muito alto
nível, tipicamente Apresentação de Dados.
System Administrator
• Administra o ambiente e faz o afinamento (fine tuning);
• Monitoração em tempo real de:
o Servidores de aplicação
o Componentes
o Containers
o Clientes
• Pode definir o número concorrente de utilizadores que executam um cliente
ou Container ou componente específico;
• Pode ter visão instantânea ou histórica de eventos, cargas, etc.
• Criação, composição e packaging de componentes;
• Um módulo é uma unidade de empacotamento;
Pág.91
Trabalho de J2EE
Aníbal Manuel e Silva Couto
• Junta um ou mais componentes do mesmo tipo
• Há 3 tipos de módulos:
o Web Modules
Unidade instalável (deployable) que contem:
• Servlets
• Páginas JSP
• Bibliotecas de tags JSP
• Ficheiros JAR de biblioteca Java
• Documentos HTML/XML
• Outros recursos (imagens, Ficheiros de classes,
applets, ...)
O Ficheiro é chamado "Web ARchive file" (WAR file)
WAR = Ficheiro JAR mas com directório WEB-INF
contendo um deployment descriptor num Ficheiro web.xml
O servidor J2EE examina o Deployment Descriptor para
saber como tratar o componente ou aplicação
o EJB Modules
Unidade instalável (deployable) que contem:
EJBs
Ficheiros JAR de biblioteca Java
Outros recursos, etc.
O Ficheiro é um Ficheiro JAR mas com deployment
descriptor ejb-jar.xml no directório META-INF
o Java Modules
Um grupo de classes clientes empacotados em Ficheiros JAR
O deployment descriptor de um Java Module está num
ficheiro chamado application-client.xml
Criação, composição e packaging de aplicações
Os módulos podem ser agrupados em aplicações num pacote chamado "EAR file"
(Enterprise ARchive). O deployment descriptor de uma aplicação está num ficheiro
Pág.92
Trabalho de J2EE
Aníbal Manuel e Silva Couto
chamado application.xml. Observe-se que os vários deployment descriptors envolvidos
permitem um melhor reuso dos módulos.
Figura 27 – Esquema applicação J2EE.
Deployment de Aplicações
O Deployment é o processo de instalar e customizar módulos numa plataforma J2EE
Envolve várias etapas:
o Copiar o ficheiro apropriado no servidor de aplicações
o Configurar a aplicação através do deployment descriptor
O deployment descriptor contém informação que pode variar entre
duas instalações
Exemplos: nomes de bases de dados, de tabelas, de campos, papeis
para segurança, etc.
o Deixar o módulo sob controlo de um container;
Isso frequentemente envolve a criação dinâmica de um container
usando uma ferramenta especial
Isso é necessário quando o container está intimamente relacionado
com os componentes do módulo (veremos exemplos adiante)
Pág.93
Trabalho de J2EE
Aníbal Manuel e Silva Couto
5 – Servidores J2EE
Neste ponto vão ser abordados alguns dos servidores J2EE que permitem correr
aplicações deste tipo. Foi minha preocupação focar os servidores que considero serem os
mais importantes, não só pelo facto de serem mais acessíveis e de menor custo, mas
também pela existência de varias referencias bibliográficas que ajudam o utilizador a
interagir mais facilmente com este tipo de servidores.
5.1 - JBoss
JBoss é hoje, sem dúvida nenhuma o servidor de aplicação que mais vem chamando a
atenção no mundo J2EE. Várias características fazem dele uma opção inteligente. Neste
artigo vamos mostrar um pouco de sua história, e falar acerca dos factos mais importantes
deste servidor de aplicação.
O JBoss existe desde 1999. No começo ele começou a ser denominado por EJBoss ou
EJB Open Source Server. Mas por motivos legais, o nome ficou apenas JBoss (que na
minha opinião é muito melhor). Ele é desenvolvido por um equipa de primeira liderado
pelo francês Marc Fleury (estamos a falar do JBoss Group). A nova arquitectura é toda
baseada em JMX (Java Management Extension). Ao contrário da maioria de seus
concorrentes que são implementados em um gigantesco bloco monolítico, o JBoss possui
um microkernel baseado em JMX. Cada componente do servidor de aplicação é um
componente JMX (ou melhor, um MBean). Originalmente criado para efectuar a gestão
redes, o JMX permite o mapeamento de componentes através de nomes. Os componentes
são mapeados por nomes em um servidor de MBeans. A chamada de um método de um
MBean deve ser feita indicando-se o nome do MBean, o nome do método e os parâmetros.
Um pequeno exemplo da vantagem de um servidor de aplicação baseado em JMX e open
source é a facilidade de substituição de um componente.
O Jboss é desenvolvido por uma comunidade open source sob a licença LGPL e está-se
tornando um sério concorrente aos servidores de aplicação comercial. Segundo o site
SourceForge, é efectuado o download mais do que 150 mil vezes por mês!
Pág.94
Trabalho de J2EE
Aníbal Manuel e Silva Couto
O JBoss 4.0 inclui um framework para AOP — Aspect-Oriented Programming — que
permite que a quem desenvolver possa facilmente acrescentar serviços como transacções,
persistência e replicação de cache à partir de objectos Java comuns, sem a necessidade de
criar EJBs. O framework AOP cuida de todo o trabalho de transformar o objecto Java em
um EJB, e libera o developer para se concentrar na lógica de Negócio das aplicações.
O JBoss conquistou em 2002 o prémio da JavaWorld na categoria “Best Java
Application Server”, estando à frente de produtos comerciais cujas licenças custam vários
milhares de euros por CPU.
Como conclusão poderemos referir que os servidores de aplicação J2EE estão a ganhar
um grande impulso devido à produtividade no desenvolvimento de aplicações corporativas
distribuídas que eles permitem, e devido à facilidade que têm no aproveitamento de
sistemas legados e bases de dados relacionais em novas aplicações. Estes servidores estão a
tornar-se numa infra-estrutura da nova geração de aplicações corporativas, seja para
utilização intra-corporação, seja em aplicações B2B e B2C.
Em um cenário em que os executivos de TI têm cada vez maiores restrições
orçamentárias, mas também enormes pressões para resultados cada vez maiores, uma
alternativa de servidor de aplicação open source de grande qualidade caiu como uma luva.
Assim como o Linux, o Apache e outros softwares open source, o JBoss está a tornar-se
parte fundamental nas decisões de TI das grandes corporações.
5.2 - Jakarta Tomcat
O software Tomcat, desenvolvido pela Apache Software Foundation, permite a
execução de aplicações para web. A Sua principal característica técnica é estar centrada na
linguagem de programação Java, mais especificamente nas tecnologias de Servlets e de
Java Server Pages (JSP). Esta abordagem rivaliza, por exemplo, com a usada pela
Microsoft com o ASP (baseada na linguagem Visual Basic).
A Apache Foundation, mais conhecida pelo seu servidor web de mesmo nome, permite,
como no caso do servidor Apache, que o Tomcat seja usado livremente, seja para fins
comerciais ou não.
Pág.95
Trabalho de J2EE
Aníbal Manuel e Silva Couto
O Tomcat está escrito em Java e, por isso, necessita que a versão Java 2 Standard
Edition (J2SE) esteja instalada no mesmo computador onde ele será executado. No entanto,
não basta ter a versão runtime de Java instalada, pois o Tomcat necessita compilar (e não
apenas executar) programas escritos em Java. O projecto Jakarta da Apache Foundation, do
qual o subprojeto Tomcat é o representante mais ilustre, tem como objectivo o
desenvolvimento de soluções código aberto baseadas na plataforma Java.
Este projecto, é um projecto que recebe o apoio de grandes empresas como Sun, IBM,
Netscape, etc.
Pág.96
Trabalho de J2EE
Aníbal Manuel e Silva Couto
5.3. – Websphere
O Webpshere foi lançado pela IBM, e este representa nos dias de hoje uma
plataforma importante para as aplicações e-business de hoje.
Este produto da IBM, é um servidor de aplicações que corre aplicações de vários
tipos e fornece todo o apoio necessário para o desenvolvimento e para correr aplicações de
J2EE.
No Websphere temos várias componentes importantes para o desenvolvimento de
J2EE. Por um lado temos o nosso ambiente para desenvolver uma aplicação J2EE, em que
se usa o Websphere Studio Application Developer, e por outros os servidores de aplicação
(Websphere Aplicattion Server) que servem para correr de uma maneira ideal as nossas
aplicações J2EE ou outro tipos de aplicações.
5.3.1. - Websphere Studio Application Developer
O Websphere Studio Application Developer é uma ferramenta universal, aberta,
portátil, em que a plataforma de integração é baseada na tecnologia do projecto eclipse da
IBM.
O Websphere Studio Application Developer tem tudo que é necessário para a
construção de aplicação J2EE muito eficaz na medida em que tem um ambiente muito fácil
de usar, com muitas componentes diferentes.
Esta aplicação é muito boa quando se fala essencialmente em trabalhar em equipa,
na medida em que podemos ligar a repositórios de CVS (Version Control System), ou seja,
efectuar tratamento das várias versões de um determinado ficheiro(verificar diferenças,
procurar uma versão anterior, entre outros), podemos efectuar diferentes plugins para
acrescentar algumas funcionalidades para melhorar o ciclo de desenvolvimento, entre
outros.
Existe ainda uma vertente do Websphere Studio Application Developer que é a
vertente para Iseries, o Websphere Studio Application Developer para Iseries, acrescenta
algumas funcionalidades como a do Webfacing, que permiter a conversão de aplicações de
OS400,ou seja, converter directamente essas aplicações em aplicações Web de uma forma
muito simples, gerando os respectivos JSP para os respectivos ecrãs de 5250
Pág.97
Trabalho de J2EE
Aníbal Manuel e Silva Couto
seleccionados. A IBM sempre demonstrou uma grande importância em acompanhar o
desenvolvimento dos seu produtos de uma forma muito eficaz e uniforme, e para além
disso demonstrou sempre a preocupação de ficar acompanhado com as novas tecnologias
de hoje em dia, na medida em que o OS400 e o RPG trata-se de talvez de um dos motivos
de maior facturação da IBM e assim de uma maneira muito simples transforma-se o que se
tinha numa tecnologia antiga (ecrãs 5250) numa aplicação Web de acordo com as novas
tecnologias.
Relativamente à construção de uma aplicação J2EE em ambiente Websphere, a
figura a seguir representa a topologia:
Figura 29 – Topologia de uma Aplicação J2EE.
Onde tem um * representa o que pode ser desenvolvido no Websphere Studio
Application Developer.
Para construção de uma aplicação J2EE, como já referi ao longo deste relatório é
necessário efectuar vários passos, para tal, vou demonstrar uma figura que ilustra como o
efectuar no Websphere Studio Application Developer.
Pág.98
Trabalho de J2EE
Aníbal Manuel e Silva Couto
Figura 30 – Construir uma Aplicação J2EE em Websphere.
5.3.2 – Websphere Application Server
O Webpshere Application Server (5.1), disponibiliza uma quantidade de
configurações e opções de desenvolvimento para ajuda ao utilizador na construção de
ambientes distribuídos e altamente dinâmicos para aplicação “stand-alone” ou multi-
servidor.
O suporte para J2EE foi um dos motivos principais para a construção do
Websphere V5. A IBM quer suportar todas as tendências e os padrões enquanto se tornam
disponíveis, e as especificações novas têm as melhorias significativas que a IBM pode usar
aumentar as potencialidades do produto de WebSphere. A especificação de J2EE 1.4
forneceu especificações novas do desenvolvimento. Servlet, JSP, e EJB, adicionou
bibliotecas do API para processar aplicações distribuídas assim como a sustentação
integrada do Messaging.
Pág.99
Trabalho de J2EE
Aníbal Manuel e Silva Couto
6. - CONCLUSÃO
Após a realização deste trabalho, é então altura de fazer uma breve reflexão.
A elaboração deste pequeno trabalho permitiu-me colocar em prática algumas coisas
que apenas tinha uma pequena noção do conceito e que agora pude ver como era o seu
funcionamento.
Deparei-me com algumas dificuldades na escolha do tema, na medida em que, não sabia
como focar este tema da maneira mais lógica e explicá-lo de uma forma simples e sintética
para todos.
No que se refere às referências bibliográficas confesso que existe muito documentação
sobre este tema que de facto é um dos temas do momento, e em que a maioria das
empresas tenta colocá-lo em prática.
De um modo geral, penso ter atingido minimamente os objectivos a que inicialmente
me propus, aquando da realização deste trabalho.
Devo referir que na minha opinião este trabalho mostrou-se bastante enriquecedor, não
só em termos de aquisição de ideias, como também a nível de profissional porque o facto
de ter efectuado um trabalho sobre este tema pode ajudar imenso o meu futuro visto ser o
tema do momento e sobre o qual as empresas procuram mais pessoas com boa formação
sobre o mesmo.
Em suma, quero agradecer a todos que me ajudar a conseguir efectuar este trabalho da
melhor maneira possível, apesar de a realização deste trabalho ocorreu de uma forma um
pouco “atribulada”, devido ao facto de já ter uma vida profissional, e ter pouco tempo para
a realização do mesmo.
Pág.100
Trabalho de J2EE
Aníbal Manuel e Silva Couto
REFERÊNCIAS BIBLIOGRÁFICAS
Martin Bond, Dan Haywood, Debbie Law, Andy Longshaw, Peter Roxburgh - Teach YourSelf J2EE in 21 Days java.sun.com/j2ee/
• java.sun.com/j2ee/white/j2ee_guide.pdf • java.sun.com/j2ee/j2ee-1_4-pfd3-spec.pdf
users.pandora.be/bert.torfs/j2ee.pdf portaljava.com/home/tutoriais/design_patterns_j2ee.pdf www.ucb.br/prg/professores/fgoulart/j2ee_ejb.pdf www.ime.usp.br/~peas/files/TutorialJ2EE.pdf www.lozano.eti.br/palestras/intro-j2ee.pdf http://www.theserverside.com/ www.j2eebrasil.com.br/ www.javacampinas.com.br/palestras/ www.ibm.com www.jboss.org www.javapassion.com/j2eeadvanced/WhatsnewinJ2EE1.44.pdf
Pág.101