realizado por: aníbal manuel e silva couto supervisor ...paf/proj/set2004/i980305 - trabalho...

109
Licenciatura em Engenharia Informática Ramo Computadores e Sistemas Realizado por: Aníbal Manuel e Silva Couto Supervisor: Engº Orlando Sousa Porto, Outubro 2004

Upload: docong

Post on 09-Feb-2019

215 views

Category:

Documents


0 download

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

assim for programado

Pág.36

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