Download - Desenvolvendo aplicações corporativas

Transcript
Page 1: Desenvolvendo aplicações corporativas

UNIVERSIDADE TECNOLÓGICA FEDERAL DO PARANÁDEPARTAMENTO ACADÊMICO DE INFORMÁTICA

ESPECIALIZAÇÃO EM TECNOLOGIA JAVA

ALESSANDER FECCHIO

JAVA EE 5: DESENVOLVENDO APLICAÇÕES CORPORATIVAS

CURITIBA2006

Page 2: Desenvolvendo aplicações corporativas

UNIVERSIDADE TECNOLÓGICA FEDERAL DO PARANÁDEPARTAMENTO ACADÊMICO DE INFORMÁTICA

ESPECIALIZAÇÃO EM TECNOLOGIA JAVA

ALESSANDER FECCHIO

JAVA EE 5: DESENVOLVENDO APLICAÇÕES CORPORATIVAS

Trabalho apresentado como requisito para aobtenção de título de especialista em tecnologiaJava, da Universidade Tecnológica Federal doParaná.Orientadora: Prof. Ana Cristina B. KochemVendramin.

CURITIBA2006

Page 3: Desenvolvendo aplicações corporativas

SUMÁRIO

1 Introdução..................................................................................................................................82 O Java........................................................................................................................................9

2.1 Uma breve história do Java..................................................................................................92.2 Nomenclatura e versionamento do Java ..............................................................................122.3 Conceitos fundamentais da estrutura da plataforma Java .....................................................13

2.3.1 Java é uma linguagem interpretada.............................................................................142.3.2 Edições do Java .........................................................................................................15

3 Visão geral do Java EE..............................................................................................................173.1 Modelo de desenvolvimento do Java EE.............................................................................173.2 Componentes Java EE.......................................................................................................18

3.2.1 Clientes Java EE........................................................................................................193.2.2 Componentes web.....................................................................................................193.2.3 Componentes de negócios..........................................................................................193.2.4 Outros componentes..................................................................................................19

3.3 Containers Java EE...........................................................................................................204 Tecnologias empregadas...........................................................................................................22

4.1 Ambiente de desenvolvimento integrado.............................................................................224.1.1 Utilização de recursos do sistema...............................................................................234.1.2 Aproveitamento do código já desenvolvido...................................................................234.1.3 Adequação do IDE ao tipo de aplicação a ser desenvolvida..........................................244.1.4 Controle de versões...................................................................................................24

4.2 Servidor de aplicações.......................................................................................................244.3 MVC.................................................................................................................................254.4 Banco de dados.................................................................................................................27

4.4.1 MySql........................................................................................................................274.4.2 PostgreSQL...............................................................................................................284.4.3 Derby........................................................................................................................29

5 Uma Aplicação prática da tecnologia Java EE.............................................................................305.1 Ambiente de desenvolvimento............................................................................................31

5.1.1 Pré-requisitos.............................................................................................................315.1.2 Instalação dos software..............................................................................................31

5.2 Integração do NetBeans com o SJSAS...............................................................................325.3 Criação do banco de dados................................................................................................34

5.3.1 Conceitos sobre acesso a bancos de dados no Java....................................................375.4 Configuração do SJSAS.....................................................................................................43

6 Enterprise Java Beans...............................................................................................................466.1 Beans...............................................................................................................................476.2 Session beans...................................................................................................................47

6.2.1 Statefull beans...........................................................................................................476.2.2 Stateless beans..........................................................................................................48

6.3 Interfaces..........................................................................................................................486.4 Anotações.........................................................................................................................496.5 Container para aplicações cliente.......................................................................................496.6 Java Web Start ..................................................................................................................506.7 Contexto...........................................................................................................................506.8 Tipos de arquivo ................................................................................................................516.9 Persistência de dados........................................................................................................516.10 Facades..........................................................................................................................52

7 Uma aplicação simples..............................................................................................................537.1 Session bean.....................................................................................................................537.2 Interfaces..........................................................................................................................537.3 Aplicação cliente................................................................................................................547.4 Construção da aplicação com o NetBeans..........................................................................55

7.4.1 Criação de um projeto................................................................................................567.4.2 Criação do bean.........................................................................................................577.4.3 Programação do bean e das interfaces........................................................................587.4.4 Programação da aplicação cliente...............................................................................58

Page 4: Desenvolvendo aplicações corporativas

7.4.5 Deploy da aplicação...................................................................................................607.4.6 Execução do cliente...................................................................................................61

8 Prova de Conceito - uma aplicação completa..............................................................................628.1 Projeto..............................................................................................................................62

8.1.1 Diagrama de casos de uso..........................................................................................638.1.2 Diagrama de seqüência..............................................................................................63

8.2 Arquivos de configuração...................................................................................................648.3 Módulo EJB.......................................................................................................................65

8.3.1 Criação dos entity beans.............................................................................................658.3.2 Entidade....................................................................................................................698.3.3 Entidades para chaves primárias.................................................................................718.3.4 Criação dos session beans.........................................................................................728.3.5 Persistência...............................................................................................................748.3.6 Interfaces...................................................................................................................75

8.4 Completando a aplicação EJB............................................................................................768.5 Acesso aos EJB num cliente desktop..................................................................................77

8.5.1 Listagem....................................................................................................................778.5.2 Inclusão.....................................................................................................................778.5.3 Pesquisa....................................................................................................................788.5.4 Atualização................................................................................................................788.5.5 Exclusão....................................................................................................................798.5.6 Criação de usuários....................................................................................................79

8.6 Acesso ao EJB numa aplicação web...................................................................................808.7 Documentação..................................................................................................................83

9 Conclusão................................................................................................................................87Referências.................................................................................................................................89Apêndice A - Script para criação das tabelas no banco de dados....................................................91Apêndice B - Módulo EJB.............................................................................................................93Apêndice C - Módulo cliente desktop...........................................................................................113Apêndice D - Módulo aplicativo web............................................................................................119

Page 5: Desenvolvendo aplicações corporativas

LISTA DE FIGURAS

Figura 1: O aparelho Star 7 [JAVA NET].........................................................................................9Figura 2: Versões de Duke - o mascote Java [JAVA NET]..............................................................10Figura 3: Esquema básico de programação, compilação e execução de um programa.....................15Figura 4: Edições do Java e suas máquinas virtuais.......................................................................16Figura 5: Diagrama das camadas do Java EE................................................................................18Figura 6: Tipos de container do Java EE 5 [BALL 2006].................................................................21Figura 7: Inicialização do SJSAS a partir do NetBeans...................................................................32Figura 8: Mensagem de inicialização do Java DB...........................................................................33Figura 9: Mensagem de inicialização do SJSAS.............................................................................33Figura 10: Mensagem indicando que o SJSAS foi iniciado..............................................................33Figura 11: Tela principal do ASADMIN..........................................................................................34Figura 12: Menu para iniciar e parar o Java DB..............................................................................35Figura 13: Mensagem de início do Java DB...................................................................................35Figura 14: Configurações do banco de dados Maxigroupware.........................................................35Figura 15: Nova conexão criada....................................................................................................36Figura 16: Componentes disponíveis na conexão com o banco de dados........................................36Figura 17: Mensagens de criação das tabelas................................................................................37Figura 18: Step 1 of 2 - Criação do pool de conexões.....................................................................41Figura 19: Step 2 of 2 - Propriedades do pool de conexões............................................................41Figura 20: Novo pool criado..........................................................................................................42Figura 21: Criação de um recurso JDBC........................................................................................42Figura 22: Recurso JDBC criado...................................................................................................43Figura 23: Alteração da porta padrão do container web..................................................................45Figura 24: Acesso de um bean por um cliente remoto....................................................................48Figura 25: Criação de uma aplicação Enterprise no NetBeans........................................................56Figura 26: Módulos criados pelo assistente Enterprise Application..................................................57Figura 27: Criação de um session bean no NetBeans.....................................................................57Figura 28: Programas criados pelo assistente de session beans.....................................................58Figura 29: Atualização das interfaces............................................................................................58Figura 30: Criação de uma classe Java simples.............................................................................59Figura 31: Criação de uma nova classe Java .................................................................................59Figura 32: Nova classe criada.......................................................................................................60Figura 33: Diagrama de casos de uso..........................................................................................63Figura 34: Diagrama de seqüência................................................................................................63Figura 35: Arquivos de configuração da aplicação enterprise..........................................................64Figura 36: Criação de entidades a partir do banco de dados...........................................................65Figura 37: Escolha do datasource e das tabelas para criação das entidades...................................66Figura 38: Nomenclatura e empacotamento das entidades.............................................................67Figura 39: Criação da persistence unit...........................................................................................67Figura 40: Entidade criadas no projeto..........................................................................................68Figura 41: Entidades criadas no projeto.........................................................................................69Figura 42: Criação de session beans.............................................................................................72Figura 43: Assistente para criação de session beans......................................................................73Figura 44: Empacotamento e escolha das interfaces a serem criadas.............................................73Figura 45: Session bean e interface criados...................................................................................74Figura 46: Regras de navegação da aplicação web........................................................................81Figura 47: Acesso à ferramenta AutoComment..............................................................................84Figura 48: Ferramenta AutoComment............................................................................................84Figura 49: Geração da documentação...........................................................................................85Figura 50: Mensagem de sucesso ao gerar a documentação..........................................................85Figura 51: Página inicial da documentação....................................................................................86

Page 6: Desenvolvendo aplicações corporativas

LISTA DE SIGLAS

API Application Programming Interface CRUD Create, Recover, Update, Delete CVS Concurrent Version System DBCP Database Connection Pool EAR Enterprise Archive EJB Enterprise Java Beans GCS Gerência de Configuração de Software GPL General Public License GUI Graphic User Interface HTML Hyper Text Meta Language IDE Integrated Development Environment J2EE Java 2 Enterprise Edition J2ME Java 2 Micro Edition J2SE Java 2 Standard Edition JAR Java Archive Java EE 5 Java Enterprise Edition 5 JCE Java Cryptography Extension JDBC Java Database Connectivity JDK Java Development Kit JFC Java Foundation Classes JMS Java Message Service JNDI Java Naming and Directory JPA Java Persistence API JSF Java Server Faces JSP Anúncio da tecnologia Java Server Pages JVM Java Virtual Machine JWS Java Web Start LCD Liquid Crystal Display MVC Model-View-Controller PCMCIA Personal Computer Memory Card International AssociationPDA Personal Digital Assistant SJSAS Sun Java System Application Server UML Unified Modeling LanguageWAR Web Archive WSDP Java Web Services Developer Pack

Page 7: Desenvolvendo aplicações corporativas

RESUMO

O desenvolvimento de aplicações corporativas utilizando a versão enterprise do Java sempre foi

considerada de grande complexidade, entre outros motivos pela grande quantidade e pela extensão

de seus arquivos de configuração. Uma vez que a especificação Java deixa em aberto a possibilidade

de cada fornecedor implementar suas próprias características aos servidores de aplicação, os

arquivos de configuração acabam por não seguir um padrão. A versão enterprise do Java, chamada

de Java EE 5, tem por objetivo simplificar o desenvolvimento de aplicações e abstrair os

desenvolvedores da complexa configuração dos servidores. O objetivo deste trabalho é demonstrar a

utilização da tecnologia Java EE 5 para o desenvolvimento de aplicações corporativas. O documento

inclui demonstrações de uso dos principais tópicos relacionados à tecnologia, como persistência de

dados, EJB, aplicações cliente desktop e web, bem como a utilização de servidores de aplicação

Java. Com isto, espera-se desmitificar a idéia de que o desenvolvimento em Java EE 5 é uma tarefa

árdua mesmo para desenvolvedores experientes.

Palavras-chave: Java, EJB, enterprise, persistência de dados, servidor de aplicações.

Page 8: Desenvolvendo aplicações corporativas

8

1 INTRODUÇÃO

O Java é considerado como um dos maiores fenômenos da informática em todos os

tempos, pela velocidade com que novos recursos são criados e disponibilizados para a comunidade

de desenvolvedores e usuários.

Nascida inicialmente como uma linguagem de programação para atender a um nicho de

mercado, o Java hoje é utilizado em aplicativos de todos os tipos, e também embarcado em milhares

de aparelhos ao redor do mundo.

É possível encontrá-lo em pequenos aplicativos ou utilitários, complexos sistemas

corporativos , ou em processadores de computadores de bordo de automóveis, por causa de sua

fantástica flexibilidade. Esta flexibilidade peculiar à linguagem fez com que ela se desenvolvesse

muito rapidamente, gerando outras tecnologias dela dependentes, como por exemplo os servidores

de aplicação.

Se por um lado esta gama de tecnologias ajudou a resolver problemas dos mais

diversos, por outro lado criou duas dificuldades aos profissionais de informática: a escolha da melhor

tecnologia a ser adotada, e no caso de escolher mais de uma, como integrá-las da maneira mais

eficaz.

As questões inerentes à integração destes componentes não são fáceis de responder.

Muitas empresas, pelos mais diversos motivos, optam por utilizar apenas uma tecnologia para

desenvolver toda sua aplicação. Mas nem sempre isto é possível num cenário onde se desenvolvem

aplicações que precisam ser executas em ambientes distintos, como web , estações de trabalho e

dispositivos móveis.

Tem-se então o problema da interoperabilidade. Apesar da padronização Java ser muito

rígida, e de tecnologias específicas para um ambiente (como o desktop, também chamado de estação

de trabalho) serem capazes de se comunicar com outras (como a internet), nem sempre a

comunicação é simples.

O objetivo deste trabalho é demonstrar como estas tecnologias podem ser integradas,

fornecendo maneiras de criar um ambiente robusto, ágil e seguro para a disponibilização de

aplicações corporativas.

Page 9: Desenvolvendo aplicações corporativas

9

2 O JAVA

2.1 UMA BREVE HISTÓRIA DO JAVA

O ano era 1991. O local, um pequeno escritório localizado na rua Sand Hill Road, em

Menlo Park. Lá, um grupo de treze pessoas liderado por James Gosling, Patrick Naughton e Mike

Sheridan isolou-se da Sun Microsystems e trabalhou arduamente num projeto secreto conhecido

apenas pelo codinome Green Project [JAVA]. O grupo, conhecido por Green Team, tinha a função de

antecipar e planejar o que estava por vir na área da computação. Eles acreditavam que um ponto

importante nesta evolução seria a convergência entre computadores e dispositivos pessoais comuns

(como geladeiras, por exemplo).

O resultado apareceu dezoito meses depois, na forma de um controlador de dispositivos

(uma espécie de controle remoto), através do qual um usuário poderia controlar sua geladeira, sua

torradeira, sua TV a cabo, e quaisquer dispositivos prontos para a tecnologia.

Conforme ilustra a Figura 1, o aparelho desenvolvido, conhecido como *7 (Star 7), era

uma handheld wireless, utilizando um processador SPARC, com tela Liquid Crystal Display (LCD)

colorida de 5 polegadas touchscreen, rede de 900 MHz, Personal Computer Memory Card

International Association (PCMCIA), codecs de áudio e vídeo. O aparelho tinha um novo

gerenciamento de energia e, para controlar tudo isso, uma versão do UNIX era executada em menos

de 1 MB de RAM – inclusive os drivers [JAVA NET].

Figura 1: O aparelho Star 7 [JAVA NET]

Page 10: Desenvolvendo aplicações corporativas

10

Segundo os responsáveis pelo projeto, o Star 7 também possuía

“...a new small, safe, secure, distributed, robust, interpreted, garbage collected, multi-threaded,

architecture neutral, high performance, dynamic programming language...” [JAVA NET]

Ou, numa tradução livre:

“...uma linguagem de programação pequena, segura, distribuída, robusta, interpretada, com

memória auto-gerenciada, multi-threaded, de arquitetura neutra, de alto desempenho e

dinâmica...”

Esta linguagem foi batizada de Oak (carvalho, em inglês) - uma árvore que James

Gosling podia ver de sua janela, enquanto trabalhava.

Um segundo produto nasceu daquela equipe: um cartoon, criado e desenhado por Joe

Palrang, chamado Duke (ver Figura 2). Duke era o assistente utilizado para o Star 7 , e sua função era

ensinar o usuário a utilizar os recursos do equipamento. Com o fim do produto e o tempo passando,

acabou se transformando no mundialmente mascote Java [JAVA NET].

Figura 2: Versões de Duke - o mascote Java [JAVA NET]

O Star 7 carecia de um nicho de mercado onde poderia ser inserido. Inicialmente, a

equipe pensou que uma boa idéia seria controlar vídeo sob demanda através da TV a cabo e para

isso, chegou a construir um protótipo.

O grande problema era que a indústria de TV a cabo não tinha como oferecer o que o

Star 7 podia controlar. Nem mesmo infraestrutura existia e seria caríssimo para que apenas um grupo

de empresas a construísse. Ironicamente, o vídeo sob demanda e o controle da televisão digital é

hoje uma realidade no mundo, e tanto a Oak como o Star 7 estavam fadados ao desaparecimento.

Entretanto, um fato viria a mudar este aparente fracasso para uma das mais

estrondosas vitórias do mundo da informática: a internet.

A rápida evolução da internet fez com que uma imensa infraestrutura de

telecomunicações e transmissão de dados fosse disponibilizada, calcada inicialmente na malha de

cabos e fios das empresas de telecomunicações. A infraestrutura que declarou o fim do Star 7,

repentinamente fora criada.

Page 11: Desenvolvendo aplicações corporativas

11

James Gosling, foi novamente incumbido de um projeto, dessa vez de preparar a Oak

para a internet. Em 1995, ele conclui seu trabalho, lançando uma nova versão do Oak , rebatizada de

Java [WIRED].

Java foi inteiramente desenvolvida para atuar em ambientes heterogêneos, como o da

internet. Assim, Java poderia ser executado diretamente nos browsers (navegadores de internet), na

forma de applets1. Os browsers, que antes eram limitados a um conteúdo estático, podiam agora

exibir também conteúdo dinâmico. Isso fez com que o Java crescesse como nenhuma outra

linguagem de programação cresceu na história da informática, rapidamente sendo alçado à categoria

de plataforma [WIKIPEDIA 01].

Dez anos depois, não só a linguagem, mas toda a plataforma evoluiu muito, e alguns

números bem interessantes podem mostrar este crescimento [JAVA 01]:

• 4 milhões de desenvolvedores ao redor do mundo;

• mais de 700 milhões de computadores;

• mais de 700 milhões de celulares e outros dispositivos;

• mais de 1 bilhão de smart cards;

• impressoras, web cams, jogos, sistemas de navegação de automóveis e muitos

outros.

Hoje, o Java pode ser encontrado na internet, em computadores, laptops e telefones

celulares, e em equipamentos onde as pessoas nem imaginam, como geladeiras, fornos de

microondas e cartões de crédito.

A linha do tempo da Tabela 1 demonstra sua evolução.

Ano Fato

1991 • Lançamento do Green Project

1992 • Lançamento da linguagem Oak, do Star7 e do Duke

1994 • Lançamento do WebRunner, o primeiro navegador a suportar conteúdo

dinâmico

1995 • Nascimento do Java. Pai: James Gosling. Mãe: Sun Microsystems;

• Anúncio oficial na SunWorld.

1996 • Lançamento do Java Development Kit (JDK) 1.0;

• Primeira JavaOne (conferência de desenvolvedores);

• JavaBeans , Servlets e outras tecnologias anunciadas;

• Application Programming Interface (API) Java Card anunciada.

1 Um applet é um programa escrito em Java, embutido numa página web (dinâmica ou estática), que é executado na JVM daestação cliente.

Page 12: Desenvolvendo aplicações corporativas

12

Ano Fato

1997 • Lançamento do JDK 1.1;

• Lançamento do Java Servlet Developers Kit;

• Anúncio da tecnologia Enterprise Java Beans (EJB);

• Inclusão da tecnologia Java Foundation Classes (JFC) na plataforma Java.

1998 • Anúncio das JFC/"Project Swing";

• Visa lança o primeiro smart card com tecnologia Java Card;

• Lançamento do Java 2 para Linux;

• Lançamento da plataforma Java 2.

1999 • Liberação do código fonte da plataforma Java 2;

• Anúncio da tecnologia Java Server Pages (JSP);

• Divisão oficial da plataforma Java 3 edições: Java 2 Standard Edition (J2SE),

Java 2 Enterprise Edition (J2EE), Java 2 Micro Edition (J2ME);

• Liberação da plataforma J2EE;

• Liberação da plataforma J2SE para Linux.

2000 • Liberação da plataforma J2SE 1.3;

• Liberação da plataforma J2SE 1.3 para Apple Mac OS X.

2001 • Liberação da Java Web Start 1.0.

2002 • Lançamento do JDK 1.4;

• Lançamento do Java Web Services Developer Pack (WSDP);

• Lançamento da J2EE 1.4 Beta.

2004 • Lançamento do Java 5.0.

2005 • Java – 10º aniversário;

• Aproximadamente 4,5 milhões de desenvolvedores utilizam Java.

2006 • Lançamento do Java Enterprise Edition 5 (Java EE 5), nova versão do J2EE

Tabela 1: Evolução da plataforma Java. [JAVA 02]

2.2 NOMENCLATURA E VERSIONAMENTO DO JAVA

Como é possível notar na Tabela 1, com o lançamento da versão 5 do Java, houve uma

grande mudança em sua nomenclatura, e a compreensão destes nomes e acrônimos torna-se

necessária para o completo entendimento da estrutura do Java.

Page 13: Desenvolvendo aplicações corporativas

13

As edições do Java (discutidas na seção 2.3.2) foram lançadas em 1999, pouco tempo

depois do lançamento do Java 2. O próprio nome Java 2 na realidade não se refere à versão 2 do

Java, e sim à versão 1.2. Esta estranha alteração de nome foi feita como uma jogada de marketing,

para mostrar que a linguagem havia sido radicalmente alterada, da sintaxe de alguns comandos até a

estrutura interna da Java Virtual Machine (JVM). Assim, havia o JDK 1.2 e o JRE 1.2 que eram a base

do Java 2. Esta diferença entre a versão do software e a versão da linguagem gerava muita confusão.

Em 2004, o Java 5 foi lançado, e com ele o novo padrão de nomenclatura, desta vez

bem simplificado. A comunidade pôde participar da definição da nomenclatura, e junto com o

departamento de marketing da Sun, chegaram à conclusão que o melhor caminho para a

simplificação seria simples: tirar o 2 e expandir o acrônimo.

Não existe Java 3 e nem o Java 4. A versão passou diretamente da versão 2 para a 5. O

motivo é simples: existe um número de versão utilizado internamente pela Sun e existe o nome

comercial. A versão utilizada internamente pela Sun atualmente é a 1.5. Para sincronizar a versão

interna com a versão comercial, optou-se por retirar a expressão "1." da versão comercial, gerando

assim o Java 5.

Oficialmente, a partir de junho de 2005, a nova nomenclatura foi adotada, sendo que de

imediato, as seguintes alterações foram realizadas:

• J2SE 6.0 foi chamado de Java SE 6 e J2SE 7.0 será chamado de Java SE 7,

quando lançado;

• J2EE 5.0 foi chamado de Java EE 5;

• J2ME foi chamado de Java ME, pois não tem um número de versão.

Outro ponto importante do versionamento é que versões intermediárias do software não

mais serão lançadas, somente serão disponibilizadas versões para correção de erros. Novos recursos

e implementações serão sempre lançadas com as versões principais (Java 6, etc).

2.3 CONCEITOS FUNDAMENTAIS DA ESTRUTURA DA PLATAFORMA JAVA

Para se entender a plataforma Java, é necessário primeiro conhecer sua estrutura.

Por definição, plataforma é “um ambiente de hardware ou software no qual um

programa é executado” [JAVA 03]. Java é uma plataforma apenas de software, sendo executada

numa outra plataforma, composta de hardware e software (o sistema operacional, dependente do

hardware onde é executado).

Page 14: Desenvolvendo aplicações corporativas

14

A plataforma Java é composta de duas partes:

• A JVM, responsável pela execução dos programas;

• A Java API, conjunto de classes responsáveis por prover os mais diversos recursos,

como acessar bancos de dados.

2.3.1 Java é uma linguagem interpretada

O Java segue a filosofia Write Once, Run Everywhere (Escreva uma vez, execute em

todos os lugares). Um programa escrito em Java puro pode ser executado em todas as plataformas

disponíveis, do desktop ao mainframe.

Para que seja executado em todas as plataformas, o programa Java depende da JVM,

ou seja, Java é uma linguagem interpretada. O diferencial para as linguagens interpretadas mais

conhecidas (como o antigo BASIC), é que a VM não interpreta o programa original.

Ao ser compilado, um programa Java gera um código intermediário, que não é um

programa fonte, nem um executável. Este código intermediário – chamado de byte code – é que pode

ser interpretado pela VM [JAVA 03]. Como a execução do byte code depende apenas da VM,

qualquer sistema operacional que tenha uma VM pode executá-lo sem precisar ser reescrito. Por isto,

Java é considerado multi plataforma.

O processo pode ser melhor compreendido através da Figura 3.

Page 15: Desenvolvendo aplicações corporativas

15

Figura 3: Esquema básico de programação, compilação e execução de um programa

O fato de ser interpretado, fez com que o Java fosse conhecido como uma linguagem

lenta, de baixo desempenho. Atualmente, os avanços da informática e o empenho dos especialistas

da Sun em otimizar este componente conseguiram tornar o Java quase tão rápido quanto o C++,

embora essa afirmação seja fonte de muitas discussões em listas e fóruns na internet.

Existem três tipos de VM:

• Java Card VM, utilizada em smart cards [JAVA CARD];

• KVM, utilizada em dispositivos móveis como celulares e Personal Digital Assistant

(PDA) [KVM];

• JVM, utilizada em computadores e alguns tipos de dispositivos móveis [JVM].

Cada uma das VMs tem como base uma tecnologia diferenciada, formada por uma ou

mais API. Por exemplo: a KVM utiliza a API para dispositivos móveis.

2.3.2 Edições do Java

Uma edição do Java é uma versão da plataforma que contém os recursos necessários

para atender um determinado segmento do mercado. Cada edição é formada por dois conjuntos de

API. Um deles é chamada de core, sendo o conjunto de bibliotecas que deve ser suportada por todas

as implementação compatíveis com a edição. O outro é opcional, sendo fornecido com a edição, e

Page 16: Desenvolvendo aplicações corporativas

16

pode ou não ser implementado por uma edição compatível. Opcionalmente, os pacotes adicionais

podem se tornar parte do core, se houver demanda do mercado.

O objetivo é que as classes que pertencem ao core estejam disponíveis em todos os

sistemas operacionais que possam executar o Java. Portanto, se um programa utiliza apenas as

classes do core, ele é 100% portável, podendo ser executado em qualquer plataforma.

Existem três edições do Java:

• Java ME : utilizada em dispositivos móveis, normalmente com pequeno poder de

processamento, como celulares, PDAs e impressoras, entre outros. Oferece

funcionalidades que vão desde criar interfaces simples até protocolos complexos de

rede, passando por um robusto modelo de segurança [JAVA ME];

• Java SE : utilizada para desenvolver e distribuir aplicativos em desktops e

servidores. Com ela também é possível desenvolver software embarcado e para

ambientes de real-time. Além disso, contém a base para o Java EE [JAVA SE];

• Java EE : utilizada para o desenvolvimento de aplicações corporativas, de grande

porte, executadas num servidor. É formada pelo Java SE e um conjunto de

bibliotecas complementares, e provê serviços como web services, modelos de

componentes, API para gerenciamento e mensagens, entre outros recursos. É a

edição utilizada para o desenvolvimento deste trabalho [JAVA EE].

A Figura 4 demonstra as edições do Java, e a JVM utilizada por cada uma delas.

Figura 4: Edições do Java e suas máquinas virtuais

Page 17: Desenvolvendo aplicações corporativas

17

3 VISÃO GERAL DO JAVA EE

O Java EE é a edição mais abrangente do Java, pois engloba todas as tecnologias para

desenvolvimento em ambientes de servidor e desktop.

No desenvolvimento deste trabalho, é utilizado o Java EE 5, nova versão da plataforma

corporativa do Java. O grande objetivo dessa versão é simplificar o desenvolvimento de aplicações

corporativas, sem entretanto alterar os recursos disponíveis na versão 1.4.

As principais alterações do Java EE 5 em relação a sua versão anterior são [JAVA EE]:

• Uso de annotations (anotações), que insere grande parte das configurações da

aplicação dentro do próprio código;

• A versão 3.0 do EJB foi bastante simplificada;

• Java Server Faces (JSF), um poderoso framework que possibilita o uso de

componentes similares aos de Graphic User Interface (GUI) em aplicações web;

• Tecnologia de web services simplificada;

• Java Persistence API, uma camada de persistência objeto-relacional que pode ser

utilizada também fora do contexto Java EE 5.

3.1 MODELO DE DESENVOLVIMENTO DO JAVA EE

O Java EE utiliza um modelo de múltiplas camadas para aplicações corporativas. Uma

aplicação é dividida em componentes de acordo com sua função, e os componentes podem ser

instalados em vários servidores, de acordo com a camada:

• Componentes da camada cliente são executados na estação cliente;

• Componentes da camada web são executados no servidor Java EE;

• Componentes da camada de negócios são executados no servidor Java EE;

• Componentes da camada de sistemas de informação (normalmente um banco de

dados) são executados num servidor próprio.

A Figura 5 mostra um diagrama das camadas do Java [BALL 2006].

Page 18: Desenvolvendo aplicações corporativas

18

Figura 5: Diagrama das camadas do Java EE

3.2 COMPONENTES JAVA EE

Aplicações Java EE são formadas por componentes. Componentes são unidades de

software funcionais e independentes, cujas classes e arquivos se comunicam com outros

componentes. A especificação Java define três componentes [BALL 2006]:

• Clientes Java EE;

• Java Servlets e JSP, que são componentes web da aplicação;

• Enterprise Java Beans, que são componentes de negócios.

Cada um destes componentes pode acessar qualquer tecnologia Java disponível no

servidor Java EE (ou em um container, se for o caso). Uma descrição dos três componentes é

apresentada a seguir.

3.2.1 Clientes Java EE

Os clientes Java EE são executados na estação de trabalho, e são divididos em dois

tipos:

Page 19: Desenvolvendo aplicações corporativas

19

• Aplicações desktop, que podem ter uma GUI ou uma interface por linha de

comando. Podem interagir com os componentes de negócio, acessando-os direta

ou indiretamente (por meio de conexões HTTP);

• Um conjunto de navegador web e applet.

3.2.2 Componentes web

Os componentes web são executados no servidor (que pode ser um servidor Java EE

ou simplesmente um container JSP).

Há dois tipos de componentes web:

• Java Servlets: classes que recebem uma requisição e a processam dinamicamente,

gerando conteúdo HTML como saída;

• JSP: documentos texto plano, que são executados no servidor.

3.2.3 Componentes de negócios

Os componentes de negócio são executados no servidor Java EE, e contêm as regras

de negócio da aplicação. Entre outras funções, acessam bancos de dados, processam dados e os

reenviam, para os clientes ou para o próprio banco de dados. São os Enterprise Java Beans.

3.2.4 Outros componentes

Existe ainda um outro tipo de componente, chamado Java Bean, que não é considerado

um componente Java EE. Normalmente eles são utilizados para controlar o fluxo de dados entre uma

aplicação cliente e os componentes no servidor. Java Beans possuem propriedades e métodos get e

set para acessá-los. Utilizados desta maneira, são fáceis de implementar, mas devem seguir a

especificação Java quanto à nomenclatura utilizada.

3.3 CONTAINERS JAVA EE

Cada tecnologia disponível no servidor Java EE deve ser executada em um container.

Um container é um pequeno servidor dentro do servidor Java EE, especializado em um determinado

serviço. Por extensão, um servidor Java EE pode ser considerado um conjunto de containeres.

O mais famoso exemplo de container é o Tomcat, muitas vezes chamado de servidor

JSP [TOMCAT]. Na realidade, ele é um container responsável pela execução de Servlets e JSP.

Ficou tão conhecido como servidor por ser um bom substituto aos tradicionais servidores Java EE,

Page 20: Desenvolvendo aplicações corporativas

20

complexos de administrar e grandes consumidores de recursos de hardware. Ele tornou-se o padrão

de fato em containeres JSP, sendo utilizado atualmente por grande parte dos servidores Java EE do

mercado.

Quando uma aplicação é desenvolvida, seus módulos devem ser empacotados e

distribuídos para seus respectivos containeres. Empacotamento é o processo pelo qual todos os

programas, bibliotecas e arquivos de configuração são colocados num único arquivo compactado

chamado package [BALL 2006]. Uma das funções do servidor Java EE é receber o pacote e distribuir

cada módulo para seu respectivo container.

Uma vez que o container é dependente do servidor Java EE e não da aplicação, um

componente pode se comportar de maneiras diferentes, de acordo com a configuração do container.

Um exemplo: um EJB distribuído para um servidor Java EE de testes e também para um de

produção. Com os servidores configurados para acessar bancos de dados diferentes, o EJB

acessaria diferentes informações, sem que precisasse ser alterado.

Os tipos de container do Java EE são (ver Figura 6):

• Container EJB: executa os EJB. O container, por sua vez, é executado dentro do

servidor Java EE;

• Container web: executa JSP e servlets. É executado dentro do servidor Java EE;

• Container da aplicação cliente: é executado na estação cliente, e é responsável

pela execução de aplicações desktop;

• Container applet: executa os applets carregados em navegadores web, na estação

cliente. Normalmente, é formado pelo navegador e um plugin Java.

Page 21: Desenvolvendo aplicações corporativas

21

Figura 6: Tipos de container do Java EE 5 [BALL 2006]

Page 22: Desenvolvendo aplicações corporativas

22

4 TECNOLOGIAS EMPREGADAS

O que é mostrado a partir deste ponto é uma prova de tecnologia utilizando os principais

recursos da plataforma Java EE de maneira integrada. O foco não é a linguagem de programação em

si, embora em alguns momentos a discussão de alguns pontos seja necessária. O objetivo principal é

demonstrar como realizar a integração entre componentes distribuídos por plataformas tão diferentes

, como o desktop e um container EJB.

A seguir, são discutidos todas as tecnologias e software necessários à aplicação, e os

motivos pelos quais são utilizados neste trabalho.

4.1 AMBIENTE DE DESENVOLVIMENTO INTEGRADO

Todo desenvolvedor tem preferência por algum Integrated Development Environment

(IDE), seja porque consome menos memória, possui mais recursos, ou porque geram

automaticamente quase a totalidade do código. Também existem desenvolvedores que não utilizam

IDEs, preferindo editores mais simples, que normalmente não geram código automaticamente.

IDE é um aplicativo que agrega várias ferramentas com o único objetivo de desenvolver

software . A maioria dos IDE possui ferramentas que permitem:

• Editar o código fonte e formatá-lo dentro de padrões próprios ou definidos pelo

usuário;

• Automatizar tarefas repetitivas, como gerar os pacotes de distribuição da aplicação;

• Compilar, executar, testar e depurar o código;

• Navegar pela estrutura do projeto;

• Verificar erros de digitação e possíveis erros de compilação, propondo soluções

alternativas;

• Integrar-se com ferramentas externas, como versionadores, servidores de aplicação

e utilitários de construção e distribuição;

• Refactoring (propagação das alterações efetuadas em um componente para todas

as suas ocorrências no projeto – por exemplo, renomear uma classe);

• Auditoria e otimização do código, para garantir a aderência a padrões e convenções

de mercado;

Page 23: Desenvolvendo aplicações corporativas

23

• Suporte a plugins (extensões), componentes normalmente desenvolvidos por

terceiros, que podem adicionar funcionalidades ainda não existentes no IDE.

O processo de escolha de um IDE não deve considerar apenas os aspectos técnicos.

Um ferramenta, apesar de ser tecnicamente a melhor, pode não ser a mais adequada ao trabalho

desenvolvido. São comuns os casos de desenvolvedores que utilizam mais de um IDE, cada qual

com características únicas. Além das especificações técnicas, algumas características operacionais

também devem ser analisadas. Algumas delas são listadas a seguir.

4.1.1 Utilização de recursos do sistema

O IDE não deve consumir exageradamente os recursos do sistema, como memória. Isso

diminui a produtividade, pois desde o acesso aos menus do aplicativo até o processo de compilação o

IDE é prejudicado com a perda de desempenho.

4.1.2 Aproveitamento do código já desenvolvido

Um problema muito comum ao adotar uma nova ferramenta de desenvolvimento é que o

código desenvolvido com a ferramenta antiga não funciona como esperado no novo IDE. O problema

neste caso não é o código (que continua sendo executado sem erros), mas a maneira como os IDE

geram o código, que nem sempre é compreendido por outros IDE. Isto acontece porque cada

ferramenta possui um padrão de geração de código.

A grande dificuldade em migrar programas de uma ferramenta para outra não está no

que se vê, e sim no que não se vê. Quando um IDE abre uma classe para edição, realiza-se também

uma série de verificações, que vão desde o classpath da aplicação até a busca por erros de

compilação e dependências.

Adicionalmente, nos arquivos que possuem um editor gráfico (caso das GUI), é feito

também uma análise da estrutura do programa, que busca identificar como o código fonte pode ser

transformado em elementos visuais. Se esta estrutura estiver incorreta, o IDE não a reconhecerá, não

podendo executar o editor visual, embora o programa seja executado sem problemas.

Existe outro fator complicador: muitas vezes, as ferramentas disponibilizam recursos

que não são padrão no Java. Um bom exemplo são os gerenciados de layout . O SpringLayout , por

exemplo, não é implementado por nenhum IDE de mercado atualmente. O IDE que mais se aproxima

de uma implementação é o NetBeans, com o Matisse – gerenciador baseado no SpringLayout .

Alguém que desenvolva uma aplicação utilizando o Matisse não pode editá-la em nenhum IDE que

não seja o NetBeans.

Page 24: Desenvolvendo aplicações corporativas

24

4.1.3 Adequação do IDE ao tipo de aplicação a ser desenvolvida

Ao desenvolver aplicativos para um determinado ambiente, é natural que a ferramenta

escolhida para seu trabalho deva possuir recursos adequados à plataforma.

Como exemplo, o IDE Java Studio Creator , da Sun, foi criado especificamente para o

desenvolvimento de aplicações para a internet. Se o foco for desenvolver aplicativos para telefones

celulares, o NetBeans oferece grande quantidade de recursos (desde que a extensão apropriada seja

instalada). Já o principal nicho de utilização do JDeveloper - a té sua versão 9 – era o

desenvolvimento de aplicações corporativas que utilizassem o banco de dados Oracle.

Para o desenvolvimento deste trabalho optou-se pela utilização do IDE NetBeans, na

versão 5.5 - projeto de código aberto mantido pela Sun. A escolha se deve ao fato do NetBeans ser

compatível com o tipo de aplicação desenvolvida, sendo um dos únicos com suporte completo ao

desenvolvimento de EJB na versão 3.0. Além de possuir um equilibrado conjunto de ferramentas,

como desenvolvimento de diagramas UML e monitoramento de memória.

Existe também a questão mercadológica. A Sun é a principal patrocinadora do

NetBeans, e todas as suas outras ferramentas de desenvolvimento são nele baseados. Precisando

popularizar o NetBeans (e conseqüentemente seus outros IDE), a Sun une esforços no sentido de

dotá-lo de recursos visando a facilidade de uso e o baixo consumo de recursos.

4.1.4 Controle de versões

Praticamente todos os IDEs de hoje possuem um pequeno gerenciador de versões, o

suficiente para desenvolvimento de pequenas aplicações. Entretanto, quando o desenvolvimento de

software é feito em grandes equipes, é necessário que o controle de versões seja centralizado. Para

isso, utiliza-se aplicativos de Gerência de Configuração de Software (GCS).

É desejável que a ferramenta utilizada possa ser integrada com algum software de GCS.

Normalmente isso não é considerado um problema, uma vez que praticamente todos os IDEs são

compatíveis pelo menos com o Concurrent Version System (CVS), um software livre de GCS que está

entre os mais utilizados no mundo [SAVANNAH].

4.2 SERVIDOR DE APLICAÇÕES

Muitas vezes os desenvolvedores se deparam com um dos grandes problemas do

desenvolvimento Java: a compatibilidade entre as ferramentas disponíveis no mercado. Este

problema é ainda maior quando se trata de uma tecnologia nova, como o Java EE 5. Não pela

tecnologia em si, mas pelo suporte que as ferramentas de desenvolvimento dão a ela.

Page 25: Desenvolvendo aplicações corporativas

25

Como exemplo, é possível citar o servidor de aplicações. No início do desenvolvimento

deste trabalho, apenas o GlassFish e o Sun Java System Application Server (SJSAS) tinham suporte

completo à especificação Java EE 5 - e isto porque o SJSAS é baseado no GlassFish. Outros

servidores são compatíveis apenas com alguns dos novos recursos da especificação.

A seguir, são apresentados os principais motivos pela escolha do SJSAS para o

desenvolvimento deste trabalho [GLASSFISH]:

• É homologado pela Sun, dando suporte completo à especificação Java EE 5;

• Consome poucos recursos do equipamento onde é executado, por não implementar

recursos avançados de gerenciamento, como clustering e computação em grade;

• Foi desenvolvido especialmente para a versão 5 do Java, tirando proveito de todos

os novos recursos da linguagem;

• Fácil administração;

• É gratuito para ambientes de desenvolvimento e produção.

Um dos problemas causados pelo pioneirismo da implementação da especificação é

que não existe ainda uma grande comunidade de desenvolvedores, de modo que o suporte em caso

de problemas nem sempre é rápido.

4.3 MVC

MVC é o acrônimo de Model-View-Controller , uma arquitetura de software que separa

as camadas de modelo de dados (Model ), interface com o usuário (View) e lógica de negócio

(Controller), de modo que as alterações em uma camada causem o menor impacto possível nas

outras [SUNONE].

A camada do modelo é onde os processamentos são realizados, desde cálculos de

impostos sobre as vendas até a verificação se uma data é válida. Embora pelo padrão MVC não

exista uma camada específica para o acesso ao banco de dados, estas operações são implicitamente

realizadas pela camada do modelo.

A camada de visualização é responsável por transformar as informações do modelo em

componentes visuais, de modo que o usuário possa compreendê-las, como uma lista dos filmes

melhor avaliados de uma vídeo locadora.

Na camada de controle, as ações ordenadas pelo usuário na camada de visualização

são interpretadas pela aplicação, indicando qual ação da camada do modelo deve ser executada.

Page 26: Desenvolvendo aplicações corporativas

26

Esta separação garante certa independência entre as camadas, pois um elemento

nunca está presente em duas camadas distintas. Por exemplo, pode-se garantir que uma atualização

no banco de dados seja realizada unicamente na camada de modelo. Desta maneira, no caso de

alguma alteração no banco de dados, apenas um ponto da aplicação deve ser alterado. Do mesmo

modo, caso uma tela seja alterada na camada de visualização, ela em nada influencia nas demais

camadas.

Este padrão de arquitetura provocou o surgimento dos frameworks, software

construídos para fornecer infraestrutura a outros software. Eles são criados para que os

desenvolvedores possam se preocupar com os requisitos da aplicação a ser desenvolvida, e não com

a infraestrutura necessária para ele. Por exemplo, numa aplicação de comércio eletrônico, o

desenvolvedor deve estar focado em como um pedido deverá ser finalizado, e não em como navegar

sem erro entre as páginas – decisão tomada pela camada de controle.

Ultimamente, o padrão MVC tem sido fortemente empregado em aplicativos para a web ,

onde a complexidade pde desenvolvimento é maior que em ambientes cliente-servidor. Por este

motivo, várias implementações distintas apareceram, inclusive no ambiente Java. Duas delas

despontam como as mais utilizadas: Struts (mais antiga e mais utilizada, atuando no nível de páginas)

e JSF (atua no nível de componentes) [PLUGMASTERS].

O Struts é um projeto da Fundação Apache. É uma camada de controle MVC baseada

unicamente em tecnologias padrão Java além de várias bibliotecas da família Commons.

Seu ponto forte é o componente de controle, sendo facilmente integrado a outras

tecnologias, de modo a prover as camadas de modelo e visualização. Na camada de modelo, pode

interagir com tecnologias como JDBC, EJB e camadas de persistência como o Hibernate. Sua

camada de visualização pode ser construída utilizando JSP, JSF ou outros frameworks de

apresentação [STRUTS].

JSF é uma especificação aberta, que pode ser implementada por qualquer pessoa ou

empresa. De fato, além da implementação de referência da própria Sun (mantenedora da

especificação), a Fundação Apache também possui uma implementação chamada MyFaces.

Este framework está ganhando muitos adeptos, entre outros motivos por possuir uma

configuração mais simplificada que os demais frameworks disponíveis hoje. Mas existe outro ponto

que o diferencia dos demais. Desde o início de seu projeto, o objetivo do JSF sempre foi tratar cada

parte da aplicação como um componente, que por sua vez atende a todo o modelo de

desenvolvimento Java, como por exemplo o tratamento de eventos, que podem ocorrer até mesmo

dentro de uma página JSP, com a diferença de que este evento é disparado no servidor, e não no

cliente.

Page 27: Desenvolvendo aplicações corporativas

27

Para que os componentes de visualização (como listas, botões e caixas de texto)

pudessem tirar proveito desta característica, eles passaram a ser desenhados no servidor, e não mais

pelo navegador web . Todos os componentes do Hyper Text Meta Language (HTML, a linguagem

utilizada para se construir páginas da internet) foram substituídos por componentes JSF.

Por estas características, o JSF foi utilizado para o desenvolvimento deste trabalho,

utilizando a implementação de referência da Sun.

4.4 BANCO DE DADOS

Atualmente, existem diversos bancos de dados gratuitos e livres disponíveis no

mercado. Dentre eles, os mais conhecidos são o MySql, o PostgreSQL e mais recentemente o Derby

(desenvolvido e mantido pela Fundação Apache). Identificar qual o melhor deles é uma tarefa

bastante subjetiva, pois possuem características próprias que os levam a ser mais interessantes para

uso em algumas áreas, em detrimento de outras.

4.4.1 MySql

O MySql é um produto desenvolvido pela MySql AB (http://www.mysql.com). Foi criado

para satisfazer a necessidade de maior flexibilidade e desempenho para acesso aos dados da

empresa, que utilizava o mSQL. Segundo a empresa, o nome MySql não tem origem muito clara.

Enquanto alguns dizem que o nome se deve ao fato de que um grande número de bibliotecas tinham

o prefixo my, outros dizem que é uma homenagem à filha de um dos fundadores da empresa, Monty

Widenius, que se chama My. Assim, a origem real do nome MySql é um mistério para a própria

empresa [MYSQL].

Sem concorrentes de peso no chamado "mundo livre", sua utilização foi disseminada

pelo mundo todo, especialmente durante a expansão da internet (o chamado boom da internet). Entre

os motivos para o sucesso do MySql pode-se citar:

• o seu alto desempenho;

• o fato de ser gratuito para utilização em websites;

• ser leve, consumindo poucos recursos de processamento e memória dos

servidores.

A necessidade de alcançar alto desempenho fez com que muitos recursos típicos de

bancos de dados como transações e stored procedures fossem deixado de lado em suas primeiras

versões, e alguns deles ainda não foram implementados nas versões mais recentes.

Page 28: Desenvolvendo aplicações corporativas

28

O MySql é licenciado de duas maneiras:

• pela General Public License (GPL), se o software desenvolvido também utilizar uma

licença livre;

• pela licença comercial da MySql AB, se o software for liberado por uma licença não-

livre ou for obtido lucro com ele.

4.4.2 PostgreSQL

O PostgreSQL, inicialmente chamado de Postgres, foi criado na Universidade de

Berkley (Califórnia) em 1986, pelo professor Michael Stonebraker, em substituição ao Ingres, banco

de dados que na época foi comprado pela Computer Associates . Postgres tem o significado de "após

o Ingres"). Ele foi desenvolvido pelo professor e seus alunos por oito anos, período no qual os

principais recursos de bancos de dados relacionais foram incorporados. O Postgres foi então

comercializado e se tornou o Illustra, que foi comprado pela Informix, que por sua vez foi comprado

pela IBM [POSTGRESQL].

Em 1995, após a substituição da linguagem interna do Postgres, ele foi rebatizado de

Postgres95, e no ano seguinte seu código foi aberto, sendo que um grupo de alunos de Berkeley

continuou a desenvolvê-lo. Após alguns anos e muitas modificações, foi novamente rebatizado, desta

vez como PostgreSQL. Sua primeira versão foi a 6.0, em memória aos longos anos de

desenvolvimento anteriores, que lhe deram a reputação de um banco de dados robusto e confiável.

Atualmente, o PostgreSQL está na versão 8.1.

Sendo um banco de dados livre, seguro, rápido e disponível em várias plataforma, o

PostgreSQL despertou o interesse de grandes corporações, que viram nele uma alternativa não só

econômica, mas principalmente tecnicamente viável aos caríssimos bancos de dados proprietários.

Por causa disto, várias delas (como a Fujitsu Australia, Red Hat e Sun Microsystems) estão

contribuindo com o projeto, seja financeira ou tecnicamente.

Page 29: Desenvolvendo aplicações corporativas

29

4.4.3 Derby

Em 1996 a Cloudscape Inc., empresa baseada em Oakland (Califórnia), foi fundada com

o objetivo de desenvolver tecnologias para bancos de dados em Java. A primeira versão de seu

produto foi lançada em 1997, com o nome de JBMS, sendo mais tarde rebatizado de Cloudscape. Em

1999, a Cloudscape foi adquirida pela Informix, que dois anos depois foi comprada pela IBM. O banco

de dados foi novamente renomeado, desta vez para IBM Cloudscape, que continuou a desenvolvê-lo,

mas desta vez com foco em bancos de dados embarcados. Em 2004, a IBM cedeu o código do IBM

Cloudscape para a Fundação Apache, que o transformou no Derby. Em julho de 2005, o Derby foi

lançado oficialmente.

Dentre as principais características do Derby pode-se citar [DERBY]:

• é livre para qualquer tipo de uso;

• totalmente desenvolvido em Java, o que garante sua execução em múltiplas

plataformas;

• facilidade de uso para desenvolvedores e usuários finais, que não precisam

administrá-lo;

• é pequeno – o banco de dados completo, com o motor e driver JDBC embarcado,

tem apenas 2 MB, o que garante alto desempenho e baixa utilização dos recursos

da máquina, permitindo seu uso até mesmo em telefones celulares;

• baseado nos padrões Java e ANSI SQL, incluindo a sintaxe SQL, transações,

concorrência, triggers e backup on-line.

Tendo sido desenvolvido como um banco de dados embarcado, o Derby é facilmente

integrado em diversas ferramentas, entre elas o SJSAS, que o utiliza inclusive para armazenar os

dados internos do servidor – não impedindo sua utilização para qualquer tipo de aplicação. Da

mesma maneira, o NetBeans 5.5, acessa diretamente o Derby do SJSAS, permitindo operações

como criação de bancos de dados e tabelas e realização de consultas, entre outras.

Por todas estas características, o Derby foi utilizado no desenvolvimento deste trabalho.

Page 30: Desenvolvendo aplicações corporativas

30

5 UMA APLICAÇÃO PRÁTICA DA TECNOLOGIA JAVA EE

A aplicação base para este trabalho é um software gerenciador de projetos. Foram

desenvolvidos apenas os módulos necessários para a demonstração das tecnologias envolvidas. A

mesma linha foi adotada quanto aos recursos do servidor de aplicações Java EE, onde apenas foram

configurados os recursos necessários para o desenvolvimento do aplicativo.

É importante frisar que o objetivo deste trabalho não é ser uma referência para o ensino

da linguagem de programação Java . O objetivo é dar subsídios para o início do desenvolvimento de

aplicações que englobam várias das tecnologias disponíveis na plataforma Java EE 5.

Parte-se do pressuposto, então, que o leitor já possua conhecimentos da linguagem de

programação Java em ambientes desktop e web , bem como familiaridade com algum IDE e o

framework JSF.

Por conta disto, o enfoque maior é o que , e não como fazer. De fato, pouco código foi

escrito – o trabalho foi em grande parte feito pelo próprio IDE. Baseado neste código, os principais

conceitos e configurações serão discutidos.

O aplicativo a ser desenvolvido é bastante simples, e ao final do desenvolvimento, os

principais recursos tratados terão sido (não necessariamente nesta ordem):

1. Banco de dados

1.1. Utilização do Derby a partir do NetBeans;

1.2. Pool de conexões controlado pelo servidor de aplicações;

1.3. Recursos de acesso ao banco de dados controlado pelo servidor de aplicações;

1.4. Utilização de camada de persistência;

1.5. Utilização da Java Persistence API (JPA).

2. Camada de negócios

2.1. Beans

2.1.1. Interfaces locais e remotas;

2.1.2. Anotações.

2.2. Entidades

2.2.1. Para tabelas simples;

2.2.2. Para tabelas com chaves estrangeiras;

2.2.3. Para tabelas com chaves compostas;

Page 31: Desenvolvendo aplicações corporativas

31

2.2.4. Interfaces locais e remotas;

2.2.5. Facades.

2.3. Arquivos de configuração;

2.4. Utilização da Java Cryptography Extension (JCE).

3. Camada de visualização (desktop)

3.1. Acesso aos componentes de negócio a partir da aplicação desktop;

3.2. Utilização do container de aplicações cliente do SJSAS.

4. Camada de visualização (web )

4.1. Utilização de EJB a partir da aplicação web ;

4.2. Acesso aos recursos do contexto Faces;

5.1 AMBIENTE DE DESENVOLVIMENTO

Para a construção do aplicativo, é fundamental que o ambiente de desenvolvimento

esteja configurado. Ao final do procedimento a seguir, o ambiente deve estar instalado, integrado e

em funcionamento.

A correta configuração do NetBeans é fundamental para o desenvolvimento do projeto,

pois praticamente todas as operações serão realizadas através dele.

Todo o desenvolvimento foi realizado na plataforma Windows XP Professional, com o

Service Pack 2 instalado.

5.1.1 Pré-requisitos

• JDK 1.5.0_03 ou acima. Neste trabalho, foi utilizada a versão 1.5.0_08, disponível

em http://java.sun.com/javase/downloads/index.jsp;

• NetBeans 5.5, disponível em http://www.netbeans.org/downloads..

• SJSAS, disponível no endereço http://java.sun.com/javaee/downloads/index.jsp. Ao

final da página, escolha o componente Sun Java System Application Server

Platform Edition 9, Multi-language.

5.1.2 Instalação dos software

Os software podem ser instalados em qualquer pasta do computador. Entretanto, é

importante que seja criada uma variável de ambiente chamada JAVA_HOME, cujo conteúdo é o

caminho para a pasta de instalação do JDK. Todos eles podem ser instalados com as configurações

default.

Page 32: Desenvolvendo aplicações corporativas

32

5.2 INTEGRAÇÃO DO NETBEANS COM O SJSAS

O NetBeans e o SJSAS são patrocinados pela Sun, e por isso são facilmente

integrados:

• No NetBeans, acesse o menu Tools / Server manager;

• Clique no botão Add Server;

• Na tela que abrir, deixe os valores default e clique em Next;

• No campo Platform location, informe a pasta de instalação do SJSAS;

• Se já não estiver marcada, marque a opção Register Local Default Domain. A URL

localhost:4848...\domain1 é localizada automaticamente;

• Clique em Next e, na próxima tela digite o usuário e senha de administração,

informados durante a instalação do SJSAS.

A partir deste momento, é possível iniciar e parar o SJSAS através do NetBeans. Para

testar a integração, o seguinte procedimento pode ser realizado:

• Selecione a aba Runtime (está localizada no topo esquerdo da área de trabalho do

NetBeans), abra o nó Servers, acesse o menu de contexto e selecione Start,

conforme ilustra a figura a seguir.

Figura 7: Inicialização do SJSAS a partir do NetBeans

• Na área de mensagens do NetBeans serão abertas duas janelas, uma chamada

Java DB Database Process e a outra Sun Java System Application Server.

• O procedimento de inicialização termina quando as mensagens das Figuras 8 e 9

forem mostradas na área de output.

Figura 8: Mensagem de inicialização do Java DB

Page 33: Desenvolvendo aplicações corporativas

33

Figura 9: Mensagem de inicialização do SJSAS

• Num navegador web, acesse o endereço http://localhost:8080 . Se o SJSAS foi

carregado corretamente, uma tela com a mensagem abaixo deve ser mostrada.

Figura 10: Mensagem indicando que o SJSAS foi iniciado

O container web do servidor de aplicações por padrão utiliza a porta 8080 para que as

aplicações seja mostradas aos usuários. Entretanto, o SJSAS possui uma aplicação que responde na

porta 4848, utilizada para administração e configuração do servidor, chamada de Admin Console

(Painel de Administração). Para acessá-la, basta utilizar o endereço http://localhost:4848. Informe o

usuário admin e a senha informada durante a instalação, e uma página como ilustra a Figura 11 é

mostrada.

Sempre que for necessário configurar algum parâmetro no SJSAS, o procedimento deve

se feito através do Painel de Administração.

Figura 11: Tela principal do ASADMIN

Page 34: Desenvolvendo aplicações corporativas

34

5.3 CRIAÇÃO DO BANCO DE DADOS

A criação do banco de dados e das tabelas necessárias ao aplicativo é feita através do

próprio NetBeans. Este procedimento é adotado pois o banco utilizado, o Derby, é embarcado no

servidor de aplicações, e não possui nenhum tipo de ferramenta visual.

Entretanto, o NetBeans possui um módulo básico de acesso a banco de dados que

permite executar instruções SQL, criar e excluir tabelas, além de outras opções. Este módulo utiliza

conexões JDBC, e é compatível com praticamente todos os principais produtos do mercado, entre

eles o Derby.

Uma observação se faz necessária. A Sun utiliza o Derby embarcado em vários de seus

produtos, como o SJSAS. Seu principal objetivo é ser um banco de dados para desenvolvimento,

para que programadores testem suas aplicações sem a necessidade de possuir uma infraestrutura

complexa. No procedimento a seguir, várias figuras fazem alusão ao Java DB, nome pelo qual a Sun

chama sua versão customizada do Derby.

O primeiro passo é criar um banco de dados para utilizar na aplicação.

• Inicie o banco de dados. Para isto, acesse o menu Tools / Java DB Database / Start

Java DB Server (ver Figura 12). Se o SJSAS já tiver sido iniciado esta opção estará

desabilitada, pois o Java DB é inciado juntamente ao servidor de aplicações.

Figura 12: Menu para iniciar e parar o Java DB

• Verifique na área de saída do NetBeans (parte inferior da tela) se o banco foi

iniciado (ver Figura 13).

Figura 13: Mensagem de início do Java DB

• Acesse o menu Tools / Java DB Database / Create Java DB Database. Na tela a

seguir, informe os dados constantes na Figura 14 e clique em OK.

Page 35: Desenvolvendo aplicações corporativas

35

Figura 14: Configurações do banco de dados Maxigroupware

O local de gravação do banco de dados é indicado no campo Database Location . Para

alterar o local onde o Java DB cria os bancos de dados, basta seguir as instruções constantes na

própria tela.

• Com o banco de dados criado, é criada também uma conexão para acessá-lo (ver

Figura 15). Acesse seu menu de contexto, e escolha a opção Connect... Informe a

senha, se necessário.

Figura 15: Nova conexão criada

• Expanda a conexão, e vários componentes do banco de dados serão mostrados,

conforme ilustra a Figura 16.

Figura 16: Componentes disponíveis na conexão com o banco de dados

Page 36: Desenvolvendo aplicações corporativas

36

O segundo passo é criar as tabelas do banco de dados. A criação pode ser feita de duas

maneiras:

1. Através da opção Create table, do menu de contexto da opção Tables;

2. Através de scripts SQL.

Neste trabalho foi utilizado um script simples, que cria as três tabelas necessárias à aplicação. O

conteúdo do script está disponível no Apêndice A.

Para executar o script:

• Acesse o menu de contexto de qualquer componente da conexão (incluindo ela

mesma) e escolha a opção Execute command;

• Na janela que se abrir no NetBeans, digite o conteúdo do script e execute-o. Para

isto, clique no botão da barra de ferramentas. As mensagens da Figura 17

serão mostradas.

Figura 17: Mensagens de criação das tabelas

• Acesse o menu de contexto do nó Tabelas e escolha a opção Refresh. As tabelas

criadas serão mostradas.

As tabelas de projetos e usuários foram criadas com uma chave primária do tipo auto-

incremento, ou seja, o próprio banco de dados controla a geração dos códigos de projetos e usuários.

O problema desta abordagem é que campos de auto-incremento não são comuns a todos os bancos

de dados (por exemplo, Oracle e PostgreSQL utilizam as chamadas sequences ).

Esta abordagem foi utilizada apenas para fins didáticos, e não é a maneira ideal de se

controlar esta informação. O correto é criar seu próprio gerenciador de identidades, garantindo que

ele seja compatível com todos os bancos de dados. Entretanto, esta implementação não faz parte do

escopo deste trabalho.

Page 37: Desenvolvendo aplicações corporativas

37

5.3.1 Conceitos sobre acesso a bancos de dados no Java

Quando se fala em acessar bancos de dados utilizando Java, é necessário conhecer

três conceitos, nos quais se baseiam a conexão, a pesquisa e a utilização destes dados, otimizando

os recursos disponíveis de máquina. Estes conceitos são:

• Conexão direta via Java Database Connectivity (JDBC);

• Pool de conexões;

• Camadas de persistência.

5.3.1.1 Conexão direta via JDBC

JDBC é o mecanismo básico de acesso ao banco de dados. Todos os acessos são

realizados através de conexões JDBC. É uma API completa que permite realizar desde simples

consultas até o gerenciamento completo do banco de dados.

Cada banco de dados tem um driver específico para acessá-lo. Este driver

(normalmente desenvolvido pelo próprio fabricante do banco de dados) é específico para o banco,

não havendo nenhum driver genérico.

No desenvolvimento tradicional, a cada acesso ao banco de dados é associada uma

conexão. Desta maneira, se num determinado método forem executados cinco acessos ao banco,

serão criadas cinco conexões. Estas conexões somente serão liberadas através de comandos no

próprio programa, ou então quando o banco o banco de dados enviar um sinal de timeout . Se muitas

conexões forem executadas simultaneamente (como num ambiente corporativo), o banco pode não

suportar a carga, perdendo desempenho.

Criar uma conexão pode consumir vários segundos, enquanto a instrução SQL

executada por ela pode consumir apenas milissegundos. Num ambiente internet, por exemplo, com

milhares de usuários, o consumo de recursos seria enorme. Por esta ineficiência, a conexão via

JDBC é pouco utilizada. Seu principal uso é a execução de pesquisa complexas, nas quais as

camadas de persistência normalmente têm baixo desempenho.

Para resolver este problema, são utilizados os pools de conexão.

5.3.1.2 Pool de conexões

O conceito de pool de conexões é bastante simples. Ao invés de criar as conexões sob

demanda, gerando sobrecarga ao banco de dados, cria-se um conjunto de conexões durante a carga

da aplicação. Estas conexões vão sendo utilizadas pela aplicação. Após o uso, as conexões são

Page 38: Desenvolvendo aplicações corporativas

38

liberadas. Quando todas as conexões do pool são utilizadas, novas conexões são recusadas, ou

então são adicionadas novas conexões ao conjunto já existente, aumentando sua capacidade (o

comportamento depende da configuração do pool) [IMASTERS].

Não são necessárias grandes quantidade de conexões dentro do pool, pois parte-se do

princípio que embora uma aplicação possa ter milhares de usuários, poucos deles farão acesso ao

banco de dados num determinado momento, e o tempo utilizado para o acesso é muito pequeno

(alguns milissegundos). Isto garante que sempre haja uma conexão disponível para uso.

Como as conexões não precisam mais ser criadas com grande freqüência, o

desempenho do acesso ao banco de dados é muito superior, e apenas o crescimento do número de

conexões é feito sob demanda. As conexões extras criadas serão canceladas pelo banco quando

expirar seu timeout , não sobrecarregando nem o servidor de aplicações, nem o de banco de dados.

Um pool de conexões pode ser facilmente implementado, sendo que existem boas

bibliotecas gratuitas disponíveis hoje, como o DBCP (acrônimo para Database Connection Pool), da

Fundação Apache [DBCP].

5.3.1.3 Camadas de persistência

Conceitualmente, uma camada de persistência permite o armazenamento em meio

físico das informações contidas num objeto.

Para uma melhor compreensão, tome-se por exemplo a tabela Projeto, criada no

banco de dados Maxigroupware. Sempre que um objeto do tipo Projeto precisar ser gravado no

banco de dados, deve-se obter os dados do objeto e executar um comando no banco de dados, já

com os dados do projeto, para gravação.

O tratamento manual desta operação pode provocar uma grande quantidade de

problemas. Por exemplo, se a estrutura da tabela for alterada no banco de dados, deve-se alterar,

recompilar e redistribuir o programa para os usuários.

O objetivo da camada de persistência é abstrair o desenvolvedor deste problema.

Utilizando vários recursos do Java, ao receber um objeto do tipo Projeto, ela sabe perfeitamente

quais dados obter do objeto, e a quais campos da tabela eles devem ser associados. Também

gerencia um pool de conexões próprio e centraliza o acesso ao banco de dados, facilitando a

manutenção do sistema.

O grande problema das camadas de persistência é que, às vezes, ela pode ser

ineficiente. Sendo bibliotecas genéricas, devem trabalhar da maneira mais padronizada possível, e

Page 39: Desenvolvendo aplicações corporativas

39

portanto não pode utilizar os recursos avançados típicos de cada banco. Prendendo-se a padrões

SQL, muitas vezes não seguidos pelos fornecedores de banco de dados, as camadas de persistência

têm aí o seu ponto fraco.

5.3.1.4 Pool de conexões no servidor de aplicações

Como citado anteriormente, o pool de conexões otimiza bastante o acesso ao banco de

dados, mas apresenta um problema. Cada aplicação deve controlar seu próprio pool. Aparentemente,

esta é uma tarefa simples, mas se for levado em consideração um ambiente corporativo, pode-se

chegar a alguns números interessantes. Por exemplo: um ambiente com 80 aplicações, todas

acessando o mesmo banco de dados. Para cada uma delas deveria ser criado um pool com 10

conexões. Seriam utilizadas 800 conexões ao banco.

Para minimizar o problema, é possível criar um pool não na aplicação, mas no próprio

servidor de aplicações, e compartilhar este pool entre várias aplicações diferentes, otimizando o

acesso ao banco. No exemplo acima, poderia ser criado um único pool, com 10 conexões servindo a

todas as aplicações. Deixariam de ser utilizadas 790 conexões.

Obviamente, existem limitações. A principal delas é que cada pool pode acessar apenas

um banco de dados de cada vez – o que não impede que seja criado um pool para cada banco. Neste

caso (e ainda utilizando o exemplo acima), num ambiente com 20 bancos diferentes, seriam criados

20 pools, totalizando 200 conexões. Ainda assim, deixariam de ser criadas 600 conexões.

5.3.1.5 Criação do pool de conexões ao banco de dados

Novamente é utilizado o painel de administração do SJSAS.

• No menu principal, acesse a opção Resources / JDBC / Connection Pools;

• Na tela mostrada, clique no botão New;

• Na nova tela mostrada (ver Figura 18) informe os dados abaixo:

Name..................: MaxigroupwarePool

ResourceType.....: javax.sql.DataSource

DatabaseVendor. . : Derby

• Clique em Next;

• Na tela seguinte (ver Figura 19), preencha apenas as seguintes propriedades:

• No menu aparece o nome do novo pool conforme pode ser visto na Figura 20.

Clique sobre ele para editá-lo e exclua todas as propriedades não listadas no item

anterior. Clique em Save.

Page 40: Desenvolvendo aplicações corporativas

40

Figura 18: Step 1 of 2 - Criação do pool de conexões

Figura 19: Step 2 of 2 - Propriedades do pool de conexões

Page 41: Desenvolvendo aplicações corporativas

41

Figura 20: Novo pool criado

5.3.1.6 Criação do recurso JDBC

O recurso JDBC é o elo de ligação entre a aplicação e o pool de conexões. Quando for

necessário se conectar ao banco de dados, é este recurso que deve ser referenciado, o que

automaticamente seleciona o pool de conexões correto.

Para criar o recurso JDBC:

• Acesse o menu Resources / JDBC / JDBC Resources (ver Figura 21). Depois,

clique em New...;

Figura 21: Criação de um recurso JDBC

Page 42: Desenvolvendo aplicações corporativas

42

• Na tela mostrada, informe:

JNDI Name. . : jdbc/maxigroupware

Pool Name...: MaxigroupwarePool

• Clique em OK;

• O recurso foi criado (ver Figura 22).

Figura 22: Recurso JDBC criado

Uma consideração sobre o JNDI Name . JNDI significa Java Naming and Directory

Interface. O nome JNDI é utilizado para organizar e localizar componentes num ambiente de

computação distribuído, de maneira análoga a um índice de páginas amarelas encontrado em listas

telefônicas. Como conseqüência, o nome JNDI é o método mais importante de acesso aos recursos

do servidor de aplicações.

Dentro do servidor de aplicações, os componentes são agrupados em categorias. Pode-

se compará-las a um diretório localizado no servidor de aplicações, dentro do qual estão diversos

recursos do mesmo tipo. A primeira parte do nome JNDI indica a pasta a ser pesquisada.

Por convenção, o nome do diretório com os recursos de banco de dados começa com

jdbc/. Assim, para localizar o recurso JDBC chamado maxigroupware , utilizamos o endereço

jdbc/maxigroupware .

5.4 CONFIGURAÇÃO DO SJSAS

O SJSAS em sua versão gratuita não pode ser considerado um servidor de aplicações

corporativo, devido à inexistência de recursos como computação em grade, balanceamento de carga

e alta escalabilidade, entre outros. Por isto, é considerado um servidor departamental.

Isto não impede que ele seja utilizado em ambientes com grande quantidade de

processamento, mas não existem garantias quanto ao desempenho em caso de sobrecarga.

Outra característica é que após sua instalação, ele está pronto para ser utilizado. Suas

configurações iniciais sugerem sua utilização num ambiente não muito pesado, e para isto ele é uma

Page 43: Desenvolvendo aplicações corporativas

43

ótima opção. Vale ressaltar que o SJSAS é baseado no GlassFish, projeto de código aberto

patrocinado pela Sun, e que o GlassFish nas próximas versões será distribuído com recursos

avançados de escalabilidade e tolerância a falhas [GLASSFISH WIKI].

Com isto, nenhuma configuração é realmente necessária para este trabalho. Entretanto,

foi alterada a porta padrão do servidor HTTP.

Por padrão, todas as requisições HTTP são feitas na porta 80 do servidor, e por este

motivo, não é necessário informá-la nos endereços web. Por exemplo, quando o endereço

http://localhost é digitado, a ausência do número da porta identifica que deve ser utilizada a porta 80.

Por outro lado, containeres web como o Tomcat utilizam por padrão a porta 8080,

mesmo respondendo a requisições HTTP. Por isso, é necessário indicar a porta na URL (por

exemplo: http://localhost:8080).

Para facilitar a digitação das URL utilizadas nos exemplos, a porta padrão do container

web do SJSAS foi alterada para 80, dispensando a informação da porta nos endereços.

Todas as configurações do SJSAS serão feitas a partir de sua página de administração.

• Num navegador, acesse o endereço http://localhost:4848/asadmin.

• Informe o usuário admin e a senha informada durante a instalação do servidor de

aplicações (ou outra, se ela foi alterada). É mostrado o painel de administração.

• No menu à esquerda, acesse: Configuration / HTTP Service / HTTP Listeners / http-

listener-1;

• Altere a opção Listener Port para 80;

• Clique no botão Save;

• Para testar a configuração, acesse o endereço http://localhost em um navegador.

Uma tela com o conteúdo mostrado na Figura 10 deve ser mostrada.

Veja as opções na Figura 23.

Page 44: Desenvolvendo aplicações corporativas

44

Figura 23: Alteração da porta padrão do container web

Page 45: Desenvolvendo aplicações corporativas

45

6 ENTERPRISE JAVA BEANS

O Java EE não é uma tecnologia simples. Ao contrário, ela é muito complexa, o

suficiente para não ser tratada como uma tecnologia monolítica, mas formada por partes menores,

chamadas de componentes . O conceito de componente deve ser bem compreendido antes de

qualquer desenvolvimento em Java EE.

A universidade de Princeton (localizada em Princeton, nos Estados Unidos) possui um

interessante serviço chamado de WordNet, que é essencialmente um dicionário léxico [PRINCETON].

Lá, o conceito de componente é:

“...um artefato que é uma parte individual de uma entidade composta, especialmente uma parte

que possa ser separada de ou anexada a um sistema...”.

Entretanto, componentes de software vão além disto. Eles são uma parte concreta do

sistema, um código escrito para representar o comportamento de um conceito abstrato. Por exemplo

um componente chamado AmortizaFinanciamento deve conter todo o código necessário para realizar

a amortização de um financiamento (com todas as particularidades que o processo de amortização

possui), e interagir com elementos como pessoas, empresas, e até mesmo outros componentes

[SRIGANESH 2006].

Um componente é independente, e se for bem construído pode ser reutilizado por outros

componentes e sistemas. Quando distribuído, deve ser empacotado juntamente com todos os

recursos necessários para seu funcionamento, como arquivos e configurações, de modo que ele

possa existir por si só, sem depender da aplicação original. Desta maneira, um sistema pode ser

formado por vários componentes reutilizados, cada um com sua funcionalidade específica.

Com um bom conjunto de componentes reutilizáveis, é possível montar um sistema

inteiro simplesmente definindo as ligações entre eles.

6.1 BEANS

Beans são componentes reutilizáveis, que realizam algum tipo de trabalho quando

acionados pelas aplicações clientes, encapsulando a lógica do negócio [JAVABEANS]. Podem, por

Page 46: Desenvolvendo aplicações corporativas

46

exemplo, consultar um preço, processar o cancelamento de nota fiscal, ou apenas armazenar os itens

de um carrinho de compras de uma aplicação de comércio eletrônico.

Desta maneira, não é necessário (nem recomendável) desenvolver a lógica de negócio

nas aplicações cliente. Isto permite acessar os beans de várias maneiras: numa aplicação web , numa

aplicação desktop ou através de web services .

Existem dois tipos de beans [BALL 2006]:

• Session beans: realizam operações para os clientes, e podem conter web services;

• Message driven beans: atuam como listeners para algum tipo de mensagem,

definidas pela API Java Message Service (JMS).

Neste trabalho, são utilizados apenas os Session Beans que, deste em ponto em diante

são tratados simplesmente como beans.

6.2 SESSION BEANS

Um session bean representa uma única instância do cliente, dentro do servidor de

aplicações. A única maneira de um cliente acessar as informações da aplicação são os métodos dos

beans , o que abstrai o cliente completamente da complexidade da aplicação.

Um bean é único e atende somente a um cliente que o acessa através de uma sessão

(daí o nome de session bean). Um bean não pode ser compartilhado entre sessões, nem persistido

(gravado em banco de dados, por exemplo). Uma vez que o cliente finaliza a sessão, o bean não é

mais associado a ela, e simplesmente é destruído.

Existem dois tipos de beans, classificados quanto à maneira que tratam seus estados

[BALL 2006]: stateless (os mais comuns) e statefull.

6.2.1 Statefull beans

O estado de um bean consiste nos valores de suas variáveis no decorrer da sessão. Um

statefull bean mantém esses valores enquanto durar a sessão do cliente. Se a aplicação cliente

remove o bean ou então é encerrado (por exemplo, o navegador é fechado), a sessão termina e o

bean é destruído. Caso contrário, mesmo que o bean termine de ser utilizado, ele permanece

disponível no servidor, e pode ser acessado a qualquer momento, juntamente com os dados

previamente informados.

Page 47: Desenvolvendo aplicações corporativas

47

6.2.2 Stateless beans

Num stateless bean , as variáveis podem ter um estado, mas ele somente é válido

durante a execução do método que chamou o bean. Quanto a execução termina, o estado das

variáveis não é retido.

À exceção de quando um método é executado, todas as instâncias de um stateless

bean são iguais, permitindo ao container EJB alocar qualquer instância para qualquer cliente. Esta

característica permite que eles sejam utilizados por vários clientes, e por isto são utilizados em

aplicações que tenham grande número de usuários simultâneos, otimizando a carga do servidor e

conseqüentemente seu desempenho.

Outra característica deste tipo de bean é que ele é o único que pode implementar web

services.

6.3 INTERFACES

Um cliente não pode acessar um bean diretamente. Por mais métodos que um bean

possua, o cliente só pode acessar os que forem declarados em suas interfaces. Isto é importante,

pois um bean pode ter métodos para seu uso próprio, que não são visíveis ao cliente. A Figura 24

mostra os passos para um cliente remoto acessar um bean.

Figura 24: Acesso de um bean por um cliente remoto

Interfaces são fundamentais para a construção de aplicativos de fácil manutenção. Além

de abstrair os clientes da complexidade da aplicação, permitem que o bean seja alterado sem afetar

os clientes. Se uma interface for escrita e algum dia for alterada, todos os clientes que a utilizam

deverão ser alterados também.

Existem três tipos de interfaces para acesso aos beans: remotas, locais e web services.

Os web services não são tratados neste trabalho.

As interfaces locais são utilizadas quando um bean é acessado por outro bean, e ambos

estejam na mesma JVM. Por exemplo: após realizar uma operação, um bean deve enviar um e-mail

para o responsável pelo processo. O bean que envia a mensagem é acessado somente para este tipo

Page 48: Desenvolvendo aplicações corporativas

48

de uso. Sendo acessado somente pelos beans já criados no container EJB, ele somente necessita da

interface local.

A s interfaces remotas são utilizadas quando aplicações externas ao container EJB

acessam os beans lá mantidos. Por exemplo, se uma aplicação web precisa acessar um bean,

somente pode fazê-lo a partir de uma interface remota, pois a aplicação web é executada em outro

container.

Como última observação, é necessário ressaltar que um bean pode implementar as

duas interfaces, sendo então referenciados por clientes remotos ou locais.

6.4 ANOTAÇÕES

Nas versões anteriores da especificação J2EE (nome do Java EE, até a versão 1.4),

todas as configurações necessárias à aplicação era feita em arquivos XML. Nestes arquivos,

chamados de deployment descriptors (descritores de publicação) eram especificados os beans

constantes da aplicação, se estes eram stateless o u statefull, se eram acessados remota ou

localmente, entre outras informações. Esta quantidade de informações gerava arquivos muito grandes

e de alta complexidade, o que por extensão tornava o desenvolvimento J2EE extremamente difícil e

demorado.

Na especificação Java EE 5, um dos principais objetivos é simplificar o desenvolvimento

e aumentar a produtividade. Para isso, parte das configurações antes descritas em arquivos XML são

agora inseridas na própria codificação do programa, através das annotations (anotações), e o

trabalho pesado ficou a cargo do servidor de aplicações. Como resultado direto, os arquivos de

configuração tiveram seus tamanhos (e complexidade) reduzidos drasticamente.

As anotações no Java são sempre precedidas do símbolo da arroba (@).

6.5 CONTAINER PARA APLICAÇÕES CLIENTE

O servidor de aplicações possui um container desenvolvido especificamente para

executar aplicações cliente. O principal objetivo é facilitar a distribuição e execução da aplicação em

ambiente distribuído. Neste container, o próprio servidor de aplicações se encarrega de fornecer as

bibliotecas necessárias à sua execução.

Quando se desenvolve um cliente, este normalmente faz referências a várias bibliotecas

(por exemplo, um componente para desenho de telas). O IDE envia as bibliotecas necessárias

juntamente com a aplicação e todas as configurações necessárias, como o classpath. O servidor de

Page 49: Desenvolvendo aplicações corporativas

49

aplicações então se encarrega de prover toda a infraestrutura necessária para a execução da

aplicação.

6.6 JAVA WEB START

Outro motivo para utilizar o container de aplicações cliente, é que normalmente os

clientes são desenvolvidos utilizando uma interface gráfica, como o Swing. O container se encarrega

de automaticamente disponibilizar a aplicação através do Java Web Start (JWS), sem que seja

necessário escrever uma única linha de código.

O JWS é uma tecnologia que permite distribuir e atualizar as aplicações cliente para

todos os usuários. Seu funcionamento é bastante simples: quando o usuário acessa a aplicação pela

primeira vez, o JWS copia a aplicação e todas as bibliotecas necessárias à execução para estação, e

depois a executa. Quando o usuário carrega a aplicação pela segunda vez, ao invés de copiar toda a

aplicação, o JWS copia apenas os arquivos alterados desde a última execução da aplicação pelo

usuário.

A tecnologia JWS permite que:

• o usuário sempre tenha a última versão do aplicativo;

• seja definida apenas uma origem para a aplicação, acabando com o problema de

enviar ao usuário algum tipo de mídia (CD ou disco flexível) ou de deixar a cargo do

usuário a instalação da nova versão.

6.7 CONTEXTO

Um contexto é uma área do servidor de aplicações onde ficam armazenadas as

informações dos EJB disponíveis. Basicamente, é um mapa relacionando objetos a seus respectivos

nomes, para que seja possível localizá-los no container EJB [JNDI].

Para acessar um EJB, é necessário primeiro criar um contexto, identificando o servidor e

a porta disponível para acessá-lo. Só então pode-se pesquisar o EJB, cujo nome sempre é relativo a

este contexto.

6.8 TIPOS DE ARQUIVO

Cada módulo de uma aplicação enterprise possui um tipo de arquivo diferente, que o

servidor de aplicações utiliza de maneiras diferentes. Embora estes arquivos possuam extensões

Page 50: Desenvolvendo aplicações corporativas

50

diferentes, todos eles são arquivos compactados no formato ZIP, que possuem internamente uma

estrutura de pastas e arquivos definida pela especificação Java.

Graças a este padrão, o servidor ou container onde o arquivo está sendo publicado sabe

interpretá-lo corretamente, e tomar as ações necessárias para disponibilizá-lo.

Estes arquivos são [BALL 2006]:

• JAR: tipo mais comum de arquivo do Java, o Java ARchive tem por finalidade

agrupar classes para criar bibliotecas. Normalmente uma aplicação Java pode

conter várias centenas de classes e o “empacotamento” em uma biblioteca facilita a

disponibilização do aplicativo.

• WAR: os Web ARchives são arquivos que contêm aplicações web completas, já

prontas para disponibilização num container JSP/Servlet como o Tomcat ou num

servidor de aplicações como o SJSAS.

• EAR: são os Enterprise ARchives, que contêm aplicações empresariais completas.

Um EAR normalmente é formado por vários módulos, que podem ser arquivos JAR

e/ou WAR. Estes arquivos somente são manipulados corretamente por servidores

de aplicação.

6.9 PERSISTÊNCIA DE DADOS

A persistência de dados é um dos pontos mais importantes de qualquer sistema. Por

melhor que seja seu desempenho, se o acesso ao banco de dados for lento, o sistema também o

será. Por isto, a especificação Java EE 5 tem diversos recursos para facilitar este acesso [BALL

2006]:

• Entity beans - ou simplesmente entidades, são os objetos responsáveis pelo acesso

direto aos bancos de dados utilizados numa aplicação. Uma entidade representa

uma tabela, e cada uma de suas instâncias corresponde a um registro desta tabela;

• A JPA fornece meios para gerenciar o mapeamento objeto-relacional de objetos

Java para um banco de dados. O mapeamento objeto-relacional relaciona cada

propriedade da entidade com uma coluna da tabela.

• Um PersistenceContext é um conjunto de instâncias de entidades no qual para cada

entidade existe apenas uma instância com um determinado valor de chave primária.

• A API EntityManager é usada para executar operações no banco de dados, como

inclusão, exclusão, alteração e consulta. Uma vez realizada a operação no

EntityManager, o PersistenceContext e o banco de dados são automaticamente

atualizados.

Page 51: Desenvolvendo aplicações corporativas

51

• O conjunto de entidades que podem ser acessadas por uma Entity Manager é

definido numa Persistence Unit. Ela supervisiona todas as operações de

persistência da aplicação. Sua configuração é feita no arquivo persistence.xml, que

também define o datasource e que tipo de operações podem ser realizadas, entre

outras informações.

• Um datasource é um recurso criado no servidor de aplicações que possui

informações de conexão ao banco de dados, como usuário, senha, protocolo de

rede utilizado e outras informações. Utilizando um datasource, a aplicação não

precisa fazer nenhuma conexão através de JDBC, pois elas serão fornecidas pelo

próprio datasource.

6.10 FACADES

Facades são session beans que encapsulam as chamadas a todos os serviços do

sistema. Quando se deseja executar uma ação do sistema, o cliente acessa um dos métodos da

classe facade, que por sua vez executa a tarefa necessária. [FACADE]

Não existe nenhum tipo de padrão quanto à quantidade de facades num sistema. É

possível construir sistemas de qualquer porte com apenas um facade e uma interface. Como beans

normais, não existe a obrigatoriedade de publicar todos os métodos da classe na interface.

Cada método da facade pode executar uma operação simples (como retornar o texto

“Olá, Mundo”) tanto como serviços complexos (como criar uma nota fiscal envolvendo processos

como expurgo de impostos e substituições tributárias, por exemplo).

Page 52: Desenvolvendo aplicações corporativas

52

7 UMA APLICAÇÃO SIMPLES

Este capítulo descreve um exemplo de aplicação contendo um EJB simples, suas

interfaces (remota e local), e um pequeno cliente em linha de comando para acessá-lo.

7.1 SESSION BEAN

O código abaixo é um stateless session bean simples. Sua função é unicamente

retornar a popular expressão Ola, Mundo.

package teste;import javax.ejb.Stateless;

@Statelesspublic class OlaMundoBean implements OlaMundoRemote, OlaMundoLocal { public String digaOla() { return "Ola, Mundo"; }}

O primeiro ponto a observar é a anotação @Stateless. Esta anotação identifica o bean

como sendo do tipo stateless.

O segundo ponto é a implementação de duas interfaces, uma delas remota

(OlaMundoRemote) e outra local (OlaMundoLocal). Isto possibilita ao bean ser acessado tanto por

clientes quanto por outros beans do mesmo container.

O único método do bean, digaOla, não possui nenhum argumento e retorna uma string

com o conteúdo Ola, Mundo .

7.2 INTERFACES

Como visto anteriormente, para executar um método do bean é necessário que sua

interface seja acessada. Neste exemplo, o bean implementa duas interfaces.

Page 53: Desenvolvendo aplicações corporativas

53

A interface remota tem o seguinte código:

package teste;import javax.ejb.Remote;

@Remotepublic interface OlaMundoRemote { java.lang.String digaOla();}

A anotação @Remote é o único código que identifica a interface como remota. Da

mesma maneira, na interface local o identificador de que a interface é local é a anotação @Local:

package teste;import javax.ejb.Remote;

@Localpublic interface OlaMundoLocal { java.lang.String digaOla();}

7.3 APLICAÇÃO CLIENTE

Um cliente simplificado para acessar o EJB, utilizando apenas uma janela do prompt de

comando do Windows tem o seguinte conteúdo:

package olamundo;

import java.util.Properties;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;import teste.OlaMundoRemote;

public class Main {

public static void main(String[] args) { Main teste = new Main(); teste.executa(); } public void executa() { try { Properties p = System.getProperties(); p.put(Context.PROVIDER_URL, "localhost:1099"); Context ctx = new InitialContext(p); OlaMundoRemote olaMundoRemote =

(OlaMundoRemote)ctx.lookup("teste.OlaMundoRemote"); System.out.println(olaMundoRemote.digaOla()); } catch (NamingException ex) { System.out.println("EJB OlaMundo não encontrado"); } }}

Um contexto sempre é criado a partir das variáveis de ambiente do servidor. No

processo de criação, espera-se que esteja disponível uma variável de ambiente com um endereço

Page 54: Desenvolvendo aplicações corporativas

54

válido do servidor de nomes. Este servidor de nomes deve estar ativo e respondendo num porta

conhecida.

O servidor de nomes utiliza a tecnologia JNDI (ver seção 5.3.1.6).

Para criar a variável de ambiente, são executadas as linhas abaixo, o que indica uma

chave chamada java.naming.provider.url (que é o conteúdo da constante definida por

Context.PROVIDER_URL), cujo valor é o endereço localhost:1099.

Properties p = System.getProperties();p.put(Context.PROVIDER_URL, "localhost:1099");

A criação do contexto é realizada pela instrução abaixo:

Context ctx = new InitialContext(p);

O contexto ctx é criado, e acessa o servidor JNDI especificado na variável de ambiente

previamente definida. A partir deste momento, é possível pesquisar o EJB disponíveis no contexto,

através do método lookup():

OlaMundoRemote olaMundoRemote = (OlaMundoRemote) ctx.lookup("teste.OlaMundoRemote");

Nenhuma referência direta é feita ao EJB, mas sim à sua interface. Por este motivo, ao

pesquisar um EJB passamos como argumento o nome da interface correspondente. No exemplo, a

aplicação cliente é executada num container diferente do qual EJB está sendo executado, por isto é

referenciada sua interface remota.

A partir deste ponto, sempre que o objeto olaMundoRemote for referenciado, ele está

automaticamente acessando o EJB OlaMundoBean, pois este implementa a interface remota

OlaMundoRemote. Isto é facilmente verificado pela instrução abaixo:

System.out.println(olaMundoRemote.digaOla());

Esta instrução é a responsável por acessar o método digaOla do EJB.

7.4 CONSTRUÇÃO DA APLICAÇÃO COM O NETBEANS

Os passos a seguir criam a aplicação OlaMundo com a utilização do IDE NetBeans. Os

mesmos passos são utilizados para criar a aplicação de controle de projetos. Para isto, o NetBeans

deve estar sendo executado, e o servidor de aplicações deve ter sido iniciado, conforme descrito na

seção 5.2.

Page 55: Desenvolvendo aplicações corporativas

55

7.4.1 Criação de um projeto

• Acesse o menu File / New Project;

• Na tela mostrada, selecione Enterprise na janela da esquerda, e Enterprise

Application na janela da direita;

• Clique em Next;

• É mostrada uma tela com os dados da nova aplicação conforme ilustra a Figura 25.

Informe OlaMundo como nome do projeto. Os outros dados serão preenchidos

automaticamente, refletindo a alteração;

• Se desejar, altere a pasta definida em Project Location;

• Certifique-se que a opção Create Application Client Module esteja marcada;

• Clique em Finish.

Figura 25: Criação de uma aplicação Enterprise no NetBeans

O projeto é criado, com quatro módulos: uma aplicação corporativa (enterprise), uma

aplicação cliente, um módulo EJB e uma aplicação web, conforme ilustra a Figura 26.

Page 56: Desenvolvendo aplicações corporativas

56

Figura 26: Módulos criados pelo assistente Enterprise Application

7.4.2 Criação do bean

O bean e suas interfaces devem ser criados dentro do módulo EJB da aplicação. Esta

operação pode ser feita rapidamente através do assistente disponível no IDE.

• Acesse o menu de contexto do módulo OlaMundo-ejb e acesse a opção New /

Session Bean, para que o assistente seja iniciado;

• Na tela mostrada (ver Figura 27, informe o EJB Name (OlaMundo) e o package

(teste);

• Marque o tipo Stateless;

• Certifique-se de que os dois tipos de interface (Remote e Local) estejam marcados;

• Clique em Finish;

Figura 27: Criação de um session bean no NetBeans

Page 57: Desenvolvendo aplicações corporativas

57

O bean e as interfaces serão criados, conforme ilustra a Figura 28.

Figura 28: Programas criados pelo assistente de session beans

7.4.3 Programação do bean e das interfaces

• Abra o arquivo OlaMundoBean.java para edição;

• Altere o programa, criando o método olaMundo, conforme a listagem da seção 7.1;

• Posicione o cursor na linha com a assinatura do método olaMundo. Um pequeno

símbolo (uma lâmpada amarela) aparece ao lado do número da linha (ver Figura

29). Clique sobre ele e acesse a opção Add to Local interface. Repita a operação,

desta vez acessando a opção Add to Remote interface.

Figura 29: Atualização das interfaces

• Para verificar a criação do métodos nas interfaces , basta abrir os arquivos para

edição e comparar com o conteúdo da seção 7.2.

7.4.4 Programação da aplicação cliente

• Selecione o projeto OlaMundo-app-client ;

• Acesse o menu File / New File;

• Certifique-se de que o projeto OlaMundo-app-client esteja selecionado;

• Selecione as opções Java classes na janela da esquerda e Java Class na janela da

direita (ver Figura 30);

• Clique em Next ;

Page 58: Desenvolvendo aplicações corporativas

58

Figura 30: Criação de uma classe Java simples

• Na tela New Java Class (ver Figura 31), informe o Class Name Main, e o package

olamundo ;

• Clique em Finish;

• Uma nova classe foi criada e está disponível no projeto (ver Figura 32);

• Substitua o conteúdo da classe pelo código disponível na seção 7.3.

Figura 31: Criação de uma nova classe Java

Page 59: Desenvolvendo aplicações corporativas

59

Figura 32: Nova classe criada

7.4.5 Deploy da aplicação

Há três maneiras de realizar o deploy (publicação) da aplicação no SJSAS:

• Pelo painel de administração do servidor:

• Pelo NetBeans: acessando o menu de contexto da aplicação enterprise e escolher a

opção Deploy Project, o NetBeans faz o deploy da aplicação ;

• Manualmente: copiando o EAR gerado pelo IDE para a pasta autodeploy do

servidor de aplicações (o nome desta pasta varia de um servidor de aplicações para

outro).

Na pasta onde o projeto enterprise do NetBeans é gravado, são criadas várias pastas:

• build: pasta para onde o NetBeans copia os arquivos finais já empacotados dos

projetos, para posteriormente criar o EAR. Estes arquivos são os JAR dos módulos

EJB e cliente, e o WAR das aplicações web;

• dist: pasta utilizada pelo NetBeans para gerar o arquivo EAR final, a ser publicado

no servidor de aplicações;

• projeto-app-client : contém o projeto da aplicação cliente. Projeto deve ser

substituído pelo nome do projeto enterprise criado – no caso, OlaMundo ;

• projeto-ejb: contém o projeto do módulo EJB;

• projeto-war : contém a aplicação web .

No SJSAS, a pasta autodeploy está localizada na pasta domains\nome_do_domínio

(tomando por base a pasta de instalação do SJSAS). Nome_do_dominio deve ser substituído pelo

domínio onde a aplicação será publicada – no caso deste trabalho é utilizado sempre o padrão

domain1 .

Alguns instantes após a cópia, é gerado um outro arquivo, com o mesmo nome do EAR,

mas com a extensão ear_deployed, indicando que o arquivo foi publicado com sucesso. Se o arquivo

não foi criado ou foi criado com outra extensão, então a publicação teve problemas.

Page 60: Desenvolvendo aplicações corporativas

60

7.4.6 Execução do cliente

Para executar o cliente dentro do container do servidor de aplicações basta executar o

seguinte comando, numa tela de linha de comando:

SERVER\bin\appclient -client APP\ARQUIVO.JAR -mainclass CLASSE

Os dados escritos em letras maiúsculas devem ser substituídos pelo seguinte conteúdo:

• SERVER: pasta de instalação do SJSAS;

• APP: pasta onde são instalados os arquivos já publicados da aplicação.

Normalmente a pasta é SERVER\domains\domain1\generated\xml\j2ee-

apps\NomeAplicacao;

• ARQUIVO.JAR; nome do JAR que contém a aplicação cliente;

• CLASSE: classe do JAR a ser executada.

Uma vez que as linhas de comando tendem a ficar extensas, é aconselhável a criação

de um arquivo de processamento em lote (batch) para executar a aplicação. Um conteúdo possível é:

@echo offset SERVER=D:\Apl\Sun\AppServerset APP=D:\Apl\Sun\AppServer\domains\domain1\generated\xml\j2ee-apps\OlaMundoset JAR=OlaMundoClient.jarset CLASSE=olamundo.Maincls@echo on%SERVER%\bin\appclient -client %APP%\%JAR% -mainclass %CLASSE%

Ao ser executado, este script executa a aplicação OlaMundo dentro do container de

aplicações cliente do SJSAS.

Page 61: Desenvolvendo aplicações corporativas

61

8 PROVA DE CONCEITO - UMA APLICAÇÃO COMPLETA

O objetivo deste capítulo é demonstrar a utilização da persistência em banco de dados

através de uma aplicação enterprise que envolve os módulos EJB, web e desktop.

Convencionalmente, esta aplicação é chamada de CRUD (Create, Recover, Update, Delete), por

considerar as quatro operações básicas de um banco de dados (inserir, pesquisar, atualizar e excluir)

[WIKIPEDIA 02].

A aplicação é apenas uma prova de conceito, uma demonstração de como a tecnologia

funciona e pode ser aplicada no dia a dia e por isto é essencialmente didática.

Para o desenvolvimento da aplicação, os seguintes pontos devem ser observados:

• os software descritos na seção 5 devem ter sido instalados e configurados;

• uma aplicação enterprise deve ter sido criada, como descrito na seção 7.4.1. O

projeto contém os três módulos (EJB, web e application client). Neste trabalho, o

nome do projeto foi definido como Maxigroupware.

No desenvolvimento, foram utilizados o máximo possível de recursos do NetBeans. Esta

abordagem foi feita para evitar a complexidade de criar e manipular os arquivos de configuração

manualmente. Esta seria uma tarefa árdua e desnecessária, uma vez que uma das funções dos IDE é

aumentar a produtividade do desenvolvedor, automatizando grande parte dos processos.

Os fontes completos do aplicativo estão disponíveis no Apêndice B.

8.1 PROJETO

Mesmo sendo um aplicativo simples contendo apenas a operação de autenticar um

usuário, o projeto é necessário para facilitar a compreensão do que deve ser feito em sua

implementação. Neste trabalho, foi utilizada a Unified Modeling Language (UML).

A UML é uma linguagem-padrão para a elaboração de projetos de software, usada para

visualizar, especificar, construir e documentar sistemas de qualquer espécie. É uma linguagem

gráfica, formada por componentes que por sua vez são agrupados em diagramas. Existem treze tipos

de diagramas na última versão da UML [OMG].

Page 62: Desenvolvendo aplicações corporativas

62

8.1.1 Diagrama de casos de uso

Este tipo de diagrama demonstra de maneira generalizada os principais serviços

realizados pelo sistema. No aplicativo de testes, existe apenas um caso de uso (ver Figura 33):

Figura 33: Diagrama de casos de uso

8.1.2 Diagrama de seqüência

O diagrama de seqüência identifica as interações entre os objetos num espaço de

tempo, indicando quais operações e dados trafegam na troca de informações entre os objetos.

A Figura 34 ilustra o diagrama de seqüência para autenticação do usuário, do momento

em que os dados são informados na página de login até a exibição da mensagem confirmando ou

negando a autenticação.

Figura 34: Diagrama de seqüência

Usuário

Efetuar login

Usuário :Página login :Login :UsuarioFacadeRemote UsuarioFacade

2: autenticar( )

3: autentica(usuario, senha)

4: status = autentica(usuario, senha)5: findByLogin(usuario)

1: usuário, senha

8: status9: status10: mensagem

SGBD

6: login

7: dados pesquisados

Page 63: Desenvolvendo aplicações corporativas

63

8.2 ARQUIVOS DE CONFIGURAÇÃO

Ao criar uma aplicação enterprise, o NetBeans automaticamente cria os arquivos de

configuração necessário. No decorrer do desenvolvimento, estes arquivos são automaticamente

mantidos pelo IDE, e por isto normalmente não são alterados manualmente.

O principal arquivo de configuração da aplicação enterprise é o application.xml. Ele

pode ser encontrado no nó Configuration files da aplicação enterprise (ver Figura 35).

Figura 35: Arquivos de configuração da aplicação enterprise

O conteúdo do arquivo é descrito a seguir:

<?xml version="1.0" encoding="UTF-8"?><application version="5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_5.xsd">

<display-name>Maxigroupware</display-name> <module> <web> <web-uri>Maxigroupware-war.war</web-uri> <context-root>/Maxigroupware-war</context-root> </web> </module> <module> <java>Maxigroupware-app-client.jar</java> </module> <module> <ejb>Maxigroupware-ejb.jar</ejb> </module></application>

Os elementos do arquivo são:

• display-name: é o texto descritivo a ser mostrado ao usuário (por exemplo, no painel

de administração) no servidor de aplicações;

• module: são os módulos que compõem a aplicação. Podem ser do tipo web

(aplicações web), java (aplicações cliente) ou ejb (componentes enterprise). Pode

haver vários módulos de um mesmo tipo;

• web-uri: nome do pacote (arquivo WAR) que contém uma aplicação web;

Page 64: Desenvolvendo aplicações corporativas

64

• context-root: contexto a ser criado no servidor de aplicações para execução da

aplicação web . É utilizado para formar a URL a ser utilizada no navegador. No

arquivo acima, a aplicação tem a URL http://nome_do_servidor/Maxigroupware-war ;

• java: nome do pacote (arquivo JAR) que contém uma aplicação cliente;

• ejb: nome do pacote arquivo JAR) que contém um módulo EJB.

Embora os valores definidos originalmente funcionem corretamente, neste trabalho o

elemento context-root foi alterado para o seguinte conteúdo:

<context-root>/maxi</context-root>

Desta maneira, a URL para acessar o aplicativo é http://nome_do_servidor/maxi,

simplificando sua utilização.

8.3 MÓDULO EJB

8.3.1 Criação dos entity beans

• No menu de contexto do módulo Maxigroupware-ejb acesse a opção New / Entity

beans from database (ver Figura 36);

Figura 36: Criação de entidades a partir do banco de dados

• Na tela mostrada (ver Figura 37), informe o nome do datasource criado no servidor

de aplicações. A partir dele, serão lidas todas as tabelas disponíveis no banco de

dados, que serão mostradas na janela da esquerda.

• Selecione a tabele Projeto, clique em Add e em seguida em Next;

Page 65: Desenvolvendo aplicações corporativas

65

• Na tela mostrada (ver Figura 38), informe o nome do package como

entidades.projeto;

• Desmarque a opção Generate Named Query...;

• Clique em Create Persistence Unit;

Figura 37: Escolha do datasource e das tabelas para criação das entidades

Figura 38: Nomenclatura e empacotamento das entidades

Page 66: Desenvolvendo aplicações corporativas

66

• Na tela mostrada (ver Figura 39), aceite todas as opções fornecidas,

• Certifique-se que a opção Table Generation Strategy esteja definida como None.

Esta opção define como a criação das tabelas relativas às entidades é tratada. Para

mais informações sobre a persistence unit, veja a seção 6.9;

• Clique em Create;

Figura 39: Criação da persistence unit

• Na tela mostrada (ver Figura 38), cliquem em Finish;

• As entidades criadas serão mostradas no painel Projects, conforme ilustra figura a

seguir.

Figura 40: Entidade criadas no projeto

• Abra o arquivo Projeto.java para edição, e insira a anotação a seguir logo após a

anotação @Id:

@GeneratedValue(strategy=GenerationType.IDENTITY)

• Tecle a combinação ALT – SHIFT – F ; isto faz com que os imports correspondentes

sejam adicionados à classe, refletindo a alteração.

Page 67: Desenvolvendo aplicações corporativas

67

Agora basta repetir o processo para criar as entidades para as outras tabelas. Para o

desenvolvimento do aplicativo, foram utilizadas as configurações descritas na Tabela 2.

Tabela Classe Pacote

USUARIO Usuario entidades.usuario

PROJ_USUARIO ProjetoUsuario entidades.projetousuarioTabela 2: Entidades adicionais do projeto

• Ao final, a estrutura do projeto estará conforme a Figura 41.

• Abra o arquivo Usuario.java para edição, e insira a anotação a seguir logo após a

anotação @Id. Como anteriormente, tecle a combinação ALT – SHIFT – F para

importar as classes correspondentes.

@GeneratedValue(strategy=GenerationType.IDENTITY)

Figura 41: Entidades criadas no projeto

8.3.2 Entidade

Uma entidade possui diversas características que a diferenciam de uma classe

tradicional. A listagem a seguir é um extrato do código da entidade Projeto gerado pelo NetBeans,

que pode ser encontrado no Apêndice B.

...@Entity@Table(name = "PROJETO")public class Projeto implements Serializable {

@Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name = "CODPROJETO", nullable = false) private Integer codprojeto;

@Column(name = "NOME", nullable = false) private String nome;

@Lob @Column(name = "DESCRICAO", nullable = false) private String descricao;

Page 68: Desenvolvendo aplicações corporativas

68

public Projeto() { }

// métodos get e set ...

@Override public String toString() { return "entidades.projeto.Projeto[codprojeto=" + codprojeto + "]"; }}

Como é possível observar, uma entidade possui várias anotações, que a diferenciam de

uma classe normal. Muitas têm argumentos que alteram seu comportamento padrão.

@Entity

Define esta classe como uma entidade. É obrigatória para todas as entidades.

@Table(name="PROJETO")

Identifica qual tabela no banco de dados esta entidade vai representar. Pela

especificação Java EE 5, se esta anotação for omitida ela referenciará uma tabela com o mesmo

nome da classe. Portanto, sua inclusão somente é obrigatória se a tabela e a entidade não tiverem o

mesmo nome.

@Id

Define que a próxima propriedade contém a chave primária da entidade. É utilizada

somente se a chave primária contiver apenas uma coluna, caso contrário é obrigatória a utilização de

outra entidade representando a chave primária (como na entidade ProjetoUsuario.java, discutida

adiante).

@GeneratedValue(strategy=GenerationType.IDENTITY)

Define qual a estratégia de geração de chaves primárias. Os bancos de dados

trabalham com diferentes tipos de estruturas para geração automática de chaves primárias. Por

exemplo, o Oracle utiliza o recurso de sequences , enquanto o Derby utiliza um campo do tipo inteiro

com atributo de identidade, o que provoca seu incremento automático.

Neste caso, a estratégia utilizada é a identidade, implementada nos bancos de dados

como campos de valor auto incrementados. Seus outros valores podem ser AUTO (a decisão fica a

cargo da camada de persistência), SEQUENCE (utiliza uma seqüência previamente criada no banco de

dados) e TABLE (a camada de persistência utiliza uma tabela do banco de dados para criação das

chaves primárias).

Page 69: Desenvolvendo aplicações corporativas

69

@Column(name="CODPROJETO", nullable = false)

A anotação @Column identifica um coluna da tabela. Seu comportamento é o mesmo

da anotação @Table: se omitida, o padrão é referenciar uma coluna com o mesmo nome da

propriedade. A opção nullable definida como false (o default é true) reflete a característica not null

definida no momento da criação da tabela no banco de dados, ou seja, torna seu preenchimento

obrigatório.

@Lob

Especifica que a propriedade deve ser persistida do banco de dados como um large

object. Pode ser dos tipos binário (campo do tipo BLOB no banco de dados) ou então caracter

(normalmente um campo do tipo TEXT.

@Override

Esta anotação indica que o método a seguir sobrescreve um método da superclasse.

Foi criada na versão 5 do Java, atendendo a pedidos de desenvolvedores. Antes era impossível

saber se um método era sobrescrito ou não.

8.3.3 Entidades para chaves primárias

No código da classe ProjetoUsuario.java, observa-se a utilização de outras

anotações além das discutidas anteriormente, juntamente com o uso de uma outra entidade como

chave primária.

...@Table(name = "PROJ_USUARIO") public class ProjetoUsuario implements Serializable { @EmbeddedId protected ProjetoUsuarioPK projetoUsuarioPK;

@JoinColumn(name="CODPROJETO", referencedColumnName="CODPROJETO",insertable=false, updatable=false)

@ManyToOne private Projeto projeto;

@JoinColumn(name="CODUSUARIO", referencedColumnName="CODUSUARIO", insertable=false, updatable=false)

@ManyToOne private Usuario usuario; public ProjetoUsuario(ProjetoUsuarioPK projetoUsuarioPK) { this.projetoUsuarioPK = projetoUsuarioPK; }

public ProjetoUsuario(int codusuario, int codprojeto, String lider){ this.projetoUsuarioPK = new ProjetoUsuarioPK(codusuario,

codprojeto); this.lider = lider; }

public ProjetoUsuarioPK getProjetoUsuarioPK() { return this.projetoUsuarioPK; }

Page 70: Desenvolvendo aplicações corporativas

70

public void setProjetoUsuarioPK(ProjetoUsuarioPK projetoUsuarioPK) { this.projetoUsuarioPK = projetoUsuarioPK; } // métodos get e set ....}

@Table

A entidade ProjetoUsuario referencia a tabela Proj_Usuario. Uma vez que o nome da

entidade difere da tabela, a anotação @Table torna-se obrigatória.

@EmbeddedId

A anotação @EmbeddedId identifica uma chave primária composta, tratada

obrigatoriamente por outra entidade. A entidade ProjetoUsuarioPK foi gerada automaticamente

pelo NetBeans, no momento em que foi identificada uma tabela com uma chave primária composta.

Na utilização da entidade ProjetoUsuario, sempre que a chave primária precisar ser referenciada,

deve-se utilizar a entidade ProjetoUsuarioPK.

@JoinColumn

Identifica uma chave estrangeira. Quando uma pesquisa na entidade ProjetoUsuario é

realizada, sua chave primária também é atualizada automaticamente. Por isto, na entidade

ProjetoUsuarioPK serão realizadas pesquisas nas entidades Projeto e Usuario. A anotação

@JoinColumn é responsável por identificar a coluna da tabela a ser utilizada para realizar a pesquisa,

sendo que a tabela é definida pelo próprio tipo de objeto da variável.

Os outros parâmetros da anotação (insertable=false e updatable=false) são

obrigatórios neste caso. Eles fazem com que as entidades Projeto e Usuario não possam atualizar

as colunas da chave primária em suas respectivas tabelas no banco de dados. Desta maneira, as

entidades atuando como chaves estrangeiras podem apenas pesquisar no banco de dados, nunca

alterá-lo – procedimento previsto na especificação Java EE 5.

@ManyToOne

Identifica a cardinalidade muitos-para-um no banco de dados. Ou seja, para cada

entidade que for chave estrangeira, pode haver várias entidades descendentes. Exemplo: um usuário

pode ser alocado em vários projetos.

@Embeddable

A anotação @Embeddable é utilizada em todas as entidades que puderem ser utilizadas

como chaves primárias embarcadas. Nas classes utilizadas neste trabalho, a única que utiliza esta

anotação é a ProjetoUsuarioPK.

Page 71: Desenvolvendo aplicações corporativas

71

8.3.4 Criação dos session beans

• No menu de contexto do nó Source Packages do painel Projects, acesse a opção

New / Session Beans For Entity Classes (ver Figura 42);

Figura 42: Criação de session beans

• Na tela mostrada (ver Figura 43), selecione a entidade Projeto e clique sobre Add;

• Clique em Next ;

Figura 43: Assistente para criação de session beans

• Na tela seguinte (ver Figura 44), altere o package para entidades.projeto;

• Certifique que apenas a opção Remote esteja marcada e clique em Finish;

• Os session beans (que neste caso serão facades) e suas interfaces serão criados;

• Repita o processo, criando os beans e interfaces restantes nos pacotes de suas

respectivas entidades. É possível criar as classes para cada entidade

separadamente, ou então criar todas ao mesmo tempo, e depois selecionar as

classes de um pacote e arrastá-la para o pacote correto (neste caso, deve-se

arrastar e soltar uma classe de cada vez).

Page 72: Desenvolvendo aplicações corporativas

72

Figura 44: Empacotamento e escolha das interfaces a serem criadas

Figura 45: Session bean e interface criados

8.3.5 Persistência

Como explanado na seção 6.10, facades são o ponto de acesso para as aplicações

cliente executarem as ações do sistema, sendo session beans normais.

A listagem a seguir é a facade utilizada para as operações realizadas com entidade

Projeto. E la é um stateless session bean , definido pela anotação @Stateless. Para realizar

operações de persistência com a entidade, é utilizado um EntityManager.

...@Statelesspublic class ProjetoFacade implements ProjetoFacadeRemote {

@PersistenceContext private EntityManager em;

Page 73: Desenvolvendo aplicações corporativas

73

public ProjetoFacade() { }

public void create(Projeto projeto) { em.persist(projeto); }

public void edit(Projeto projeto) { em.merge(projeto); }

public void destroy(Projeto projeto) { em.remove(em.merge(projeto)); }

public void destroy(int id) { em.remove(this.find(id)); }

public Projeto find(Object pk) { return (Projeto) em.find(Projeto.class, pk); }

public List findAll() { return em.createQuery("select object(o) from Projeto as o")

.getResultList(); }

}

Os métodos mais utilizados da API EntityManager são os seguintes:

persist

Persiste (grava) uma nova instância da entidade no PersistenceContext.

merge

Altera os dados de uma instância da entidade no PersistenceContext.

remove

Exclui uma instância da entidade do PersistenceContext.

find

Localiza uma entidade através de sua chave primária. O retorno é uma entidade com os

dados pesquisados.

createQuery

Cria uma instância de Query. Query é um objeto que pode realizar qualquer tipo de

operação no PersistenceContext. É utilizado quando os métodos tradicionais não são suficientes

para realizar a operação desejada (por exemplo, é necessário localizar uma entidade por um índice

diferente da chave primária). Seus métodos principais são:

Page 74: Desenvolvendo aplicações corporativas

74

• executeUpdate: atualiza (inclui ou altera) ou exclui uma entidade do

PersistenceContext;

• getSingleResult: executa uma pesquisa retornando uma única entidade.

• getResultList: executa uma pesquisa, retornando uma ou mais entidades na forma

de um List.

8.3.6 Interfaces

As interfaces são a referência dos facades dentro do servidor JNDI, ou seja, é através

delas que podemos localizar os EJB. A seguir, o código da interface do bean ProjetoFacade. O

único ponto em que se diferencia de uma interface tradicional do Java é a anotação @Remote,

indicando que é um interface remota. Se fosse uma interface local, a anotação seria @Local.

...@Remotepublic interface ProjetoFacadeRemote { void create(Projeto projeto); void edit(Projeto projeto); void destroy(Projeto projeto); Projeto find(Object pk); List findAll(); void destroy(int id); }

8.4 COMPLETANDO A APLICAÇÃO EJB

Embora o NetBeans gere grande parte do código da aplicação, sempre é necessário

fazer pequenos ajustes, a fim de fornecer maiores funcionalidades ao aplicativo.

A Tabela 3 lista as alterações necessárias para completar o módulo EJB. Os fontes

completos estão disponíveis no Apêndice B.

Classe Alterações

ProjetoUsuarioFacade • Criar o método findProjetosPorUsuario;

ProjetoUsuarioFacadeRemote • Adicionar o método findProjetosPorUsuario à

interface.

ProjetoFacade • Criar o método destroy(int id);

ProjetoFacadeRemote • Adicionar o método destroy(int id) à interface;

UsuarioFacade • Alterar o construtor UsuarioFacade();

UsuarioFacade • Alterar o método create(Usuario usuario);

UsuarioFacade • Criar o método destroy(int id);

Page 75: Desenvolvendo aplicações corporativas

75

Classe Alterações

UsuarioFacade • Criar o método findByLogin(String login);

UsuarioFacade • Criar o método autentica(String login,

String senha);

UsuarioFacadeRemote • Inserir os métodos destroy, findByLogin e

autentica;

Tabela 3: Alterações necessárias ao módulo EJB

Além disto, é necessário criar as seguintes classes:

• utils.Criptografia;

• utils.Mensagem.

8.5 ACESSO AOS EJB NUM CLIENTE DESKTOP

O acesso aos EJB numa aplicação desktop é bastante simples, como visto

anteriormente na seção 7.3.

A listagem disponível no Apêndice C é um pequeno cliente em linha de comando que,

dependendo dos parâmetros passados, realiza as operações de inserir, excluir, alterar, consultar e

listar projetos. Este programa deve ser criado criado no projeto Maxigroupware-app-client, e é

chamado de maxigroupware.Main. Para executá-lo, é possível executar um batch como o abaixo:

@echo offset SERVER=D:\Apl\Sun\AppServerset APP=%SERVER%\domains\domain1\generated\xml\j2ee-apps\MaxiGroupwareset JARNAME=MaxiGroupwareClient.jarset CLASS=maxigroupware.Maincls@echo on%SERVER%\bin\appclient -client %APP%\%JARNAME% -mainclass %CLASS% %1 %2

O programa é um aplicativo CRUD que trabalha unicamente com o EJB relacionado à

tabela Projeto. O acesso aos EJB a partir de uma aplicação cliente foi discutido na seção 7.3. Os

métodos que trabalham com a entidade são discutidos a seguir.

8.5.1 Listagem

Antes e depois de cada operação os registros gravados no banco de dados (se houver

algum) serão listados, para que uma comparação dos dados seja possível.

Page 76: Desenvolvendo aplicações corporativas

76

O método implementado para imprimir os registros é o lista(). Ele executa uma

pesquisa na entidade Projeto,através do método findAll(), que retorna todos os registros

cadastrados, imprimindo-os a seguir.

List lista = projetoFR.findAll(); for (Object o : lista) { System.out.println(" " + o.toString()); }

8.5.2 Inclusão

A inclusão de registros é realizada pelo método create(). Um objeto do tipo Projeto é

criado e seus dados são inicializados. Nesta implementação, o nome e a descrição do projeto contém

a data e hora de criação do objeto. Desta maneira, mesmo que sejam incluídos vários projetos, nunca

haverão dois registros iguais.

private void create() { System.out.println("\n--- Criando ---"); Timestamp timestamp = new Timestamp(System.currentTimeMillis()); Projeto p = new Projeto(); p.setNome("Prj: " + timestamp); p.setDescricao("Criado em " + timestamp); projetoFR.create(p); System.out.println(" " + p.toString()); System.out.println(); }

A linha a seguir é responsável pela gravação do registro no banco de dados. Observe

que é acessado o método create() da interface ProjetoFacadeRemote, sendo passado como

parâmetro o objeto a ser gravado.

projetoFR.create(p);

8.5.3 Pesquisa

A pesquisa é realizada pelo método recover(). Para que seja realizada, o código do

projeto deve ser informado como argumento na linha de comando. O código é então passado ao

método find() da interface. Este método retorna um objeto que pode ser nulo (caso o código não

tenha sido cadastrado previamente), ou então um projeto já inicializado com o conteúdo gravado no

banco de dados.

Projeto p = projetoFR.find(codigo); if (p==null) { System.out.println(" Projeto nao encontrado: " + s); } else { System.out.println(" " + p.toString());

Page 77: Desenvolvendo aplicações corporativas

77

}

8.5.4 Atualização

O processo de atualização é realizado pelo método update() e envolve dois

procedimentos. O primeiro é a pesquisa do projeto a ser alterado, realizado pela instrução a seguir:

Projeto p = projetoFR.find(codigo);

O código deve ter sido passado como argumento na linha de comando. A pesquisa é

necessária para que não seja feita uma tentativa de atualizar um registro que ainda não foi criado, o

que provocaria um erro na execução do comando.

O segundo procedimento é a alteração dos dados do objeto pesquisado e sua gravação:

Timestamp timestamp = new Timestamp(System.currentTimeMillis()); p.setNome("Prj: " + timestamp); p.setDescricao("Alterado em " + timestamp); projetoFR.edit(p);

O método edit() definido na interface do EJB é acionado e, então, realiza-se a

gravação dos dados.

8.5.5 Exclusão

A exclusão de registros é feita pelo método delete() e a instrução responsável é a

seguinte:

projetoFR.destroy(codigo);

O código deve ter sido passado como argumento na linha de comando.

É importante notar que o método destroy(int id) foi criado manualmente, não sendo

gerado automaticamente pelo NetBeans. Desta maneira, a pesquisa ao projeto com o código

correspondente é realiza da diretamente no container EJB, e não na aplicação cliente, aumentando o

desempenho do processo.

8.5.6 Criação de usuários

Para o desenvolvimento da aplicação web , é necessário também a criação de um

cliente cuja única função é incluir usuários no banco de dados.

Page 78: Desenvolvendo aplicações corporativas

78

O código fonte do cliente está disponível no Apêndice D, e sua operação foi discutida na

seção anterior.

A seguir está um exemplo de arquivo batch para acessá-lo:

@echo offset SERVER=D:\Apl\Sun\AppServerset APP=%SERVER%\domains\domain1\generated\xml\j2ee-apps\MaxiGroupwareset JARNAME=MaxiGroupwareClient.jarset CLASS=maxigroupware.CreateUsercls@echo on%SERVER%\bin\appclient -client %APP%\%JARNAME% -mainclass %CLASS% %1 %2 %3 %4

Para utilizá-lo, basta executar o programa passando como parâmetros, nesta ordem, o

login, a senha, o nome e o e-mail do usuário.

No processo de criação, a senha é automaticamente codificada.

8.6 ACESSO AO EJB NUMA APLICAÇÃO WEB

Há muito tempo, o desenvolvimento de aplicações web em Java tem sido feito na

maioria das vezes utilizando unicamente JSP. Muitos desenvolvedores acabam mesclando código

HTML com scriptlets (código programado em Java dentro de páginas JSP). Embora esta abordagem

não seja contra a especificação Java, ela não é bem vista por muitos desenvolvedores por várias

razões [INFORMIT]:

• prejudica a legibilidade do código da página;

• coloca a lógica do negócio dentro da camada de visualização;

• aumenta a complexidade da manutenção das páginas.

Para evitar estes problemas, todo o acesso à camada de negócio é feito através de

servlets (ver seção 3.2.2) ou beans. Estes componentes por sua vez acessam os EJB e realizam as

ações necessárias.

Neste trabalho, a abordagem utilizada é carregar os EJB a partir de beans. Foi criada

uma aplicação simples utilizando JSF (ver seção 4.3), cuja única função é verificar a autenticidade de

um usuário. Para isto, é utilizado o método autentica, do EJB UsuarioFacade.

Uma visão geral da aplicação é fornecida a seguir:

• A página inicial é definida no arquivo web.xml (), seção welcome-file-list, como

sendo index.jsp. É possível alterar esta configuração identificando o nome da nova

Page 79: Desenvolvendo aplicações corporativas

79

página inicial para qualquer nome que se deseje (por exemplo, login.jsp), embora

não seja usual.

• As páginas informativas sobre o sucesso ou não da autenticação do usuário estão

na pasta mensagens ;

• Os arquivos auxiliares cabecalho.jsp, rodape.jsp e o arquivo estilos.css estão na

pasta recursos ;

• O único bean gerenciado sendo utilizado é o login.java, localizado no pacote

manage e configurado no arquivo faces-config.xml, juntamente com as regras de

navegação (seção 9).

Na aplicação, deve-se informar um usuário e senha válidos. Caso os dados estejam

corretos o usuário é autenticado e a página indicando o sucesso da operação é mostrada. Em caso

de problemas com a autenticação, seja por dados incorretos ou não informados, é mostrada uma

página com o erro correspondente. O esquema de navegação é mostrado na Figura 46.

Figura 46: Regras de navegação da aplicação web

Na página login.jsp (Apêndice D) são informados os dados para autenticação. O

elemento commandButton define o método a ser chamado quando o usuário clicar sobre ele:

<h:commandButton value="Login" id="enviar" action="#{Login.autenticar}"/>

A cláusula action indica que o método autenticar do bean gerenciado Login será

acionado (Login.autenticar).

O método possui o seguinte conteúdo:

public String autenticar() { String result = "nao_autenticado";

Page 80: Desenvolvendo aplicações corporativas

80

String usuarioForm = getLogin().getValue().toString(); String senhaForm = getSenha().getValue().toString(); boolean autenticado = false; try { if (usuarioForm.equals("") || senhaForm.equals("")) { addErrorMessage("Informe o login e a senha!"); } else { autenticado = usuarioFR.autentica(usuarioForm, senhaForm); if (autenticado) { setUsuario(usuarioFR.findByLogin(usuarioForm)); FacesContext facesContext=FacesContext.getCurrentInstance(); facesContext.getExternalContext() .getSessionMap().put("_usuario", getUsuario()); addSuccessMessage("Autenticação OK!"); } else { throw new Exception("Erro"); } } } catch (Exception e) { setUsuario(null); addErrorMessage("Erro na autenticação do usuário. " + "Certifique-se que informou os dados corretos!"); } return (autenticado ? "autenticado" : "nao_autenticado"); }

O método autenticar utiliza os recursos básicos de uma aplicação JSF, buscando os

conteúdos dos campos de texto do formulário exibido ao usuário, e inicializando variáveis com esses

valores. Após o processamento o método retorna uma string contendo o resultado da operação (as

expressões autenticado ou nao_autenticado). Esta string é capturada pelo servlet controlador do

JSF, que se encarrega de chamar a página correspondente ao resultado, conforme definido nas

regras de navegação.

A primeira consistência é verificar se todos os dados foram informados, lembrando que

um campo vazio não possui valor null, e sim uma string vazia de tamanho zero. Por este motivo é

utilizada a instrução

if (usuarioForm.equals("") || senhaForm.equals("")) { ...

e não

if (usuarioForm==null || senhaForm==null) { ...

Se algum dado não for informado, a execução do método é interrompida. Caso

contrário, executa-se a autenticação, através da instrução a seguir:

autenticado = usuarioFR.autentica(usuarioForm, senhaForm);

O objeto usuarioFR é instanciado na classe, com a seguinte chamada:

@EJB(beanName="UsuarioFacade", beanInterface=UsuarioFacadeRemote.class)

Page 81: Desenvolvendo aplicações corporativas

81

private UsuarioFacadeRemote usuarioFR;

A anotação @EJB é responsável por referenciar um bean existente no servidor. Como

parâmetros, exige-se o nome do bean (beanName) e a classe de sua interface (beanInterface).

Desta maneira controla-se o bean e o acesso a ele. Deste ponto em diante, utiliza-se o objeto

usuarioFR de maneira transparente, executando-se os métodos nele definidos, como na instrução a

seguir, que pesquisa um usuário através de seu login (lembrando que neste ponto o usuário já foi

autenticado):

setUsuario(usuarioFR.findByLogin(usuarioForm));

O usuário retornado pela pesquisa é atribuído ao atributo da classe usuario, do tipo

entidades.usuario.Usuario. Esta operação é realizada para que o bean gerenciado possa criar um

atributo de sessão chamado _usuario, que contém o usuário autenticado e inicializado:

FacesContext facesContext=FacesContext.getCurrentInstance(); facesContext.getExternalContext()

.getSessionMap().put("_usuario", getUsuario());

Desta maneira, é possível a qualquer bean gerenciado acessar o contexto de uma

aplicação web que o utiliza, e conseqüentemente qualquer informação que possa ser acessada por

uma página JSP tradicional, ou então um servlet, bem como manipulá-las.

8.7 DOCUMENTAÇÃO

Uma das partes mais importantes de um aplicativo, não importa seu tamanho ou

complexidade, é a documentação. No caso de um desenvolvedor não dar mais manutenção em um

sistema, é a documentação que servirá de subsídio para que outra pessoa assuma seu lugar. A

documentação deve ser simples e objetiva, embora completa.

O Java possui um interessante mecanismo de documentação dos programa fonte,

chamado de JavaDoc. É um conjunto de tags (instruções) mesclado ao programa, que contém

informações sobre a classe, os métodos e seus parâmetros, e sobre o tipo de retorno que terá este

método. Também pode fornecer informações sobre versões e autoria da classe, entre outras coisas –

basta que se forneça a tag correta e o texto desejado.

Após criar a documentação no programa, é realizada uma análise do código e gerado

um conjunto de páginas no formato HTML, que contém a documentação. A análise e geração dos

documentos são realizados por um programa chamado javadoc.exe, que faz parte do JDK. Por

convenção, os documentos gerados e também as tags de documentação também são chamados de

JavaDoc.

Page 82: Desenvolvendo aplicações corporativas

82

O NetBeans possui ferramentas para o auxílio na geração tanto das tags quanto dos

documentos. Isto facilita bastante o trabalho do desenvolvedor, que pode criar a documentação do

programa simultaneamente ao desenvolvimento.

Para criar a documentação é utilizada uma ferramenta chamada AutoComment . Para

acessá-la basta acessar o menu de contexto do programa e selecionar a opção Tools /

AutoComment , como mostra a Figura 47.

Figura 47: Acesso à ferramenta AutoComment.

A tela do AutoComment é dividida em várias seções, conforme ilustra a Figura 48.

Page 83: Desenvolvendo aplicações corporativas

83

Figura 48: Ferramenta AutoComment.

À esquerda são mostrados os objetos passíveis de documentação, como classes e

métodos. Logo abaixo há uma área indicando a classe sendo documentada, bem como os erros

existentes na documentação e que devem ser corrigidos.

O botão AutoCorrect gera uma documentação básica, indicando o que deve ser

preenchido pelo desenvolvedor no campo Javadoc Comment Text . Este texto deve explicar qual o

objetivo do componente sendo documentado.

O campo Tags provê uma maneira simples de incluir as tags de documentação no texto.

O botão New mostra uma lista com todas as opções disponíveis. Após incluí-la, basta pressionar o

botão Delete para excluí-la.Os botões Move up e Move down movem a tag para cima ou para baixo

da lista, indicando a ordem em que aparecerão na documentação. Finalmente, a lista Name seleciona

uma das tags para que sua descrição seja informada no campo Description.

A qualquer momento, é possível ver como ficará as tags de documentação. Para isto,

basta selecionar a aba do editor que contém o programa sendo documentado, ou então pressionar o

botão View Source. Exemplos de código documentado estão disponíveis no Apêndice B.

Após documentar todos os programas desejados, é necessário gerar a documentação

em formato HTML. Para gerar a documentação, basta seguir os passos:

Page 84: Desenvolvendo aplicações corporativas

84

• Selecione um projeto;

• Acesse o menu de contexto, selecionando a opções Generate Javadoc for Project

(conforme Figura 49);

Figura 49: Geração da documentação.

• Quando o processo for finalizado, será emitida uma mensagem na área de saída do

NetBeans. No exemplo da Figura 50, a mensagem indica que a documentação foi

gerada com sucesso;

Figura 50: Mensagem de sucesso ao gerar a documentação.

• Em caso de sucesso da geração, será aberto um navegador, mostrando a

documentação gerada, como mostra a Figura 51;

Page 85: Desenvolvendo aplicações corporativas

85

Figura 51: Página inicial da documentação.

A página da documentação é dividida em três partes:

• Na parte superior esquerda são mostrados todos os pacotes disponíveis na

documentação. Para mostrar as classes do pacotes, basta acessar seu link. Para

mostrar novamente todas as classes do projeto, basta acessar o link All classes ;

• Na parte inferior esquerda, são listadas as classes pertencentes ao pacote

selecionado. Se nenhum pacote for selecionado (por exemplo, logo ao iniciar o

navegador), serão mostradas todas as classes;

• Na janela à direita é mostrado o conteúdo da documentação, já formatada.

Page 86: Desenvolvendo aplicações corporativas

86

9 CONCLUSÃO

Como exposto neste trabalho, a plataforma Java é uma boa alternativa ao

desenvolvimento de aplicações corporativas, especialmente em sua nova versão Java EE 5.

A separação bem definida entre as diversas camadas da aplicação, que à primeira vista

remete ao pensamento de complexidade de integração, mostra-se fundamental para fins de

organização e manutenção da aplicação. Esta possibilidade de integração, aliada ao grande poder

dos atuais IDE propiciam ao desenvolvedor uma excelente produtividade, uma das características

que as empresas mais buscam atualmente.

A facilidade para se criar aplicações, principal característica da nova versão Java EE 5,

mostrou ser seu ponto forte, conseguindo integrar o poder da plataforma à simplicidade no

desenvolvimento e à simplicidade de integração entre os diversos componentes. Isto permite gerar

aplicativos complexos, ao mesmo tempo em que é mantida a simplicidade do código.

Este conjunto de facilidades prova que o desenvolvimento de aplicações corporativas

utilizando Java EE 5 não só é viável, como também foge do estigma de ser uma tecnologia complexa,

o que o torna uma boa opção para a construção de sistemas de qualquer porte.

Por ser uma tecnologia lançada recentemente, a falta de materiais como livros e tutoriais

(estes disponíveis na internet) que descrevam o desenvolvimento de aplicações corporativas em

todas as camadas é considerado um problema. São poucos títulos disponíveis e os tutoriais cobrem

apenas parte da necessidade.

Dentro desta expectativa, o presente trabalho serve como uma guia que conduzirá os

desenvolvedores à compreensão de conceitos relacionados às camadas de uma aplicação

corporativa. Tais conceitos englobam desde os componentes de configuração de uma aplicação,

como os EJB, containers , session beans e facades , até a infra-estrutura necessária para sua

execução, no caso o servidor de aplicações.

No que pese a escolha de determinadas ferramentas para o desenvolvimento e

execução do aplicativo, a especificação Java é suficientemente rígida para garantir que estes

conceitos possam ser aplicados em qualquer IDE e servidor de aplicações, desde que seja

obedecidas as características destas ferramentas.

Page 87: Desenvolvendo aplicações corporativas

87

Diante disto pode-se concluir que o estudo de uma tecnologia complexa, se amparado

em uma fonte de referência simples e objetiva, pode fornecer resultados rápidos, que servem de base

para estudos mais complexos, estes sim utilizando fontes de referência mais especializadas.

Page 88: Desenvolvendo aplicações corporativas

88

REFERÊNCIAS 2

[BALL 2006] BALL, Jennifer, et al. The Java EE 5 Tutorial. Santa Clara, EUA. Sun Microsystems.2006. 1262 p.

[DBCP] THE APACHE SOFTWARE FOUNDATION. Commons DBCP. Disponível em:<http://jakarta.apache.org/commons/dbcp>. Acesso em: 03 novembro 2006.

[DERBY] THE APACHE SOFTWARE FOUNDATION. Apache Derby. Disponível em:<http://db.apache.org/derby>. Acesso em: 27 outubro 2006.

[FACADE] SUN MICROSYSTEMS. Core J2EE Patterns - Session Facade. Disponível em:<http://docs.sun.com/source/819-0079/dgjndi.html>. Acesso em: 31 outubro 2006.

[GLASSFISH WIKI] GLASSFISH WIKI. List of Features proposed for v2. Disponível em:<http://www.glassfishwiki.org/gfwiki/Wiki.jsp?page=ProposedHighLevelFeaturesForV2>. Acesso em:27outubro 2006.

[GLASSFISH] GLASSFISH COMMUNITY. About GlassFish. Disponível em:<https://glassfish.dev.java.net/public/faq/GF_FAQ_2.html>. Acesso em: 27outubro 2006.

[IMASTERS] IMASTERS. Usando Connection Pooling. Disponível em:<http://www.imasters.com.br/artigo/3033/dotnet/usando_connection_pooling>. Acesso em: 27 outubro2006.

[INFORMIT] INFORMIT.COM. Comparing JSTL and JSP Scriptlet Programming. Disponível em:<http://www.informit.com/articles/article.asp?p=30334&seqNum=2&rl=1>. Acesso em: 30 outubro2006.

[JAVA 01] SUN MICROSYSTEMS. Saiba mais sobre a tecnologia Java. Disponível em:<http://www.java.com/pt_BR/about>. Acesso em: 27 outubro 2006.

[JAVA 02] SUN MICROSYSTEMS. The Java History Timeline. Disponível em:<http://www.java.com/en/javahistory/timeline.jsp>. Acesso em: 10 fevereiro 2006.

[JAVA 03] SUN MICROSYSTEMS. About the Java Technology. Disponível em:<http://java.sun.com/docs/books/tutorial/getStarted/intro/definition.html>. Acesso em: 23 maio 2006.

[JAVA CARD] SUN MICROSYSTEMS. Java Card Platform Specification 2.2.2. Disponível em:<http://java.sun.com/products/javacard/specs.html>. Acesso em: 19 maio 2006.

[JAVA EE] SUN MICROSYSTEMS. Java EE at a Glance. Disponível em:<http://java.sun.com/javaee>. Acesso em: 19 maio 2006.

[JAVA ME] SUN MICROSYSTEMS. Java ME - Micro App Development Made Easy. Disponível em:<http://java.sun.com/javame>. Acesso em: 19 maio 2006.

[JAVA SE] SUN MICROSYSTEMS. Java SE at a Glance. Disponível em:<http://java.sun.com/javase>. Acesso em: 19 maio 2006.

2 Sítios utilizados como referência em mais de um ponto possuem o número da referência logo após o nome do site. Astecnologias do Java são referenciadas separadamente. Livros e assemelhados são identificados com o ano de publicação.

Page 89: Desenvolvendo aplicações corporativas

89

[JAVA NET] THE SOURCE FOR JAVA TECHNOLOGY COLLABORATION. A Brief History of theGreen Project. Disponível em: <http://today.java.net/jag/old/green>. Acesso em: 27 outubro 2006.

[JAVABEANS] SUN MICROSYSTEMS. JavaBeans. Disponível em:<http://java.sun.com/products/javabeans>. Acesso em: 27 outubro 2006.

[JNDI] SUN MICROSYSTEMS. Using the Java Naming and Directory Interface. Disponível em:<http://docs.sun.com/source/819-0079/dgjndi.html>. Acesso em: 28 outubro 2006.

[JVM] SUN MICROSYSTEMS. The Java Virtual Machine Specification. Disponível em:<http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html>. Acesso em: 19maio 2006.

[KVM] SUN MICROSYSTEMS. The K Virtual Machine. Disponível em:<http://java.sun.com/products/cldc/ds>. Acesso em: 19 maio 2006.

[MYSQL] MYSQL AB. History of MySQL. Disponível em:<http://dev.mysql.com/doc/refman/5.0/en/history.html>. Acesso em: 23 junho 2006.

[OMG] OBJECT MANAGEMENT GROUP. Introduction to OMG's Unified Modeling Language (UML).Disponível em <http://www.omg.org/gettingstarted/what_is_uml.htm>. Acesso em 03 novembro 2006.

[PLUGMASTERS] PLUGMASTERS. Framework MVC: Apache Struts ou JavaServer Faces? parte 1.Disponível em: <http://www.plugmasters.com.br/sys/materias/211/1/Framework-MVC:-Apache-Struts-ou-JavaServer-Faces%3F-parte-1>. Acesso em: 27outubro 2006.

[PLUGMASTERS] PLUGMASTERS. Framework MVC: Apache Struts ou JavaServer Faces? parte 1.Disponível em: <http://www.plugmasters.com.br/sys/materias/211/1/Framework-MVC:-Apache-Struts-ou-JavaServer-Faces%3F-parte-1>. Acesso em: 27outubro 2006.

[POSTGRESQL] POSTGRESQL. History. Disponível em: <http://www.postgresql.org/about/history>.Acesso em: 23 junho 2006.

[PRINCETON] WORDNET. Wordnet search. Disponível em:<http://wordnet.princeton.edu/perl/webwn>. Acesso em: 05 novembro 2006.

[SAVANNAH] SAVANNAH. Concurrent Versions System. Disponível em:<http://savannah.nongnu.org/projects/cvs>. Acesso em: 10 fevereiro 2006.

[SRIGANESH 2006] SRIGANESH, Rima Patel; BROSE, Gerald; SILVERMAN, Micah. MasteringEnterprise JavaBeans 3.0. Indianapolis, EUA: Wiley Publishing, Inc. 2006. 688 p.

[STRUTS] THE APACHE SOFTWARE FOUNDATION. Struts. Disponível em:<http://struts.apache.org/1.2.9/index.html>. Acesso em: 27 outubro 2006.

[SUNONE] SUN MICROSYSTEMS. Sun ONE Architecture Guide. Disponível em:<http://www.sun.com/software/sunone/docs/arch>. Acesso em: 27outubro 2006.

[TOMCAT] THE APACHE SOFTWARE FOUNDATION. Apache Tomcat. Disponível em:<http://tomcat.apache.org>. Acesso em: 27 outubro 2006.

[WIKIPEDIA 01] WIKIPEDIA. Java (linguagem de programação). Disponível em:<http://pt.wikipedia.org/wiki/Linguagem_de_programação_Java>. Acesso em: 27 outubro 2006.

[WIKIPEDIA 02] WIKIPEDIA. CRUD (acronym). Disponível em:<http://en.wikipedia.org/wiki/CRUD_(acronym)>. Acesso em: 28 outubro 2006.

[WIRED] WIRED NEWS. The Java Saga. Disponível em:<http://www.wired.com/wired/archive/3.12/java.saga.html?pg=6>. Acesso em 27 outubro 2006.

Page 90: Desenvolvendo aplicações corporativas

90

APÊNDICE A

SCRIPT PARA CRIAÇÃO DAS TABELAS NO BANCO DE DADOS

Page 91: Desenvolvendo aplicações corporativas

91

---- Estrutura da tabela PROJETO--create table projeto ( codProjeto integer not null generated always as identity (start with 1, increment by 1), nome varchar(30) not null, descricao long varchar not null, constraint prj_PK primary key (codProjeto), constraint prj_nome_IDX unique (nome));

---- Estrutura da tabela USUARIO--CREATE TABLE usuario ( codUsuario integer not null generated always as identity (start with 1, increment by 1), login varchar(10) not null, senha varchar(256) not null, nome varchar(30) not null, email varchar(60) not null, constraint usu_PK primary key (codUsuario), constraint usu_email_IDX unique (email));

---- Estrutura da tabela PROJ_USUARIO--CREATE TABLE proj_usuario ( codProjeto int not null, codUsuario int not null, lider varchar(1) not null, constraint prjusu_PK primary key (codProjeto, codUsuario), constraint prjusu_codUsuario_IDX unique (codUsuario, codProjeto, lider), constraint prjusu_prj_FK foreign key (codProjeto) references projeto (codProjeto), constraint prjusu_usu_FK foreign key (codUsuario) references usuario (codUsuario));

Page 92: Desenvolvendo aplicações corporativas

92

APÊNDICE B

MÓDULO EJB

Page 93: Desenvolvendo aplicações corporativas

93

Projeto.java

package entidades.projeto;

import java.io.Serializable;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.Lob;import javax.persistence.Table;

/** * Classe entidade: Projeto * * @author Alessander Fecchio */@Entity@Table(name = "PROJETO")public class Projeto implements Serializable {

/** Código do projeto. */ @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name = "CODPROJETO", nullable = false) private int codprojeto;

/** Nome do projeto. */ @Column(name = "NOME", nullable = false) private String nome;

/** Descrição do projeto. */ @Lob @Column(name = "DESCRICAO", nullable = false) private String descricao; /** Cria uma nova instância de Projeto. */ public Projeto() { }

/** * Cria uma nova instância de Projeto com dados já fornecidos. * @param codprojeto O código do projeto. */ public Projeto(int codprojeto) { this.codprojeto = codprojeto; }

Page 94: Desenvolvendo aplicações corporativas

94

/** * Cria uma nova instância de Projeto com dados já fornecidos. * @param codprojeto O código do projeto. * @param nome O nome do projeto. * @param descricao A descrição do projeto. */ public Projeto(int codprojeto, String nome, String descricao) { this.codprojeto = codprojeto; this.nome = nome; this.descricao = descricao; }

/** * Lê o código o projeto. * @return O código do projeto. */ public int getCodprojeto() { return this.codprojeto; }

/** * Altera o código do projeto para o valor especificado. * @param codprojeto O novo código. */ public void setCodprojeto(int codprojeto) { this.codprojeto = codprojeto; }

/** * Lê o nome do projeto. * @return O nome do projeto. */ public String getNome() { return this.nome; }

/** * Altera o nome do projeto para o valor especificado. * @param nome O novo nome. */ public void setNome(String nome) { this.nome = nome; }

/** * Lê a descrição do projeto. * @return A descrição do projeto. */ public String getDescricao() { return this.descricao; }

/** * Altera a descrição do projeto para o valor especificado. * @param descricao A nova descrição. */ public void setDescricao(String descricao) { this.descricao = descricao; }

Page 95: Desenvolvendo aplicações corporativas

95

/** * Retorna uma representação do objeto na forma de uma String. * @return String com a descrição do objeto. */ @Override public String toString() { return "entidades.projeto.Projeto[codprojeto=" + codprojeto + "] = " + nome; } }

PROJETOFACADE.JAVA

package entidades.projeto;

import java.util.List;import javax.ejb.Stateless;import javax.persistence.EntityManager;import javax.persistence.PersistenceContext;

/** * Classe facade para manipulação de Projeto. * * @author Alessander Fecchio */@Statelesspublic class ProjetoFacade implements ProjetoFacadeRemote {

@PersistenceContext private EntityManager em; /** Cria uma instância de ProjetoFacade */ public ProjetoFacade() { }

/** * Insere um projeto no banco de dados. * @param projeto Projeto a ser inserido. */ public void create(Projeto projeto) { em.persist(projeto); }

/** * Altera um projeto existente no banco de dados. * @param projeto Projeto a ser alterado. */ public void edit(Projeto projeto) { em.merge(projeto); }

/** * Exclui um projeto do banco de dados. * @param projeto Projeto a ser excluído. */ public void destroy(Projeto projeto) { em.remove(em.merge(projeto)); }

Page 96: Desenvolvendo aplicações corporativas

96

/** * Exclui um projeto do banco de dados. * @param id Código do projeto a ser excluído. */ public void destroy(int id) { em.remove(this.find(id)); }

/** * Pesquisa um projeto no banco de dados. * @param pk Dados da chave primária para pesquisa (no caso, * o código do projeto). * @return O projeto localizado, ou então null. */ public Projeto find(Object pk) { return (Projeto) em.find(Projeto.class, pk); }

/** * Pesquisa todos os projetos do banco de dados. Pode provocar queda no * desempenho, de acordo com a quantidade de projetos cadastrados. * @return List contendo os projetos localizados. */ public List findAll() { return em.createQuery("select object(o) from Projeto as o") .getResultList(); }

}

PROJETOFACADEREMOTE.JAVA

package entidades.projeto;

import java.util.List;import javax.ejb.Remote;

/** * Interface remota para acesso à classe ProjetoFacade. * Maiores detalhes podem ser verificados na própria classe. * * @author Alessander Fecchio */@Remotepublic interface ProjetoFacadeRemote {

void create(Projeto projeto);

void edit(Projeto projeto);

void destroy(Projeto projeto);

Projeto find(Object pk);

List findAll();

void destroy(int id); }

Page 97: Desenvolvendo aplicações corporativas

97

USUARIO.JAVA

package entidades.usuario;

import java.io.Serializable;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.Table;

/** * Classe entidade: Usuario * * @author Alessander Fecchio */@Entity@Table(name = "USUARIO")public class Usuario implements Serializable {

/** * Código do usuário. */ @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name = "CODUSUARIO", nullable = false) private int codusuario;

/** * Login do usuário. */ @Column(name = "LOGIN", nullable = false) private String login;

/** * Senha do usuário. */ @Column(name = "SENHA", nullable = false) private String senha;

/** * Nome do usuário. */ @Column(name = "NOME", nullable = false) private String nome;

/** * E-mail do usuário. */ @Column(name = "EMAIL", nullable = false) private String email; /** Cria uma nova instância de Usuario. */ public Usuario() { }

/** * Cria uma nova instância de Projeto com dados já fornecidos. * @param codusuario O código do Usuario. */ public Usuario(int codusuario) { this.codusuario = codusuario; }

Page 98: Desenvolvendo aplicações corporativas

98

/** * Cria uma nova instância de Projeto com dados já fornecidos. * @param codusuario Código do usuário. * @param login Login do usuário. * @param senha Senha do usuário. * @param nome Nome do usuário. * @param email E-mail do usuário. */ public Usuario(int codusuario, String login, String senha, String nome, String email) { this.codusuario = codusuario; this.login = login; this.senha = senha; this.nome = nome; this.email = email; }

/** * Lê o código do Usuario. * @return O código do usuário. */ public int getCodusuario() { return this.codusuario; }

/** * Altera o código do usuário para o novo valor. * @param codusuario O novo código. */ public void setCodusuario(int codusuario) { this.codusuario = codusuario; }

/** * Lê o login do usuário. * @return O login do usuário. */ public String getLogin() { return this.login; }

/** * Altera o login do usuário para o novo valor. * @param login O novo login. */ public void setLogin(String login) { this.login = login; }

/** * Lê a senha do usuário. * @return A senha do usuário. */ public String getSenha() { return this.senha; }

/** * Altera a senha do usuário para o novo valor. * @param senha A nova senha. */ public void setSenha(String senha) { this.senha = senha; }

Page 99: Desenvolvendo aplicações corporativas

99

/** * Lê o nome do usuário. * @return O nome do usuário. */ public String getNome() { return this.nome; }

/** * Altera o nome do usuário para o novo valor. * @param nome O novo nome. */ public void setNome(String nome) { this.nome = nome; }

/** * Lê o e-mail do usuário. * @return O e-mail do usuário. */ public String getEmail() { return this.email; }

/** * Altera o e-mail do usuário para o novo valor. * @param e-mail O novo e-mail. */ public void setEmail(String email) { this.email = email; }

/** * Retorna uma representação do objeto na forma de uma String. * @return String com a descrição do objeto. */ @Override public String toString() { return "entidades.usuario.Usuario[codusuario=" + codusuario + "] - " + nome; } }

USUARIOFACADE.JAVA

package entidades.usuario;

import java.util.List;import javax.ejb.Stateless;import javax.persistence.EntityManager;import javax.persistence.PersistenceContext;import javax.persistence.Query;import utils.Criptografia;

/** * Classe facade para a entidade Usuario. * @author Alessander Fecchio */@Statelesspublic class UsuarioFacade implements UsuarioFacadeRemote {

Page 100: Desenvolvendo aplicações corporativas

100

/** * O contexto de persistência. */ @PersistenceContext private EntityManager em; /** * Objeto utilizado para docificar e decodificar strings. */ private Criptografia cripto; /** Contrutor padrão */ public UsuarioFacade() { try { cripto = new Criptografia(); } catch (Exception ex) { ex.printStackTrace(); } } /** * Insere um usuário no banco de dados. * @param usuario Usuário a ser inserido. */ public void create(Usuario usuario) { try { cripto = new Criptografia(); usuario.setSenha(cripto.codificar(usuario.getSenha())); em.persist(usuario); } catch (Exception ex) { ex.printStackTrace(); } } /** * Altera um usuário do banco de dados. * @param usuario O usuário a ser alterado. */ public void edit(Usuario usuario) { em.merge(usuario); } /** * Exclui um usuário do banco de dados. * @param usuario Usuário a ser excluído. */ public void destroy(Usuario usuario) { em.remove(em.merge(usuario)); } /** * Exclui um usuário do banco de dados, localizando-o pelo seu código. * @param id Código do usuário a ser excluído. */ public void destroy(int id) { em.remove(this.find(id)); } /** * Pesquisa um usuário no banco de dados. * @param pk O código do usuário a ser localizado. * @return O usuário, se ele for localizado. */ public Usuario find(Object pk) { return (Usuario) em.find(Usuario.class, pk); }

Page 101: Desenvolvendo aplicações corporativas

101

/** * Pesquisa todos os usuários do banco de dados. * @return Um List com todo os usuários cadastrados. */ public List findAll() { return em.createQuery("select object(o) from Usuario as o") .getResultList(); } /** * Pesquisa um usuário pelo seu login. * @param login Login do usuário a ser encontrado. * @return O usuário com o login especificado, se ele for localizado. */ public Usuario findByLogin(String login) { String s = "select object(o) from Usuario as o " + "where o.login=:prmLogin"; Query q = em.createQuery(s); q.setParameter("prmLogin", login); Usuario result = (Usuario) q.getSingleResult(); return result; } /** * Autentica um usuário e senha. * @param login Login do usuário. * @param senha Senha do usuário. * @return Um valor booleano true (se o usuário e senha estiverem * corretos) ou false (caso não estejam). */ public boolean autentica(String login, String senha) { boolean result = false; Usuario usuario = findByLogin(login); if (usuario==null) { result = false; } else { try { senha = cripto.codificar(senha); result = usuario.getSenha().equals( senha ); } catch (Exception ex) { result = false; } } return result; } }

USUARIOFACADEREMOTE.JAVA

package entidades.usuario;

import java.util.List;import javax.ejb.Remote;

/** * Interface remota para acesso à classe UsuarioFacade. * Maiores detalhes podem ser verificados na própria classe. * * @author Alessander Fecchio */

Page 102: Desenvolvendo aplicações corporativas

102

@Remotepublic interface UsuarioFacadeRemote { void create(Usuario usuario);

void edit(Usuario usuario);

void destroy(Usuario usuario);

Usuario find(Object pk);

List findAll();

void destroy(int id);

Usuario findByLogin(String login);

boolean autentica(String login, String senha);

}

PROJETOUSUARIO.JAVA

package entidades.projetousuario;

import entidades.projeto.Projeto;import entidades.usuario.Usuario;import java.io.Serializable;import javax.persistence.Column;import javax.persistence.EmbeddedId;import javax.persistence.Entity;import javax.persistence.JoinColumn;import javax.persistence.ManyToOne;import javax.persistence.Table;

/** * Entidade: ProjetoUsuario (associação indicando em * quais projetos cada usuário está alocado) * * @author Alessander Fecchio */@Entity@Table(name = "PROJ_USUARIO")public class ProjetoUsuario implements Serializable {

/** Chave primária */ @EmbeddedId protected ProjetoUsuarioPK projetoUsuarioPK;

/** Indica se o usuário é lider do projeto indicado. */ @Column(name = "LIDER", nullable = false) private String lider;

/** O projeto ao qual o usuário está alocado */ @JoinColumn(name = "CODPROJETO", referencedColumnName = "CODPROJETO", insertable = false, updatable = false) @ManyToOne private Projeto projeto;

Page 103: Desenvolvendo aplicações corporativas

103

/** Usuário alocado ao projeto */ @JoinColumn(name = "CODUSUARIO", referencedColumnName = "CODUSUARIO", insertable = false, updatable = false) @ManyToOne private Usuario usuario; /** Cria uma instância de ProjetoUsuario */ public ProjetoUsuario() { }

/** * Cria uma instância de ProjetoUsuario, com valores já * iniciados. * @param projetoUsuarioPK A chave primária do ProjetoUsuario. */ public ProjetoUsuario(ProjetoUsuarioPK projetoUsuarioPK) { this.projetoUsuarioPK = projetoUsuarioPK; }

/** * Cria uma instância de ProjetoUsuario, com valores já * iniciados. * @param projetoUsuarioPK A chave primária do ProjetoUsuario. * @param lider Indica se o usuário é lider ("S") ou não ("N") do projeto * em questão. */ public ProjetoUsuario(ProjetoUsuarioPK projetoUsuarioPK, String lider) { this.projetoUsuarioPK = projetoUsuarioPK; this.lider = lider; }

/** * Cria uma instância de ProjetoUsuario, com valores já * iniciados. * @param codusuario Código do usuário. * @param codprojeto Código do projeto. * @param lider Indica se o usuário é lider ("S") ou não ("N") do projeto * em questão. */ public ProjetoUsuario(int codusuario, int codprojeto, String lider) { this.projetoUsuarioPK = new ProjetoUsuarioPK(codusuario, codprojeto); this.lider = lider; }

/** * Método para cria um ProjetoUsuario a partir dos códigos de * projeto e usuário. * @param codusuario O código do usuário. * @param codprojeto O código do projeto. */ public ProjetoUsuario(int codusuario, int codprojeto) { this.projetoUsuarioPK = new ProjetoUsuarioPK(codusuario, codprojeto); }

/** * Retorna a chave primária de ProjetoUsuario. * @return A chave primária. */ public ProjetoUsuarioPK getProjetoUsuarioPK() { return this.projetoUsuarioPK; }

Page 104: Desenvolvendo aplicações corporativas

104

/** * Define a chave primária do ProjetoUsuario. * @param projetoUsuarioPK A chave primária. */ public void setProjetoUsuarioPK(ProjetoUsuarioPK projetoUsuarioPK) { this.projetoUsuarioPK = projetoUsuarioPK; }

/** * Lê o conteúdo do campo lider. * @return String indicando se o usuário é lider ("S") ou não ("N") do * projeto. */ public String getLider() { return this.lider; }

/** * Altera o indicador de liderança para o novo valor. * @param lider O novo valor de lider. */ public void setLider(String lider) { this.lider = lider; } /** * Indicando se o usuário é lider ou não do projeto * @return Boolean indicando se o usuário é lider (true) ou não (false) do * projeto */ public boolean isLider() { return (this.getLider().equalsIgnoreCase("s")); }

/** * Lê o projeto de ProjetoUsuario. * @return O Projeto. */ public Projeto getProjeto() { return this.projeto; }

/** * Altera o Projeto para do ProjetoUsuario. * @param projeto O novo projeto. */ public void setProjeto(Projeto projeto) { this.projeto = projeto; }

/** * Lê o usuário do ProjetoUsuario. * @return O usuário. */ public Usuario getUsuario() { return this.usuario; }

/** * Altera o Usuario do ProjetoUsuario. * @param usuario O novo Usuario. */ public void setUsuario(Usuario usuario) { this.usuario = usuario; }

Page 105: Desenvolvendo aplicações corporativas

105

/** * Retorna uma representação do objeto na forma de uma String. * @return String com a descrição do objeto. */ @Override public String toString() { return "entidades.projetousuario.ProjetoUsuario[projetoUsuarioPK=" + projetoUsuarioPK + "]"; } }

PROJETOUSUARIOFACADE.JAVA

package entidades.projetousuario;

import java.util.List;import javax.ejb.Stateless;import javax.jws.WebService;

import javax.persistence.EntityManager;import javax.persistence.PersistenceContext;import javax.persistence.Query;

/** * Classe para manipulação de ProjetoUsuario no banco de dados. * * @author Alessander Fecchio */@Statelesspublic class ProjetoUsuarioFacade implements ProjetoUsuarioFacadeRemote {

/** Contexto de persistência, utilizado para realizar operações no * banco de dados. */ @PersistenceContext private EntityManager em; /** Cria uma instância de ProjetoUsuarioFacade. */ public ProjetoUsuarioFacade() { }

/** * Insere um ProjetoUsuario no banco de dados. * @param projetoUsuario O ProjetoUsuario a ser gravado. */ public void create(ProjetoUsuario projetoUsuario) { em.persist(projetoUsuario); }

/** * Altera um ProjetoUsuario gravado no banco de dados. * @param projetoUsuario O ProjetoUsuario a ser gravado. */ public void edit(ProjetoUsuario projetoUsuario) { em.merge(projetoUsuario); }

Page 106: Desenvolvendo aplicações corporativas

106

/** * Exclui um ProjetoUsuario gravado no banco de dados. * @param projetoUsuario O ProjetoUsuario a ser excluído. */ public void destroy(ProjetoUsuario projetoUsuario) { em.remove(em.merge(projetoUsuario)); }

/** * Pesquisa um ProjetoUsuario gravado no banco de dados. * A chave primária é um objeto do tipo ProjetoUsuarioPK. * @param pk ProjetoUsuarioPK contendo o projeto e usuário a * ser pesquisado. * @return Um ProjetoUsuario correspondente à chave primária. * Se não for encontrado, retornará um ProjetoUsuario vazio. */ public ProjetoUsuario find(Object pk) { return (ProjetoUsuario) em.find(ProjetoUsuario.class, pk); }

/** * Retorna todos os ProjetoUsuario gravados no banco de dados. * @return Todos os ProjetoUsuario gravados no banco de dados. */ public List findAll() { return em.createQuery("select object(o) from ProjetoUsuario as o") .getResultList(); }

/** * Pesquisa todos os projetos ligados a um determinado usuário. * @param codUsuario Código do usuário de quem os projetos serão * pesquisados. * @return List com todos os projetos dos quais o usuário participa. */ public List findProjetosPorUsuario(int codUsuario) { String q = "select object(o) from ProjetoUsuario as o " + "where o.usuario.codusuario=:codUsuario"; Query query = em.createQuery(q); query.setParameter("codUsuario", codUsuario); List result = query.getResultList(); return result; }

}

PROJETOUSUARIOFACADEREMOTE.JAVA

package entidades.projetousuario;

import java.util.List;import javax.ejb.Remote;

/** * Interface remota para acesso à classe ProjetoUsuarioFacade. * Maiores detalhes podem ser verificados na própria classe. * * @author Alessander Fecchio */

Page 107: Desenvolvendo aplicações corporativas

107

@Remotepublic interface ProjetoUsuarioFacadeRemote { void create(ProjetoUsuario projetoUsuario);

void edit(ProjetoUsuario projetoUsuario);

void destroy(ProjetoUsuario projetoUsuario);

ProjetoUsuario find(Object pk);

List findAll();

List findProjetosPorUsuario(int codUsuario); }

PROJETOUSUARIOPK.JAVA

package entidades.projetousuario;

import java.io.Serializable;import javax.persistence.Column;import javax.persistence.Embeddable;

/** * Chave primária da entidade ProjetoUsuario * * @author Alessander Fecchio */@Embeddablepublic class ProjetoUsuarioPK implements Serializable { /** Código do projeto. */ @Column(name = "CODPROJETO", nullable = false) private int codprojeto; /** Código do usuário */ @Column(name = "CODUSUARIO", nullable = false) private int codusuario; /** Cria uma nova instância de ProjetoUsuarioPK */ public ProjetoUsuarioPK() { } /** * Cria uma nova instância de ProjetoUsuarioPK com valores * já definidos. * @param codusuario O código do usuário. * @param codprojeto O código do projeto. */ public ProjetoUsuarioPK(int codusuario, int codprojeto) { this.codusuario = codusuario; this.codprojeto = codprojeto; } /** * Lê o código do projeto. * @return O código do projeto. */ public int getCodprojeto() { return this.codprojeto; }

Page 108: Desenvolvendo aplicações corporativas

108

/** * Altera o código do projeto. * @param codprojeto O novo código do projeto. */ public void setCodprojeto(int codprojeto) { this.codprojeto = codprojeto; } /** * Lê o código do usuário. * @return O código do usuário. */ public int getCodusuario() { return this.codusuario; } /** * Altera o código do usuário. * @param codusuario O novo código do usuário. */ public void setCodusuario(int codusuario) { this.codusuario = codusuario; } /** * Retorna uma representação do objeto na forma de uma String. * @return String com a descrição do objeto. */ @Override public String toString() { return "entidades.projetousuario.ProjetoUsuarioPK[codusuario=" + codusuario + ", codprojeto=" + codprojeto + "]"; } }

MENSAGEM.JAVA

package utils;

/** * Classe auxiliar utilizada para criar mensagens para envio ao log do * servidor de aplicações. * @author Alessander Fecchio */public class Mensagem { /** Construtor padrão. */ public Mensagem() { }

Page 109: Desenvolvendo aplicações corporativas

109

/** * Cria uma String, contendo qtd repetições da string msg. * @param msg String a ser repetida. * @param qtd Quantidade de vezes que msg será repetida. * @return Uma String contendo qtd repetições de msg. */ public static String replicate(String msg, int qtd) { String result = ""; for (int i=0; i<qtd; i++) { result += msg; } return result; }

/** * Formata a mensagem a ser enviada ao log. * @param msg Mensagem a ser enviada ao log. * @return A mensagem formatada. */ public static String erroConsole(String msg) { String linha = replicate("-", msg.length()); String result = "\n"; result += "+-" + linha + "-+\n"; result += "| " + msg + " |\n"; result += "+-" + linha + "-+\n"; return result; }}

CRIPTOGRAFIA.JAVA

package utils;

import com.sun.crypto.provider.SunJCE;import java.security.Security;import java.security.spec.AlgorithmParameterSpec;import java.security.spec.KeySpec;import javax.crypto.Cipher;import javax.crypto.SecretKey;import javax.crypto.SecretKeyFactory;import javax.crypto.spec.DESedeKeySpec;

/** * Classe para codificação e decodificação de Strings. * Utilizada para criptografia das senhas. * * @author Alessander Fecchio */public class Criptografia { /** Chave a ser utilizada nos processos de codificação e decodificação. */ private SecretKey chaveSecreta; /** * Interface para criação de parâmetros criptográficos. */ private AlgorithmParameterSpec paramSpec = null;

Page 110: Desenvolvendo aplicações corporativas

110

/** * Cria uma nova instância de Criptografia. * @throws Exception Exceção genérica. */ public Criptografia() throws Exception { /* cada elemento é um código ASCII convertido para hexadecimal e * typecasted para byte. * DICA: pode-se mudar a chave padrão para mesclar dados próprios do * usuário, como nome, sobrenome, etc, */ byte[] chavePadrao = { (byte)0x73, (byte)0x33, (byte)0x57, (byte)0x43, (byte)0x55, (byte)0x40, (byte)0x38, (byte)0x6C, (byte)0xDE, (byte)0x90, (byte)0x21, (byte)0x2C, (byte)0xB5, (byte)0x2A, (byte)0xFF, (byte)0x3C, (byte)0xE1, (byte)0xB1, (byte)0x29, (byte)0x40, (byte)0xD9, (byte)0x96, (byte)0x9F, (byte)0xAB }; SunJCE provider = new SunJCE(); Security.addProvider(provider); geraChaveSecreta(chavePadrao); } /** * Converte um array de bytes em uma string hexadecimal. * Durante o processo, é efetuado um deslocamento bit a bit, de modo a * aumentar a complexidade da chave e, conseqüentemente, sua segurança. * @param block Array de bytes a ser convertido. * @return Uma string codificada, contendo hexadecimais. */ private String toHexString(byte[] block) { String hexits = "0123456789ABCDEF"; StringBuffer buf = new StringBuffer(); for (int i = 0; i < block.length; i++) { buf.append(hexits.charAt((block[i] >>> 4) & 0xf)); buf.append(hexits.charAt(block[i] & 0xf)); } return buf.toString(); } /** * Converte uma string hexadecimal em um array de bytes. * @param valueHexa Strinf de hexadecimais. * @return Um array de bytes. */ private byte[] toByteArray(String valueHexa) { byte[] array = new byte[valueHexa.length() / 2]; for (int i = valueHexa.length(); i > 0; i -= 2) { array[(i / 2) - 1] = (byte) Integer.parseInt(valueHexa.substring(i - 2, i), 16); } return array; }

Page 111: Desenvolvendo aplicações corporativas

111

/** * Método utilizado para gerar um SecretKey utilizado no * processo de criptografia. * @param chave Um array de bytes contendo a chave. * @throws Exception Exceção genérica. */ private void geraChaveSecreta(byte[] chave) throws Exception { KeySpec keySpec; keySpec = new DESedeKeySpec(chave); // Gera a chave secreta SecretKeyFactory factory = SecretKeyFactory.getInstance("TripleDES"); chaveSecreta = factory.generateSecret(keySpec); } /** * Codifica uma string. * @param mensagem String a ser codificada. * @throws Exception Exceção genérica. * @return Uma string codificada, contendo hexadecimais. */ public String codificar(String mensagem) throws Exception { Cipher cipher = Cipher.getInstance("TripleDES"); cipher.init(Cipher.ENCRYPT_MODE, chaveSecreta, paramSpec); return toHexString(cipher.doFinal(mensagem.getBytes())); } /** * Decofica uma string já codificada. * @param mensagem String a ser decodificado. * @throws Exception wexceção genérica. * @return A String original, antes de ser codificada. */ public String decodificar(String mensagem) throws Exception { Cipher cipher = Cipher.getInstance("TripleDES"); cipher.init(Cipher.DECRYPT_MODE, chaveSecreta, paramSpec); return new String(cipher.doFinal(toByteArray(mensagem))); } }

Page 112: Desenvolvendo aplicações corporativas

112

APÊNDICE C

MÓDULO CLIENTE DESKTOP

Page 113: Desenvolvendo aplicações corporativas

113

MAIN.JAVA

package maxigroupware; import entidades.projeto.Projeto; import entidades.projeto.ProjetoFacadeRemote; import java.sql.Timestamp; import java.util.List; import java.util.Properties; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NameNotFoundException; import javax.naming.NamingException;

/** * Aplicação cliente, executada pela linha de comando, * para teste de manipulação de EJB. * @author Alessander Fecchio */ public class Main { /** Interface para acesso à entidade Projeto. */ private static ProjetoFacadeRemote projetoFR;

/** * Método executável da classe. * @param args Lista de argumentos passados via linha de comando. * O método escreveSintaxe contém todas as sintaxes válidas. */ public static void main(String[] args) { Main teste = new Main(); teste.executa(args); }

/** * Método chamado pelo método main(), executa todas * as operações possíveis. * @param args Lista de argumentos passada via linha de comando. */ private void executa(String[] args) { try { Properties p = System.getProperties(); p.put(Context.PROVIDER_URL, "localhost:1099"); Context ctx = new InitialContext(p); try { projetoFR = (ProjetoFacadeRemote) ctx.lookup("entidades.projeto.ProjetoFacadeRemote"); } catch (NameNotFoundException ex) { System.out.println(utils.Mensagem.erroConsole( "EJB não encontrado: ProjetoFacadeRemote")); System.exit(1); }

Page 114: Desenvolvendo aplicações corporativas

114

if (! verificaParametros(args)) { System.exit(1); } if (args[0].equals("-l")) { lista(""); } else { lista("ANTES"); if (args[0].equals("-c")) { create(); } else if (args[0].equals("-r")) { recover(args[1]); } else if (args[0].equals("-u")) { update(args[1]); } else if (args[0].equals("-d")) { delete(args[1]); } lista("DEPOIS"); } } catch (NamingException ex) { ex.printStackTrace(); } }

/** * Lista todos os projetos cadastrados. * @param s Mensagem a ser impressa no cabeçalho da lista. */ private void lista(String s) { System.out.println("\n--- Lista " + s + " ---"); List lista = projetoFR.findAll(); for (Object o : lista) { System.out.println(" " + o.toString()); } System.out.println(); } /** * Cria um projeto. Inclui um Timestamp no nome e da descrição. * Deste modo, é possível incluir vários projetos sem informar * estes dados, que serão gerados dinamicamente. */ private void create() { System.out.println("\n--- Criando ---"); Timestamp timestamp = new Timestamp(System.currentTimeMillis()); Projeto p = new Projeto(); p.setNome("Prj: " + timestamp); p.setDescricao("Criado em " + timestamp); projetoFR.create(p); System.out.println(" " + p.toString()); System.out.println(); } /** * Pesquisa um projeto gravado no banco de dados. * Se encontrar, mostra seus dados. Caso contrário, * emite uma mensagem de erro. * O código do projeto deve ser informado na linha * de comando e ser um projeto válido. * @param s Código do projeto a ser pesquisado. */ private void recover(String s) { int codigo = Integer.parseInt(s); System.out.println("\n--- Recuperando projeto " + s + " ---");

Page 115: Desenvolvendo aplicações corporativas

115

Projeto p = projetoFR.find(codigo); if (p==null) { System.out.println(" Projeto nao encontrado: " + s); } else { System.out.println(" " + p.toString()); } System.out.println(); }

/** * Exclui um projeto do banco de dados. * O código do projeto deve ser informado na linha * de comando e ser um projeto válido. * @param s Código do projeto a ser excluído. */ private void delete(String s) { int codigo = Integer.parseInt(s); System.out.println("\n--- Excluindo projeto " + s + " ---"); projetoFR.destroy(codigo); System.out.println(); }

/** * Atualiza um projeto no banco de dados. * O código do projeto deve ser informado na linha * de comando e ser um projeto válido. * A alteração é a substituição do Timestamp da criação * pelo da alteração. * @param s Código do projeto a ser atualizado. */ private void update(String s) { int codigo = Integer.parseInt(s); System.out.println("\n--- Atualizando projeto " + s + " ---"); Projeto p = projetoFR.find(codigo); if (p==null) { System.out.println(" Projeto nao encontrado: " + s); } else { System.out.println(" Antes da alteracao: " + p.toString()); Timestamp timestamp = new Timestamp(System.currentTimeMillis()); p.setNome("Prj: " + timestamp); p.setDescricao("Alterado em " + timestamp); projetoFR.edit(p); System.out.println(" Depois: " + p.toString()); } System.out.println(); } /** * Verifica se os parâmetros passados via linha * de comando são válidos. Se não forem, o aplicativo * é finalizado. * @param args Argumentos passados via linha de comando. * @return Booleando indicando se os parâmetros são * válidos (true) ou não (false). */ private boolean verificaParametros(String[] args) { boolean result = true; // parâmetros não informados if (args.length == 0) { escreveSintaxe("Nenhum parametro informado"); return false; };

Page 116: Desenvolvendo aplicações corporativas

116

args[0] = args[0].toLowerCase(); String aux = "-c-r-u-d-l"; if (args[0].startsWith("-") && aux.contains(args[0])) { // parâmetro válido aux = "-r-u-d"; if (aux.contains(args[0]) && args.length<2) { // código não informado escreveSintaxe("Codigo do projeto nao informado."); return false; } else if (aux.contains(args[0])) { try { int tmp = Integer.parseInt(args[1]); } catch (NumberFormatException ex) { escreveSintaxe("Codigo deve ser um numero inteiro."); return false; } } } else { // parâmetro inválido escreveSintaxe("Parametro invalido."); return false; } return true; }

/** * Escreve a sintaxe do aplicativo na tela, com uma * mensagem de cabeçalho. * @param s Mensagem a ser exibida no cabeçalho. */ public void escreveSintaxe(String s) { System.out.println("\n\n" + s); System.out.println("+----------------------+"); System.out.println("| PARA UTILIZE |"); System.out.println("| ----- --------- |"); System.out.println("| Listar -l |"); System.out.println("| Criar -c |"); System.out.println("| Pesquisar -r codigo |"); System.out.println("| Atualizar -u codigo |"); System.out.println("| Excluir -d codigo |"); System.out.println("+----------------------+"); } }

CREATEUSER.JAVA

package maxigroupware;import entidades.usuario.Usuario;import entidades.usuario.UsuarioFacadeRemote;import java.util.List;import java.util.Properties;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NameNotFoundException;import javax.naming.NamingException;

/** @author Alessander Fecchio */public class CreateUser {

/** Interface para acesso à entidade Usuario. */ private static UsuarioFacadeRemote usuarioFR;

Page 117: Desenvolvendo aplicações corporativas

117

/** * Método executável da classe. * @param args Lista de argumentos passados via linha de comando. * O método escreveSintaxe contém todas as sintaxes válidas. */ public static void main(String[] args) { CreateUser teste = new CreateUser(); teste.executa(args); } /** * Lista todos os usuarios cadastrados. * @param s Mensagem a ser impressa no cabeçalho da lista. */ private void lista(String s) { System.out.println("\n--- Lista " + s + " ---"); List lista = usuarioFR.findAll(); for (Object o : lista) { System.out.println(" " + o.toString()); } System.out.println(); }

/** * Método chamado pelo método main(), cria o usuário solicitado. * @param args Lista de argumentos passada via linha de comando. */ private void executa(String[] args) { try { Properties p = System.getProperties(); p.put(Context.PROVIDER_URL, "localhost:1099"); Context ctx = new InitialContext(p); try { usuarioFR = (UsuarioFacadeRemote) ctx.lookup("entidades.usuario.UsuarioFacadeRemote"); } catch (NameNotFoundException ex) { System.out.println(utils.Mensagem.erroConsole( "EJB não encontrado: UsuarioFacadeRemote")); System.exit(1); } if (args.length <4) { System.out.println("\nNumero de parametros incorreto."); System.out.println("\nUTILIZE"); System.out.println(" CreateUser <login> <senha> <nome> <email> |"); System.out.println("\nDados que contenham espacos em branco " + "devem ser informados entre aspas."); System.exit(1); }; lista("ANTES"); /* Criação do usuario */ System.out.println("\n--- Criando ---"); Usuario usuario = new Usuario(); usuario.setLogin(args[0]); usuario.setSenha(args[1]); usuario.setNome(args[2]); usuario.setEmail(args[3]); usuarioFR.create(usuario); System.out.println(" " + usuario.toString() + " criado."); System.out.println(); lista("DEPOIS"); } catch (NamingException ex) { ex.printStackTrace(); } } }

Page 118: Desenvolvendo aplicações corporativas

118

APÊNDICE DMÓDULO APLICATIVO WEB

Page 119: Desenvolvendo aplicações corporativas

119

INDEX.JSP

<script> document.location="./faces/login.jsp"</script>

LOGIN.JSP

<%@ include file="/recursos/cabecalho.jsp" %><f:view><h1>Não Autenticado</h1> <h:messages errorClass="errorMessage" infoClass="successMessage"

layout="table" /></p> <h:form id="form1"> <h:panelGrid columns="2" id="panelGrid1"> <h:outputText value="Login" id="outLogin"/> <h:inputText binding="#{Login.login}" id="login"/> <h:outputText value="Senha" id="outputText2"/> <h:inputSecret binding="#{Login.senha}" id="senha"/> </h:panelGrid> <p> <h:commandButton value="Login" id="enviar"

action="#{Login.autenticar}"/> </p> </h:form> </f:view><%@ include file="/recursos/rodape.jsp" %>

MENSAGENS/LOGIN_ERRO.JSP

<%@ include file="/recursos/cabecalho.jsp" %><f:view> <h1>Não Autenticado</h1> <h:messages errorStyle="color: red" infoStyle="color: green" layout="table" /></f:view><p><a href="./faces/login.jsp">Login</a><p/><%@ include file="/recursos/rodape.jsp" %>

mensagens/login_ok.jsp

<%@ include file="/recursos/cabecalho.jsp" %><%@ page import="entidades.usuario.Usuario" %><f:view> <h1>Autenticado</h1> <h:messages errorStyle="color: red" infoStyle="color: green" layout="table" /> </p> <h:outputText value="Usuario: #{Login.usuario}" /></f:view><p><a href="./faces/login.jsp">Login</a><p/><%@ include file="/recursos/rodape.jsp" %>

Page 120: Desenvolvendo aplicações corporativas

120

RECURSOS/ESTILOS.CSS

body, p { font-family: Verdana, Helvetica, sans-serif; font-size:9pt; color:#000000;}

h1 { font-family: Verdana, Helvetica, sans-serif; color:#336699; width : 100%; font-size:170%; border : solid #CCCC99; border-width : 0px 0px 2px 0px;}

RECURSOS/CABECALHO.JSP

<%@page contentType="text/html"%><%@page pageEncoding="UTF-8"%><%@taglib uri="http://java.sun.com/jsf/core" prefix="f" %><%@taglib uri="http://java.sun.com/jsf/html" prefix="h" %><html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link href="/maxi/recursos/estilos.css" rel="stylesheet"/> <title>MaxiGroupware</title> </head> <body>

recursos/rodape.jsp

</body></html>

FACES_CONFIG.XML

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer FacesConfig 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd"><faces-config xmlns="http://java.sun.com/JSF/Configuration"> <managed-bean> <managed-bean-name>Login</managed-bean-name> <managed-bean-class>manage.Login</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> <navigation-rule> <from-view-id>/login.jsp</from-view-id> <navigation-case> <from-action>#{Login.autenticar}</from-action> <from-outcome>autenticado</from-outcome> <to-view-id>/mensagens/login_ok.jsp</to-view-id> </navigation-case> <navigation-case> <from-action>#{Login.autenticar}</from-action> <from-outcome>nao_autenticado</from-outcome> <to-view-id>/mensagens/login_erro.jsp</to-view-id> </navigation-case> </navigation-rule></faces-config>

Page 121: Desenvolvendo aplicações corporativas

121

WEB.XML

<?xml version="1.0" encoding="UTF-8"?><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<context-param> <param-name>com.sun.faces.verifyObjects</param-name> <param-value>false</param-value> </context-param> <context-param> <param-name>com.sun.faces.validateXml</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>client</param-value> </context-param> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> <session-config> <session-timeout>30</session-timeout> </session-config> <welcome-file-list>

<welcome-file>index.jsp</welcome-file> </welcome-file-list></web-app>

SUN-WEB.XML

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 Servlet 2.5//EN""http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd">

<sun-web-app error-url=""> <context-root>/maxi</context-root> <class-loader delegate="true"/> <jsp-config> <property name="classdebuginfo" value="true"> <description>Enable debug info compilation in the generated servletclass</description> </property> <property name="mappedfile" value="true"> <description>Maintain a one-to-one correspondence between static content andthe generated servlet class' java code</description> </property> </jsp-config></sun-web-app>

Page 122: Desenvolvendo aplicações corporativas

122

MANAGE/LOGIN.JAVA

package manage; import entidades.usuario.Usuario; import entidades.usuario.UsuarioFacadeRemote; import javax.ejb.EJB; import javax.faces.application.FacesMessage; import javax.faces.component.html.HtmlCommandButton; import javax.faces.component.html.HtmlInputSecret; import javax.faces.component.html.HtmlInputText; import javax.faces.context.FacesContext; import utils.Criptografia;

/** * Bean gerenciado para manipular informações do login do usuário. * @author Alessander Fecchio */ public class Login { /** Referência ao EJB UsuarioFacade através de sua interface remota. */ @EJB(beanName="UsuarioFacade", beanInterface=UsuarioFacadeRemote.class) private UsuarioFacadeRemote usuarioFR;

/** Objeto Usuario, para manipulação das informações. */ private Usuario usuario=null; /** * Instância da classe Criptografia, utilizada para * codificar e decodificar informações. */ private Criptografia cripto; /** Componente visual da página JSF para informar o login do usuário. */ private HtmlInputText login; /** Componente visual da página JSF para informar a senha do usuário. */ private HtmlInputSecret senha; /** Botão Enviar. */ private HtmlCommandButton enviar; /** * Busca o objeto representando o componente visual Login. * @return O componente visual Login. */ public HtmlInputText getLogin() { return login; } /** * Altera o conteúdo do componente visual Login. * @param login O novo login. */ public void setLogin(HtmlInputText login) { this.login = login; } /** * Busca o objeto representando o componente visual Senha. * @return O componente visual Login. */ public HtmlInputSecret getSenha() { return senha; }

Page 123: Desenvolvendo aplicações corporativas

123

/** * Altera o conteúdo do componente visual Senha. * @param senha A nova senha. */ public void setSenha(HtmlInputSecret senha) { this.senha = senha; }

/** * Autentica o usuário utilizando o login e senha informados. * @return String contendo a próxima página a ser mostrada, * de acordo com o resultado da autenticação. */ public String autenticar() { String result = "nao_autenticado"; String usuarioForm = getLogin().getValue().toString(); String senhaForm = getSenha().getValue().toString(); boolean autenticado = false; try { if (usuarioForm.equals("") || senhaForm.equals("")) { addErrorMessage("Informe o login e a senha!"); } else { autenticado = usuarioFR.autentica(usuarioForm, senhaForm); if (autenticado) { setUsuario(usuarioFR.findByLogin(usuarioForm)); FacesContext facesContext=FacesContext.getCurrentInstance(); facesContext.getExternalContext() .getSessionMap().put("_usuario", getUsuario()); addSuccessMessage("Autenticação OK!"); } else { throw new Exception("Erro"); } } } catch (Exception e) { setUsuario(null); addErrorMessage("Erro na autenticação do usuário. " + "Certifique-se que informou os dados corretos!"); } return (autenticado ? "autenticado" : "nao_autenticado"); } /** * Adiciona uma mensagem de erro à lista de mensagens da sessão. * @param msg A mensagem a ser adicionada. */ public static void addErrorMessage(String msg) { FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg); FacesContext fc = FacesContext.getCurrentInstance(); fc.addMessage(null, facesMsg); } /** * Adiciona uma mensagem de erro à lista de mensagens da sessão. * @param msg A mensagem a ser adicionada. */ public static void addSuccessMessage(String msg) { FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg); FacesContext fc = FacesContext.getCurrentInstance(); fc.addMessage(null, facesMsg); }

Page 124: Desenvolvendo aplicações corporativas

124

/** * Retorna o usuário autenticado. * @return O usuário autenticado. */ public Usuario getUsuario() { return usuario; } /** * Define o novo usuário autenticado. * @param usuario O novo usuário. */ public void setUsuario(Usuario usuario) { this.usuario = usuario; } }