Computação em Nuvens – Monografia Especialização

Propaganda
UNIVERSIDADE FEDERAL DO PARANÁ
PROGRAMA DE PÓS-GRADUAÇÃO EM TECNOLOGIA
ESPECIALIZAÇÃO EM TECNOLOGIA JAVA
DOMINGOS DE CARVALHO VILLELA JÚNIOR
COMPUTAÇÃO EM NUVEM:
Desenvolvimento de aplicações empresariais ricas na internet, na
Arquitetura Java, Google Web Toolkit e Google Application Engine
MONOGRAFIA DE ESPECIALIZAÇÃO
CORNÉLIO PROCÓPIO
2011
1
DOMINGOS DE CARVALHO VILLELA JÚNIOR
COMPUTAÇÃO EM NUVEM:
Desenvolvimento de aplicações empresariais ricas na internet, na
Arquitetura Java, Google Web Toolkit e Google Application Engine
Monografia de Especialização apresentada ao
Programa de Pós-Graduação em Tecnologia da
Universidade Tecnológica Federal do Paraná
como requisito parcial para obtenção do título
de ―Especialista em Tecnologia JAVA‖ - Área
de Concentração: Computação Ubíqua.
Orientador: Prof. Me. Rodrigo Henrique
Cunha Palácios
CORNÉLIO PROCÓPIO
2011
2
À Sueli, Priscila e Rebeca, e aos desenvolvedores de softwares que
investem na computação ubíqua.
3
AGRADECIMENTOS
Reverencio o Professor Me. Rodrigo Henrique Cunha Palácios pela sua dedicação e
orientação deste trabalho.
Agradeço à Google pelo fornecimento dos recursos de software e hardware para o
desenvolvimento deste trabalho.
Também gostaria de deixar registrado o meu agradecimento à minha família, pelas
horas não dedicadas à minha esposa e filhas nos finais de semana.
4
People who love what they do, are usually those who are doing what
they love. (Peter Serchuk, Executive Creative Director, McCannErickson, Los Angeles.)
As pessoas que amam o que fazem, são geralmente aquelas que estão
fazendo o que amam. (Peter Serchuk, Diretor Executivo de Criação,
McCann-Erickson, Los Angeles.)
5
RESUMO
VILLELA, Domingos de Carvalho Júnior. Computação em Nuvem: Desenvolvimento de
aplicações empresariais ricas na internet RIA, na arquitetura Java, Google Web Toolkit
―GWT 2‖ e Google App Engine. 2011. 102 f. Monografia (Especialização em Tecnologia
JAVA) – Programa de Pós-Graduação em Tecnologia, Universidade Tecnológica Federal do
Paraná, Cornélio Procópio, 2011.
Esta pesquisa apresenta uma nova abordagem na forma de se desenvolver sistemas
empresariais. Esta inovação é a computação em nuvem, no qual os sistemas serão projetados e
desenvolvidos para serem implantados em data centers altamente confiáveis e seguros. Com
isto as empresas deixarão de administrar o banco de dados, unidades centrais de
processamento, redes de comunicação de dados, controle de acesso, cópias de segurança dos
dados e sistemas, e recursos humanos de tecnologia da informação. A proposta deste projeto
foi utilizar o software e o hardware da Google, o Google App Engine em conjunto com o
Google Web Toolkit 2.1. Este trabalho de pesquisa abordou a evolução da computação,
computação em nuvens, aplicações ricas para internet RIA, WEB 2.0, Crome OS, Google
App Engine, Sandbox, Dynamic HTML, Cascading Style Sheets, Document Object Model,
Ajax, WidGets, Java Data Objects e o Google Web ToolKit. Traz como resultado a
implantação um estudo de caso no data center da Google, demonstrando uma proposta inicial
de projeto nas nuvens.
Palavras-chave: Computação em nuvens. Google Web ToolKit. Google App Engine.
6
ABSTRACT
VILLELA JR., Domingos de Carvalho. Cloud computation: Development of business
applications in the RIA, in the JAVA architecture, ―GWT 2‖ Google Web Toolkit, and
Goggle App Engine. 2011. 102 pp. Term paper (Specialization in JAVA Technology –
Graduate Program in Technology, Universidade Tecnológica do Paraná, Cornélio Procópio,
2011.
This research presents a new approach in the way how business systems are developed. Such
an innovation is called cloud computing, in which systems are projected and developed in
order to be implanted into highly reliable and safe data centers. By means of such a device
companies will stop managing databanks, central processing units, data communications
newtworks, access control, data and system security backups, and IT human resources. The
proposal of this project was to use Google software and hardware, Google App Engine jointly
with Google Web Toolkit 2.1. This research paper broached the development of computation,
cloud computation, RIA, WEB 2, Crome OS, Google App Engine, Sandbox, Dynamic HTML,
Cascading Style Sheets, Document Object Model, Ajax, WidGets, Java Data Objects and
Google Web Toolkit. Such an implantation has as a result a case study in Google data center,
giving a demonstration of the initial proposal of the cloud computing project.
Keywords: Cloud computing. Google Web Toolkit. Google App Engine
7
LISTA DE CÓDIGOS
Código 1
Código 2
Código 3
Código 4
Código 5
Código 6
Código 7
Código 8
Código 9
Código 10
Código 11
Código 12
Código 13
Código 14
Código 15
Código 16
Código 17
Código 18
Código 19
Código 20
Código 21
Código 22
Código 23
Código 24
Código 25
Código 26
Código 27
Código 28
Código 29
Código 30
Código 31
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
Exemplo de CSS
Exemplo de Código HTML
Exemplo de anotações POJO e JDO
Folha de estilo do date picker
Fonte do DatePicker Java/GWT
Exemplo de um arquivo gwt.xml para definição de módulos
Ativação do gerenciamento de histórico de navegação do GWT
Código para exibir mensagem do status do navegador
Implementação da classe SimpleCallback
Classe Presenter<D>
Classe LoginFormPresenter
Interface LoginFormDisplay
Interface Display
Classe LoginFormView
Classe View
Exemplo de arquivo XML para definição de interface gráfica
Classe LoginFormView usando UiBinder
Web.xml
Exemplo de classe serializável
Inferface YourService.java
Inferface WorldServiceAsync
WorldServiceImpl
Função JavaScript sayHello(name)
Função JavaScript sayHello(name)
Função formatAsCurrency
Exemplo de função GWT acessada pelo HTML
Exemplo de um arquivo no formato JSON
Exemplo de requisição feita a um servidor JSONP
Resultado do parseResponse
Código JavaScript para acessar o serviço Google Maps
Código JavaScript para acessar o serviço catacaoacoes
30
31
34
43
44
51
54
54
58
59
60
61
62
62
63
64
65
70
71
72
73
74
78
79
79
79
81
84
84
85
86
8
LISTA DE FIGURAS
Figura 1
Figura 2
Figura 3
Figura 4
Figura 5
Figura 6
Figura 7
Figura 8
Figura 9
Figura 10
Figura 11
Figura 12
Figura 13
Figura 14
Figura 15
Figura 16
Figura 17
Figura 18
Figura 19
Figura 20
Figura 21
Figura 22
Figura 23
Figura 24
Figura 25
Figura 26
Figura 27
Figura 28
Figura 29
Figura 30
Figura 31
Figura 32
Figura 33
Figura 34
Figura 35
Figura 36
Figura 37
Figura 38
Figura 39
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
–
Pesquisa no Google Insights por cloud computing realizada
em janeiro/2011
Supercomputador Lonestar 4
Eras e dimensões da computação
Data Center da Google
Papéis da computação em nuvem
Exemplo de aplicação RIA e gatgets
Tecnologias e tendências na Web
Tabela periódica de API´s para os produtos Google
Console de administração do app engine da Google
Representação de uma árvore DOM
Alguns WidGets do GWT 2
Comparação das tecnologias de persistências
Nomes dos widgets GWT 2.1
Date Picker
Biblioteca Smart-GWT
Eclipse Helios 3.6
IDE Eclipse Helios 3.6 com os ícones do GWT e App Engine
Detalhes da instalação do GWT e App Engine no Eclipse 3.6
Ray Ryan no Google I/O 2009
Criação de um projeto GTW
Estrutura de diretórios de um projeto GTW
Modo de desenvolvimento do GWT no Eclipse
Configuração dos parâmetros para implantação
Implantação da aplicação no Data Center da Google
Mensagem no brower
Modelos MVC e MVP
Diagrama de classes UML para o padrão MVP da tela de login
Criação de um arquivo UiBinder
Tecnologia Remote Method Invocation
Arquitetura do GWT
Serialização de um objeto, e persistência em disco rígido
Sintaxe do JSON
Arquivo JSON processado, com outros widgets acrescentados
UTFPR no Google Maps
Cotação de ações no <div id=‖stokList‖>
Diagrama de classes do projeto simulação de cotação de ações
Estudo de caso implantado no app engine
Equipamentos com software Android e Chrome OS
Prós, contras e crescimento da computação em nuvens
14
17
18
19
20
24
25
27
28
31
33
36
42
42
46
47
47
48
48
49
50
52
53
53
55
56
58
64
68
69
71
81
82
85
86
88
88
90
91
9
LISTA DE QUADROS
Quadro 1 – Pacotes java.lang suportados pelo GWT
Quadro 2 – Pacotes java.lang.annotation suportados pelo GWT
Quadro 3 – Pacotes java.util suportados pelo GWT
Quadro 4 – Pacotes java.io suportados pelo GWT
Quadro 5 – Pacotes java.sql suportados pelo GWT
Quadro 6 – Manchetes sobre computação em nuvens
40
40
40
41
41
89
10
LISTA DE SIGLAS E ACRÔNIMOS
AJAX
API
BigTable
Blogs
CaaS
CSS
DaaS
DeskTop
DOM
EJB
ERP
Gadgets
GAE
Googlipse
GQL
GUI
GWT
IaaS
ID
IDE
JDBC
JDO
Jetty
JPA
JRE
JSF
JSNI
JSP
KHTML
LAN
MVC
MVP
OLAP
OLTP
PaaS
PC
POJO
RIA
RMI
RPC
Asynchronous JavaScript and XML
Application Programming Interface
Local de persistência de objetos do App Engine
Site para publicação rápida e pessoal de artigos
Comunicação como um Serviço
Cascanding Style Sheets
Desenvolvimento como um Serviço
Computadores tradicionais de mesa e não portátil
Document Object Model
Enterprise Java Beans
Enterprise Resource Planning
Software ou serviço que pode ser agregado a um ambiente maior
Google Application Engine
Plugin GWT para desenvolvimento de aplicações no IDE Eclipse
Google Query Language
Grafical User Interface
Google Web ToolKit
Infraestrutura como um Serviço
Indentificador de um objeto ou dado
Ambiente de Desenvolvimento Integrado
Java Database Connectivity
Java Data Objects
Servidor de aplicações
Java Persistence API
Java Runtime Environment
Java Server Faces
Java Script Native Interface
Java Server Pages
web browser engine, layout engine ou rendering engine do browser
Local Area NetWork
Model View Contoller
Model View Presenter
OnLine Analytical Processing
OnLine Transaction Processing
Plataforma como um Serviço
Personal Computer
Plain Old Java Objects
Aplicações Ricas para Internet
Remote Method Invocation
Remote Method Call
11
RSS
SaaS
SQL
TI
URL
W3C
WAN
Widgets
Recurso para agregar conteúdo Web juntamente com os links
Software como um Serviço
Sequencial Query Language
Tecnologia da Informação
Uniform Resource Locator
World Wide Web Consortium
Wide Area NetWork
Componentes de interface gráfica
12
SUMÁRIO
1 INTRODUÇÃO
1.1 OBJETIVOS
1.2 JUSTIFICATIVA
1.3 MOTIVAÇÃO
1.4 ESTRUTURA DO TRABALHO
13
13
13
14
15
2 FUNDAMENTAÇÃO TEÓRICA
2.1 EVOLUÇÃO DA COMPUTAÇÃO
2.1.1 Computação em Cluster
2.1.2 Computação em Grade
2.1.3 Computação Ubíqua
2.1.4 Computação em Nuvens
2.1.4.1 Infraestrutura como um serviço
2.1.4.2 Plataforma como serviço
2.1.4.3 Software como serviço
2.2 ENTERPRISE RESOURCE PLANNING – ERP
2.3 APLICAÇÕES RICAS PARA INTERNET – RIA
2.4 WEB 2.0
2.5 CROME OS
2.6 GOOGLE APPLICATION ENGINE – GAE
2.7 SANDBOX
2.8 DYNAMIC HTML
2.9 CASCADING STYLE SHEETS
2.10 DOCUMENTO OBJECT MODEL
2.11 ASYNCHRONOUS JAVASCRIP AND XML
2.12 WIDGETS
2.13 JAVA DATA OBJECTS
16
16
16
18
18
19
21
21
22
22
23
24
25
26
29
29
30
31
32
32
33
3 GOOGLE WEB TOOLKIT
3.1 COMPILADOR
3.2 JRE EMULATION LIBRARY
3.3 UI LIBRARY
3.4 SETTING UP GWT
3.5 PROJETO E DESENVOLVIMENTO
3.6 TRABALHANDO COM BROWERS
3.7 DESENVOLVIMENTO DE INTERFACE COM O USUÁRIO
3.8 COMUNICAÇÃO COM O SERVIDOR DE APLICAÇÕES
3.9 MISTURANDO JAVASCRIPT E GWT
3.10 ADICIONANDO API
37
38
39
41
46
49
54
55
67
77
84
4 ESTUDO DE CASO
87
5 CONCLUSÃO
REFERÊNCIAS
89
92
APÊNDICES
95
13
1 INTRODUÇÃO
Vender recursos computacionais como infraestrutura, plataforma (GWT/eclipse) ou
software sob demanda, de acordo com a necessidade do cliente de TI, não é novidade, porém
se tornava limitada às grandes instituições capazes de adquirir recursos computacionais de
grandes fornecedores de poder computacional.
1.1 OBJETIVOS
O objetivo deste trabalho é explorar a possibilidade de desenvolvimento de sistemas
empresariais no paradigma de computação em nuvens, com a linguagem de programação Java
e com a arquitetura de TI que a Google está disponibilizando ao mercado, o ―Google
Application Engine‖ e o ―Google Web Toolkit 2‖.
1.2 JUSTIFICATIVA
A primeira transformação no mercado de TI em grande escala ocorreu na década de
80, com o uso dos computadores pessoais (PCs) pelas empresas. As empresas tiveram que
fazer pesados investimentos, todos os colaboradores de uma empresa podiam ter um
computador pessoal potente conectado via rede local em sua mesa. Desta forma 80% dos
custos dos departamentos de TI são destinados para a manutenção do serviço e não em
estratégia. Este grande custo, porém não traz um avanço estratégico para a empresa,
justificando desta forma a importância de repassar o controle dos dados e o processamento
dos serviços de TI para servidores localizados na nuvem (CARR, 2010).
14
1.3 MOTIVAÇÃO
Acredita-se que essa migração dos sistemas empresariais para as nuvens que já
começou, deva levar entre 15 e 20 anos, e será inevitável (CARR, 2010).
Na Figura 1 mostra através da ferramenta Google Insights, que retorna um gráfico
com a proporção de pesquisas de um termo em relação aos anos, um interesse crescente por
cloud computing, e também por app engine e GWT, especialmente na Índia onde são
desenvolvidos os grandes sistemas empresariais.
Figura 1 – Pesquisa no Google Insights por cloud computing realizada em janeiro/2011
Fonte: GOOGLE Trends (2011).
15
1.4 ESTRUTURA DO TRABALHO
No capítulo 2 foi descrito a evolução da computação até chegar às nuvens, as bases
tecnológicas que foram utilizadas como o conceito computação em cluster e grid, computação
ubíqua, computação em nuvens, Enterprise Resourse Planning, aplicações ricas para internet,
WEB 2.0, Chrome OS, Google Application Engine, Sandbox, Dynamic HTML, Cascading
Style Sheets, Document Object Model, AJAX, WidGets, e o Java Data Objects.
No capítulo 3 foi apresentado o Google Web Toolkit, e como configurar o ambiente
de desenvolvimento integrado ―Eclipse‖ para trabalhar no ambiente em nuvens com o Google
App Engine.
No capítulo 4 foi apresentado o resultado de uma aplicação implantada no App
Engine e no capítulo 5 uma conclusão deste estudo com as perspectivas futuras da tecnologia
em nuvens, especialmente as propostas da Google. No apêndice A e B estão os códigos fontes
da classe CotacaoAcoes.java e da página CotacaoAcoes.html.
16
2 FUNDAMENTAÇÃO TEÓRICA
Para a compreensão do atual estado da computação em nuvem, este capítulo faz uma
revisão das bases tecnológicas que serão necessárias para o desenvolvimento de modernos
sistemas aplicativos que serão hospedados no ambiente de cloud computing.
2.1 EVOLUÇÃO DA COMPUTAÇÃO
Nos primórdios da computação por volta de 1943, o processamento era feito em um
único computador (Eniac), depois surgiu o computador multitarefa com uma CPU e vários
terminais (IBM 4341), por volta de 1974 vieram os computadores pessoais PC que hoje
possuem processamento paralelo (Intel i3, i5, i7 e Xeon).
Com a evolução da internet, linguagens de programação, virtualização, e computação
distribuída, com as tecnologias de Cluster, Grade e Ubíqua, tornaram possível a computação
em nuvem.
Estas tecnologias levam à necessidade de aplicativos que possam ser acessados de
forma eficiente de qualquer lugar. Este paradigma de computação ubíqua criou a necessidade
de repensar o modo como as aplicações são desenvolvidas e disponibilizadas, ao mesmo
tempo em que motivou o desenvolvimento de tecnologias capazes de dar suporte ao seu
aperfeiçoamento.
2.1.1 Computação em Cluster
Um cluster, é composto por um conjunto de computadores, pode ser construido a partir
de computadores convencionais, que são ligados em rede locais, comunicando-se através do
sistema operacional, funcionando como se fossem uma máquina única de grande porte.
Os tipos mais conhecidos de cluster são:

Cluster de Alto Desempennho: Ele funciona permitindo que haja uma grande carga de
processamento com computadores comuns.
17

Cluster de Alta Disponibilidade: Os sistemas permanecem ativos por um longo período de
tempo e em plena condição de uso. Estes clusters nunca param de funcionar, e conseguem
detectar erros, se protegendo de possíveis falhas.

Cluster para Balanceamento de Carga: Esse cluster tem como função equilibrar a
distribuição do processamento entre as máquinas. Requer um monitoramento constante
em seus mecanismos de redundância, pois se houver alguma falha, ocorrerá uma
interrupção no seu funcionamento.
Os clusters dos data centers mais modernos são construidos com vários blades (um
servidor blade é um despojado computador servidor com um design modular otimizado para
minimizar o uso de espaço físico e energia). Na Figura 2 é mostrada a foto do Lonestar 4 do
centro de computação avançado da universidade do Texas em Austin, que entrou em operação
em fevereiro de 2011. Este cluster é composto por 1.888 blades PowerEdge M610 da Dell,
cada blade contendo dois processadores Intel Xeon X5600 Westmere, de seis núcleos, o
sistema atinge um pico de 302 teraflops (um teraflop equivale a um trilhão de operações por
segundo), tem um total de 44,3 terabytes de memória RAM e 1,2 petabytes de armazenamento
de disco (MILLER, 2011).
Figura 2 – Supercomputador Lonestar 4
Fonte: Miller (2011).
18
2.1.2 Computação em Grade
Computação em grade, é um modelo computacional capaz de alcançar uma alta taxa
de processamento dividindo suas tarefas entre diversos clusters, podendo ser em rede local
(LAN) ou rede de longa distância (WAN), que formam uma única máquina virtual. Esses
processos são balanceados entre os cluters do grid computing, evitando a ociosidade de
processamento de máquinas pertencentes à grade.
2.1.3 Computação Ubíqua
A computação ubíqua é a junção da computação móvel e da computação pervasiva.
O conceito de computação pervasiva indica que o computador está embarcado no ambiente de
forma invisível para o usuário (WLAN). O computador tem a capacidade de obter
informações do ambiente no qual ele está inserido, e utilizar este ambiente para configurar,
ajustando a aplicação para melhor atender as necessidades do dispositivo ou usuário.
Na Figura 3 é mostrada as eras e as dimensões da computação.
Figura 3 – Eras e dimensões da computação
Fonte: Adaptado de Weiser (2011).
Na Figura 4 ilustra um dos Data Centers da Google, onde podemos ver o Cluster, o
Grid computing no mapa mundi, o armazenamento de dados em raids (conjunto independente
de discos redundantes), a infraestrutura de rede e um dos prédios com seus resfriadores a
vista, para abrigar toda esta tecnologia (GOOGLE DATA CENTER..., 2009).
19
Figura 4 – Data Center da Google.
Fonte: Adaptado de GOOGLE Data Center... (2009).
2.1.4 Computação em Nuvens
Uma definição para o paradigma de computação em nuvens, podendo ser tomada
como referência é:
Computação em nuvem é um paradigma de computação em larga escala que possui
foco em proporcionar economia de escala, em que um conjunto abstrato,
virtualizado, dinamicamente escalável de poder de processamento, armazenamento,
plataformas e serviços, são disponibilizados sob demanda para clientes externos
através da internet. (FOSTER apud MÜLLER, 2010, p. 18).
A idéia da computação em nuvem consiste em que tudo é serviço, uma espécie de
self-service de tecnologias da informação, disponibilizados ao usuário, podendo ser ele um
20
desenvolvedor ou usuário final. Muitos serviços de computação em nuvem são oferecidos
pelo modelo chamado Utility Computing, o qual é definido como um pacote de recursos
computacionais medidos e cobrados de forma semelhante aos serviços de utilidade pública,
como eletricidade, água, telefone, TV por satélite ou banda larga. Este modelo prevê uma
otimização dos investimentos feitos pelos clientes nos recursos de hardware, diminuindo a
necessidade de grandes investimentos iniciais, possibilitando o aluguel de mais recursos à
medida que forem necessários, podendo ainda alguns provedores de serviços se ajustarem
dinamicamente às necessidades de demanda, na medida em que o cliente contratar mais
recursos apenas para momentos de pico, evitando que recursos fiquem ociosos a maior parte
do tempo.
Atualmente os serviços de computação em nuvem possuem três categorias bem
definidas de acordo com os recursos e o modo que estes recursos são disponibilizados. Na
Figura 5 é ilustrada que a computação em nuvem é impulsionada pelos conceitos de utility
computing, on-demand computing, autonomic computing e Green IT, e as categorias de
serviços:

Infraestrutura como um Serviço (IaaS)

Plataforma como um Serviço (PaaS)

Software como um Serviço (SaaS)
Figura 5 – Papéis da computação em nuvem
Fonte: Adaptado de WHAT... (2011).
21
2.1.4.1 Infraestrutura como um serviço
A Infraestrutura como um serviço (IaaS), e que geralmente se apóia em tecnologias
como virtualização, é a base dos serviços de computação em nuvem, sendo a parte que se
refere à disponibilização dos recursos de hardware formados pelos servidores, armazenamento
e processadores. O consumidor do serviço adquire uma máquina virtual operando sobre a
estrutura de servidores do provedor, sendo a quantidade de processamento e armazenamento
contratados disponibilizados através da configuração adequada de tais máquinas virtuais.
A vantagem destes serviços se encontra na facilidade de contornar problemas de
escalabilidade dos sistemas, na grande capacidade de suportar demandas crescentes por
recursos de forma uniforme, bastando para isto apenas ajustar as configurações das máquinas
virtuais contratadas.
2.1.4.2 Plataforma como serviço
Plataforma como um Serviço (PaaS) que se destina aos desenvolvedores, é um tipo
de serviço que procura prover toda a estrutura necessária para um ambiente de
desenvolvimento. Neste serviço o ambiente de desenvolvimento disponibiliza uma plataforma
computacional completa, incluindo sistema operacional, linguagens de programação,
bibliotecas e sistemas gerenciadores de banco de dados, disponíveis através da nuvem. Deste
modo os desenvolvedores podem construir suas aplicações sem a necessidade de instalar
qualquer ferramenta no seu computador e distribuí-la de forma simples.
Um serviço completo de PaaS todo o ciclo de vida do software deve ser suportado no
mesmo ambiente computacional, reduzindo os custos de desenvolvimento, manutenção e
distribuição das novas versões das aplicações.
22
2.1.4.3 Software como serviço
Uma definição para o modelo Software como um Serviço (SaaS), poderia ser a de
software distribuído como um serviço hospedado e acessado através da internet. Podemos
citar uma variedade de exemplos de aplicações em que neles se enquadram, como é o caso das
aplicações de webmail, aplicações que tornaram praticamente dispensáveis os aplicativos
clientes de e-mail desktop convencionais, sites de compartilhamento de fotos e vídeos, e
aplicações de escritório como as disponibilizadas pelo Google através do GoogleDocs.
Computação em nuvem despertou a necessidade para o desenvolvimento de novas
tecnologias e propostas no desenvolvimento e distribuição de aplicações, bem como
tecnologias de suporte e infraestrutura, mostrando ser um campo com grande potencial de
geração de novas necessidades, que terão que ser supridas pelos futuros profissionais de TI.
Alguns autores também consideram DaaS e CaaS como modelo de serviço de
computação em nuvem. O DaaS (Development as a Service) é uma aplicação Web que usa
conteúdo de mais de uma fonte para criar um novo serviço completo, podem possuir códigos
de terceiros que se comunicam através de uma interface publica ou de uma API como os RSS,
Widgets e Blogs. O CaaS (Communication as a Service) é o conjunto de serviços que satisfaz
a função de comunicação, como telefonia IP, mensagens instantâneas e videoconferência.
2.2 ENTERPRISE RESOURCE PLANNING – ERP
ERP ou Sistemas Integrado de Gestão Empresarial são sistemas de informação que
integram em um único sistema todos os dados e processos de uma organização empresarial. A
integração pode ser analisada sob a perspectiva funcional (sistemas de: finanças,
contabilidade, recursos humanos, fabricação, marketing, vendas, compras, etc) e sob a
perspectiva sistêmica com os sistemas transacionais (OLPT), e os sistemas analíticos (OLAP)
para prover as informações para tomada de decisão pelos gestores da organização.
Os ERPs são implantados em uma infraestrutura de software desenvolvida para
integrar os diversos setores de uma empresa, possibilitando a automação dos processos
empresariais, e armazenamento de todos os dados de negócios em um único banco de dados.
23
Processando os dados deste banco de dados, são geradas informações para os gestores, que
por sua vez criam conhecimento que geram riquezas e lucro para as empresas.
O maior benefício que um sistema de ERP proporciona a uma corporação, está na
maior confiabilidade dos dados, processos on-line, e a diminuição do retrabalho. Algo que é
atingido com o comprometimento dos funcionários, cada um com suas responsabilidades por
fazer os lançamentos que alimentam toda a cadeia de módulos do sistema, e que fazem com
que a empresa possa interagir em tempo real. Desta forma, as informações fluem pelos
diversos módulos em tempo real. Um pedido de vendas dispara um processo de fabricação
com o envio de dados para multiplos módulos, do estoque de insumos à logística do produto.
Tudo realizado com dados integrados e não redundantes.
2.3 APLICAÇÕES RICAS PARA INTERNET - RIA
Aplicações Ricas para Internet (RIA - Rich Internet Application) são Aplicações
Web que tem funcionalidades de softwares tradicionais do tipo Desktop. RIA típicos injetam
todo o processamento da interface para o navegador da internet, que assincronamente
disparam pedidos de processamento para o servidor de aplicação, com tecnologia JavaScript
e XML, o AJAX.
RIAs na maioria dos casos não necessitam de instalação na máquina cliente e rodam
localmente em um ambiente seguro chamado sandbox. Sandbox executa seus programas em
um espaço separado (caixa de areia) que é apagado automaticamente, impedindo fazer
alterações permanentes no computador cliente. Executando o browser sob a proteção do
Sandbox assegura que todo o software mal intencionado baixado pelo navegador está preso na
caixa de areia, e podem ser descartados trivialmente. O histórico de navegação, cache, cookies
e arquivos temporários coletados durante a navegação na Web estariam na caixa de areia e
não vaza para o Sistema Operacional, vírus e outros softwares mal intencionados que podem
estar escondidos em e-mail não pode sair da caixa de areia e não pode infectar o sistema real.
Na Figura 6 é ilustrada uma aplicação RIA (iGoogle) implementada com o GWT
pela Google. O iGoogle usa o conceito de gadgets, um pequeno objeto tecnológico, que tem
uma função específica. Estes gadgets têm o comportamento similar de janela no ambiente
desktop, onde possuem a funcionalidade de maximizar, mover, remover, inserir novos gadgets
e configurar a aparência dos mesmos. Os gadgets são construídos a partir dos widgets.
24
Figura 6 – Exemplo de aplicação RIA e gatgets
Fonte: iGOOGLE (2011).
2.4 WEB 2.0
O termo Web 2.0 é utilizado para descrever a segunda geração de comunidades e
serviços Web como AdSense, Ajax, Blogs, Mash-ups, RSS, Tagging [rotulação] e Wikis.
Apesar da conotação de uma nova versão para a Web, não se refere à inovação de técnicas,
mas a uma mudança na forma como ela é utilizada por usuários e desenvolvedores, tendência
que reforça o conceito de troca de informações e colaboração dos internautas com sites e
serviços virtuais. A idéia é que o ambiente on-line se torne mais dinâmico e que os usuários
colaborem para a organização de conteúdo (MOREIRA, 2009).
Como toda forma de classificação histórica, não pode se dizer exatamente quando
termina ou começa a Web 2.0 cronologicamente. Na Figura 7 é ilustrado estes padrões e
tendências de comportamento na rede, colaborando com a organização de idéias e conceitos
em uma indústria nova e complexa, por sofrer muitas mutações justamente por estar ainda em
sua fase embrionária.
25
Na web 2.0 como plataforma, os sites deixam de ter uma característica estática para
se transformarem em verdadeiros aplicativos no servidor. As funcionalidades dos sites serão
muito mais poderosas, lembrando a sofisticação de softwares que rodam no desktop de um
PC. Estes aplicativos web tem também uma integração mais eficiente com a interface no
cliente (browser), que passa a ser mais poderosa com tecnologias como XML e JavaScript, o
AJAX, que podem gerar uma usabilidade mais intuitiva e que lembra as interfaces
desenvolvidas em código de baixo nível (C++ e afins) (MOREIRA, 2009).
Figura 7 – Tecnologias e tendências na Web
Fonte: Hodgson (2008).
2.5 CROME OS
A computação em nuvem leva ao fim os sistemas desenvolvidos no modelo DeskTop
com o surgimento do Chorme OS da Google. Com o surgimento dos netbooks com sistema
operacional Chrome OS, smartPhones com sistema operacional Android da Google, tablets
com sistema operacional Android 3.0 e redes sem fio ligadas à internet em alta velocidade,
não há mais a necessidades de termos grandes Hard Disk, memórias RAM de 8 GB,
26
processadores multiprocessados com até 4 nucleos, compra, instalação e manutenção de
software, backups atualizados, preocupação com segurança dos dados e virus nas máquinas
clientes. Para utilizar algum serviço nas nuvens basta termos uma rede banda larga, e um
equipamento com um navegador internet ou com Chorme OS onde o próprio navegador é o
sistema operacional.
Alguns usuários ainda necessitarão de aplicações DeskTop, os desenvolvedores de
software por exemplo continuarão com suas potentes máquinas, assim como os usuários de
games de ponta em que é exigido grandes processadores.
Os Chromebooks são uma versão radical do conceito de netbook com o sistema
operacional Chrome OS, podem ser definidos como a experiência de netbook levada às
ultimas consequências. Aqui a ideia é ter tudo armazenado na nuvem para que a máquina seja
o mais rápida e leve possível. O Chromebook fará tudo baseado na web. Nesta arquitetura não
é o computador pessoal que envia e-mail ou edita um documento, ele é apenas um meito para
solicitar e receber os serviços da nuvem.
2.6 GOOGLE APPLICATION ENGINE - GAE
O Google foi um dos primeiros a implantar uma plataforma em cloud aberta para
desenvolvimento de aplicativos. O Google Application Engine, App Engine ou GAE é um
serviço contido no modelo de IaaS, DaaS e PaaS, que diferentemente de seu conceito original,
em que todo o ambiente responsável pelo ciclo de desenvolvimento e publicação do software
se dá através de ferramentas disponibilizadas via web, disponibiliza um ambiente desktop
completo através de plugins para o Eclipse IDE chamado de Googlipse para criar as
aplicações.
Com o Google App Engine, pode-se criar aplicativos web nos mesmos moldes de
sistemas escaláveis dos aplicativos do Google. Os aplicativos implantados no Google App
Engine são fáceis de criar, manter e escalar à medida que seu tráfego e armazenamento de
dados precisam crescer. Uma vez o implantado o sistema no app engine, os clientes já
poderão acessar e usar o aplicativo.
O Google é conhecido por ser altamente confiável, e por sua infraestrutura de alto
desempenho. Com o Google App Engine, pode-se beneficiar dos 10 anos de experiência e
conhecimento que o Google possui em executar sistemas altamente escaláveis e orientados
27
para o desempenho. As mesmas políticas de segurança, privacidade, escalabilidade e proteção
de dados para os seus aplicativos se aplicam a todos os aplicativos do Google App Engine. A
Google oferece um leque de API´s para acessos a seus serviços. A idéia da Google é fornecer
estas API´s para usar a nuvem da Google em sistemas, precisando disponibilizar vídeos em
uma aplicação use a You-tube API. Estas API´s podem ser vistas na Figura 8.
Figura 8 – Tabela periódica de API´s para os produtos Google
Fonte: GOOGLE´S... (2011).
O Google App Engine sempre será gratuito para iniciar, afirma a Google, até o limite
de 500 MB de armazenamento e 5 milhões de acessos de página mensais, e quando este limite
for atingido é só ativar o faturamento e pagar o que for usado com os seguintes preços em
dólar americano.
Tabela 1 - O custo dos recursos de computação do app engine da Google
Recurso
Unidade
Custo unitário
Largura de banda de saída
gigabytes
$0,12
Largura de banda de entrada
gigabytes
$0,10
Horas da CPU
$0,10
gigabytes por mês
$0,15
Tempo de CPU
Dados armazenados
Destinatários de e-mail
destinatários
$0,0001
Fonte: BILLING... (2011).
Conclui-se pela Tabela 1, que com $0.94 mensais é possível manter um sistema com
uso de 2 horas de CPU ($0.20), 2 GB de armazenamento ($0.30), 2 GB de saída de
informações ($0.24) e 2 GB de entrada de dados ($0.20). Através do console de administração
28
do aplicativo é possível gerenciar o orçamento do aplicativo, bem como os recursos
consumidos por ele. Na Figura 9 é mostrada a console da máquina virtual do GAE que será
usada no estudo de caso deste trabalho, para acessar o serviço deve fazer login.
Google Application Engine possui suporte a aplicativos criados com o uso das
linguagens de programação Python e Java. O App Engine permite o uso das bibliotecas
padrões da linguagem Java, que será usado neste trabalho, com exceção das que infrinjam as
restrições impostas com o grande objetivo de garantir o bom funcionamento do sistema. Para
diminuir o efeito negativo das restrições, o Google App Engine criou uma série de serviços
que facilitam o desenvolvimento e execução de determinadas tarefas.
Os aplicativos criados e disponibilizados a partir do Google App Engine podem ser
acessados a partir do domínio livre no padrão appspot.com oferecido pelo serviço adicionado
ao identificador da aplicação escolhido na hora da sua criação, ficando da forma:
identificador.appspot.com. (ex: http://www.tccposjavautfpr.appspot.com/ domínio criado para
o estudo de caso).
Figura 9 – Console de administração do app engine da Google
Fonte: RUN... (2011).
29
2.7 SANDBOX
O Application Engine, implementa de forma inovadora o paradigma de computação
em nuvem, em que o armazenamento e processamento do aplicativo são distribuídos entre os
clusters da Google, e necessita de um ambiente virtual seguro para cada aplicativo. Este
ambiente chamado de sandbox disponibiliza acesso limitado ao sistema operacional. Esta
limitação possibilita que o Google App Engine distribua as solicitações de web da aplicação
entre diversos clusters, podendo iniciar ou interromper os servidores para atender às
demandas de tráfego. O GAE também permite que cada aplicação possua uma área isolada
(caixa de areia) confiável e segura independente de hardware, sistema operacional e
localização física do servidor, garantindo que uma aplicação não influencie no funcionamento
de outras. Este método de virtualização além de possibilitar a distribuição na execução do
aplicativo, evita em um ambiente compartilhado, o uso abusivo de recursos por uma aplicação
afetando desempenho das demais.
2.8 DYNAMIC HTML
Dynamic HTML, ou DHTML, é união das tecnologias javascript, HTML e uma
linguagem de apresentação, como as folhas de estilo CSS, tudo funcionando em conjunto com
o
Modelo de Objeto de Documentos (DOM), para permitir que uma página Web seja
modificada dinamicamente no próprio navegador da máquina do cliente, sem necessidade de
novos acessos ao servidor web.
A especificação oficial do DHTML foi feita pela W3C, mas a Netscape e a Microsoft
incluíram vários recursos extras que ajudaram ainda mais o DHTML. Esses DHTMLs
incluiram novas capacidades de alterar as propriedades das marcações tags HTML
dinamicamente. O DHTML da Microsoft, permite que se adicionem efeitos como sombra e
néon a imagens apresentadas dentro de um documento HTML. DHTML é um conjunto de
recursos que fornecem um controle inovador sobre a apresentação do conteúdo de páginas da
Web, além de possibilitar a inclusão de componentes (widgets) multimédia, como animações,
diretamente no código HTML, sem a necessidade de plug-ins. O HTML Dinâmico é adotado,
por estabelecer novos patamares de usabilidade e movimento na internet a um baixo custo
medido em velocidade, abrangência e flexibilidade (HTML..., 2011)
30
2.9 CASCADING STYLE SHEETS
Cascading Style Sheets (CSS) é uma linguagem de estilo utilizada para padronizar a
apresentação de documentos codificados em uma linguagem de marcação, como HTML ou
XML. Seu principal benefício é estabelecer uma separação entre o formato e o conteúdo de
um documento HTML.
Ao invés de especificar a formatação dentro do documento, o desenvolvedor cria um
link para uma página que contém os estilos, fazendo o mesmo para todas as páginas de um
site. Quando quiser alterar a aparência do site basta portanto modificar apenas o arquivo CSS.
body
{
font-family: Arial, Verdana, sans-serif;
background-color: #FFFFFF;
margin: 5px 10px;
}
Código 1 - Exemplo de CSS
Fonte: Autoria própria.
O Código 1 é um exemplo de arquivo CSS em que define para o corpo da página
HTML, um fonte padrão Arial, se não existir este fonte na máquina cliente o CSS substitui
por Verdana, caso não exista define qualquer fonte sans-serif, este estilo define também a cor
no formato hexadecimal que no caso é branco, e as margens.
A documentação detalhada do CSS pode ser obtidas no site da W3C World Wide
Web Consortium, um consórcio de diversas empresas que trabalham juntas para estabelecer
padrões para a Internet.
Hoje ainda nenhum browser suporta igualmente as todas as definições do CSS. Desta
forma, o webdesigner deve verificar o comportamento de suas folhas de estilo em browsers de
vários fabricantes, e especialmente em mais de uma versão, para se garantir que o que foi
codificado seja apresentado da forma planejada.
31
2.10 DOCUMENTO OBJECT MODEL
Document Object Model (DOM) fornece uma representação estruturada de um
documento HTML (no contexto de navegadores web) a partir da qual seus elementos podem
ser manipulados através de JavaScript, e fornece uma notação padronizada entre os
navegadores. Mesmo não sendo totalmente, é razoavelmente padronizada, por isto a
importância de se testar as páginas em diferentes navegadores e em diferentes versões.
Qualquer alteração feita em um elemento da árvore é imediatamente refletida na
página que está sendo exibida pelo navegador.
<html>
<head>
<title>Ajax - conceitos básicos</title>
</head>
<body>
<h1>Exemplo de árvore DOM</h1>
</body>
</html>
Código 2 - Exemplo de Código HTML
Fonte: Lima (2010).
Na Figura 10 é mostrada a representação da árvore DOM feita pelo browser:
Figura 10 – Representação de uma árvore DOM
Fonte: Lima (2010).
32
Todos os componentes da HTML são representados como um nó na árvore DOM,
inclusive fragmentos de texto. Existem tipos diferentes de nó. Nó de elemento, para
representar <Tags> da HTML, nó de atributo, para representar uma propriedade de um nó de
elemento, e nó de texto, para representar cadeias de caracteres da página.
Cada nó pode possuir ou não filhos e pertencer a um único pai, cada nó pode possuir
um atributo identificador, que através de JavaScript pode-se recuperar, adicionar, modificar e
remover nó na árvore DOM. Toda alteração é refletida na página sem a necessidade de
carregar o documento HTML novamente.
2.11 ASYNCHRONOUS JAVASCRIPT AND XML
Asynchronous JavaScript and XML (AJAX), é uma técnica de programação que faz
uso conjunto de outras tecnologias como DHTML e XML. Grande parte da programação é
realizada no navegador do cliente, totalmente baseado em Java Script, XML e utilização da
árvore DOM que os navegadores implementam para promover a atualização de partes
específicas da aplicação. Ajax permite solicitações assíncronas a um determinado serviço e
atualiza somente os campos necessários para executar os requisitos da aplicação, ao invés de
recarregar toda a página, desta forma permite maior interatividade da página e torna as
aplicações web mais dinâmicas. (LIMA, 2010).
2.12 WIDGETS
O elemento básico de um programa com interface gráfica se chama widget, podem
ser janelas, botões, menus, ícones, barras de rolagem, etc. Um programa deve definir uma
hierarquia de árvore invertida de widgets, na qual alguns widgets estão subordinados a outros.
Normalmente, todos os widgets são subordinados a um widget principal. Trabalhar com
vários widgets é a principal diferença entre um programa GUI e um programa normal. No
último caso, o desenvolvedor procura sempre saber qual ponto do software está sendo
executado, no programa GUI é o sistema gerenciador de janelas que escolhe qual parte do
software (ou seja, qual parte de qual widget) está sendo rodado. As mensagens entre os
33
diversos widgets usualmente é feita de forma indireta, eles disparam mensagens indicando as
ações executadas sobre ele, e estas mensagens são recebidas pelos outros widgets para efetuar
as ações desejadas. Na figura 11 é ilustrado alguns widgets do GWT 2.
Figura 11 – Alguns WidGets do GWT 2
Fonte: Adaptado de WIDGET... (2011).
2.13 JAVA DATA OBJECTS
Java Data Objects (JDO), trata-se de um padrão Java para persistência de dados
independente do sistema de banco de dados utilizado, uma aplicação que utiliza este padrão
para modelar suas entidades de dados para utilizar como sistema de armazenamento o
BigTable do Google ou migrar para algum banco de dados relacional, como o MySQL, sem
que isso afete seu modelo de dados. Deste modo perde-se um pouco em eficiência de
modelagem, mas se ganha muito em portabilidade. Para que isto seja possível é necessário
que haja uma implementação do padrão executando em nível de servidor JVM, responsável
34
por mapear os modelos fisicamente ao sistema escolhido. O responsável por esta tarefa no
App Engine é o DataNucleus Access Platform implementando a versão 2.3 do JDO. A
modelagem das entidades baseia-se nos chamados POJOs (Plain Old Java Objects), que nada
mais são do que objetos simples dotados de atributos ou propriedades, e métodos de acesso
(atribuição e obtenção) a estes atributos, adicionados de anotações JDO para torná-los
passíveis de persistência, analogicamente como acontece com a tecnologia hibernate
(JAVA..., 2011).
A linguagem de persistência no DataStore do GAE é o GQL Google Query
Language, muito parecido com o SQL. A hospedagem no GAE foi desenvolvida para utilizar
aplicações 100% cloud, logo é disponibilizado para todas as contas registradas um banco
NoSQL para toda aplicação criada. A plataforma GAE disponibiliza o padrão JDO e JPA. O
DataStore da Google é o Bigtable projetado de forma confiável a escala de petabytes de dados
e milhares de máquinas servidoras.
Uma entidade persistente no sistema de armazenamento a ser modelada com JDO
utiliza uma classe simples, contendo atributos, métodos de acesso aos atributos e anotações
JDO correspondentes. O nome da entidade será definido pelo nome da classe, e os nomes das
propriedades que serão armazenadas serão os mesmos definidos no modelo. A anotação
@PersistenceCapable define que a classe é apta a ser persistida.
package guestbook;
import java.util.Date;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import com.google.appengine.api.users.User;
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Greeting {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;
@Persistent
private User author;
@Persistent
private String content;
@Persistent
private Date date;
public Greeting(User author, String content, Date date) {
35
this.author = author;
this.content = content;
this.date = date;
}
public Long getId() {
return id;
}
public User getAuthor() {
return author;
}
public String getContent() {
return content;
}
public Date getDate() {
return date;
}
public void setAuthor(User author) {
this.author = author;
}
public void setContent(String content) {
this.content = content;
}
public void setDate(Date date) {
this.date = date;
}
}
Código 3 - Exemplo de anotações POJO e JDO
Fonte: JAVA... (2011).
Esta classe simples define três propriedades para uma saudação: author, content e
date. Esses três atributos privados da classe acima são anotados com @Persistent para
informar que o DataNucleus deve persisti-los como propriedades de objetos no
armazenamento de dados do Google App Engine. Essa classe define os métodos set e get das
propriedades ou atributos. Elas são usadas apenas pelo aplicativo e não são necessárias para a
JDO. A classe define também um atributo chamado id, um Long anotado como @Persistent e
@PrimaryKey. O armazenamento de dados do Google App Engine usa o conceito de chaves
de entidade e pode representar a chave de diversas maneiras no objeto. Nesse caso, o campo
da chave que é o identificador de um objeto do tipo Greeting é um inteiro long, e é definido
automaticamente como um ID numérico exclusivo quando o objeto é salvo.
Na Figura 12 é ilustrada uma comparação entre as tecnologias de persistência JDBC,
JPA, EJB2, ORM proprietários e o JDO.
36
Figura 12 – Comparação das tecnologias de persistências
Fonte: JAVA... (2011).
Benefícios do uso de JDO para Programação de Aplicativos:

Facilidade de uso: Os desenvolvedores de aplicativos podem se concentrar em seu modelo
de objeto de domínio e deixar os detalhes de persistência (campo-a-campo de
armazenamento de objetos) para a implementação JDO.

Portabilidade: aplicações escritas com a API JDO podem ser executadas em várias
implementações sem recompilar ou alterar o código fonte. Metadados que descreve o
comportamento externo de persistência para o código-fonte do Java inclue a maioria dos
recursos mais usados do mapeamento O/R, e é altamente portável.

Independência Banco de Dados: Aplicações escritas com a API JDO são independentes
do banco de dados. JDO dá suporte a muitos tipos diferentes de armazenamentos de dados
transacionais, incluindo bancos de dados relacionais e objeto, XML, arquivos simples, e
outros.

Alto desempenho: Os desenvolvedores de aplicativos podem delegar os detalhes de
persistência para a implementação JDO, que podem otimizar o acesso a padrões de dados
para um ótimo desempenho.

Integração com EJB: As aplicações podem tirar proveito dos recursos do EJB, tais como o
processamento de mensagens a distância, coordenação de transações distribuídas
automática e segurança, utilizando os modelos de objeto do mesmo domínio em toda a
empresa.
37
3 GOOGLE WEB TOOLKIT
O Google Web Toolkit é um kit de desenvolvimento de aplicações web da Google,
que permite desenvolver interfaces ricas, escrevendo código fonte na linguagem de
programação Java, gerando JavaScript compatíveis com a maioria dos navegadores Web. A
formatação do GWT foi elaborada para a utilização da plataforma GAE, pois a padronização
da estrutura do projeto facilita escalar a aplicação desenvolvida e é uma alternativa ao JSF
para o desenvolvimento orientado a componentes (GOOGLE WEB..., 2011).
A ferramenta trabalha com o código dividido em duas partes distintas, uma com
código a ser executado pelo cliente e outra com código a ser executado pelo servidor através
de chamadas assíncronas feitas pelo código no cliente. O código Java destinado a ser
executado pelo cliente é automaticamente compilado pelo Google Web Toolkit para código
JavaScript capaz de ser executado por navegadores, deixando a cargo do compilador questões
de compatibilidade entre navegadores e de otimização.
Aplicativos baseados neste conceito têm uma maior usabilidade por evitar o uso
excessivo de solicitações e se aproximar da interação proporcionada por aplicativos para
desktop, evitando freqüentes carregamentos das páginas do aplicativo, melhorando a
experiência de uso, algo que é um dos principais problemas de aplicativos web. O próprio
Google utiliza esta ferramenta em vários de seus aplicativos, o Gmail, a rede social Orkut e o
conjunto de ferramentas como processadores de texto e planilhas do Google Docs. O GWT
pode ser utilizado por qualquer aplicativo Java para web e possui integração com o Google
Application Engine, sendo distribuído juntamente com seu plug-in para Eclipse o Googlipse.
O modelo de desenvolvimento de aplicações GWT, tornou possível que uma
aplicação Web seja escrita inteiramente em Java, desobrigando a usar tecnologias de páginas
dinâmicas como o JSP por exemplo. Por meio do processo de compilação, o GWT gera
código JavaScript cross-browser, garantindo que uma aplicação seja construída através de
uma forma de programação, que utiliza tecnologias implementadas em qualquer navegador
Web que suporte as especificações do W3C.
Desde seu lançamento na conferencia JavaOne em maio de 2006, o GWT vem
evoluindo passando da versão 1.0 para a 2.1 atualmente, que traz muitas novidades, entre elas
novos widgets com suporte a data binding (recurso permite efetuar a ligação com dados de
diversas fontes de dados sem ter que escrever código, permitindo gerenciar a execução e
edição de dados complexos) e um framework Model-View-Presenter.
38
Uma desvantagem do GWT atualmente é que suas páginas não podem ser indexadas
pelos mecanismos de busca, uma vez que elas são geradas dinamicamente. Para contornar o
problema é usado cloaking, que é uma técnica utilizada por webmasters para entregarem
conteúdos diferentes de uma mesma URL para visitantes específicos do site. Os visitantes
podem ser classificados pelo tipo de Web Crawler (programa de computador que navega pela
World Wide Web de uma forma metódica e automatizada) Human User ou por localidade.
Existem 3 métodos de cloaking, o cloaking por User-Agent que detecta o user-agent
e o classifica, o cloaking por IP Delivery que entrega um conteúdo diferente para um usuário
de IP específico, e o cloaking por Geo-Targeting que fornece um conteúdo diferente para
usuários dentro de uma faixa de IPs que delimitam uma região do mundo específica
(MÜLLER, 2011)
O GWT possue tres componentes básicos, o compilador Java-to-JavaScript, o emulador
Java Runtime Environment (JRE) e a liblioteca de interface gráficas com o usuário (GUI).
3.1 COMPILADOR
O compilador Java trabalha a partir das versões 1.5, e produz distintos códigos
JavaScript para serem executados em todos os browser suportados. Hoje todas as versões do
Safari e FireFox, Opera, versões 6,7 e 8 do Internet Explorer, e Google Chrome suportam
JavaScript, e são baseados no mesmo layout do WebKit (motor de renderização para
navegadores que foi desenvolvido baseado no KHTML). O JavaScript gerado fica muito
maior se for usado a internacionalização, que são processos de desenvolvimento e/ou
adaptação do softwares para uma língua e cultura de um país.
O código gerado pode ser minimizado para otimizar o download e facilitar o code
splitting, onde o JavaScript é quebrado em pedaços e feito o download sob demanda. O
compilador tem diversos otimizadores de código, que produz códigos JavaScript de alta
qualidade, as mais importantes são:

Dead Code Elimination: Códigos que nunca são chamados não são incluidos no
JavaScript gerado, por exemplo caso o software use uma classe com dez métodos e só é
usado dois métodos dos dez, será gerado código somente para os médotos chamados.
Similarmente se esta classe herda outros métodos de outra classes e não são chamados,
estes métodos não serão gerados no JavaScript.
39

Constant Folding: Quando o valor de uma expressão é conhecido em tempo de
compilação, ele é calculado neste momento e o resultado será usado no código JavaScript
gerado. Por exemplo, a instrução no GWT Window.alert(―Hello ―+‖World‖); gerará o
código $wnd.alert(―Hello World‖) no JavaScript.

Copy Propagation: O valor de uma variável conhecida pode ser eliminada em tempo de
compilação. Por exemplo o codigo int a=15; int b=a*a+5; a segunda instrução será
compilada como int b=230.

String Interning: Para evitar a criação de strings de mesmo mone em java, pois elas são
imutáveis, ou seja para alterar seu valor é necessário a criação de outro objeto string, elas
são criadas internamente uma única vez com o nome $intern_22 por exemplo e usada em
todo o código java.

Code Inlining: O GWT substitui a chamada dos métodos pelo seu corpo, caso ele seja
pequeno e simples.
O JavaScript não tem inteiro de 64 bits, então o GWT emula variáveis long com um
par de inteiros de 32 bits. Isto funciona bem mas é lento, e quando se usa JSNI (Java Script
Native Interface) não é possível passar esta variável. Para números ponto flutuante, JavaScript
prove somente double 64 bits, que pode gerar overflow e resultados imprecisos, pois estas
operações não funcionam exatamente como em Java. Exceptions são manipuladas diferentes
que Java. Em JavaScript a maioria das exeções Java como NullPointerExeption ou
MemoryOverFlowExeption são traduzidas por JavaScriptExeption. Isto causa um problema,
um NullPointerExeption não pode ser diferenciado de um MemoryOverFlowExeption em
JavaScript.
3.2 JRE EMULATION LIBRARY
Google Web Toolkit inclui uma biblioteca que emula um subconjunto da biblioteca
de runtime do Java. Nos Quadros 1, 2 e 3 são mostrados o conjunto de pacotes JRE, que o
GWT pode traduzir automaticamente.
40
Pacotes java.lang
ArithmeticException
ArrayIndexOutOfBoundsException
ArrayStoreException
AssertionError
Boolean
Byte
CharSequence
Character
Class
ClassCastException
Cloneable
Comparable
Deprecated
Double
Enum
Error
Exception
Float
IllegalArgumentException
IllegalStateException
IndexOutOfBoundsException
Integer
Iterable
Long
Math
NegativeArraySizeException
NullPointerException
Number
NumberFormatException
Object
Override
Runnable
RuntimeException
Short
StackTraceElement
String
StringBuffer
StringBuilder
StringIndexOutOfBoundsException
SuppressWarnings
System
Throwable
UnsupportedOperationException
Void
Quadro 1 – Pacotes java.lang suportados pelo GWT
Fonte: GOOGLE WEB… (2011).
Pacotes java.lang.annotation
Annotation
AnnotationFormatError
AnnotationTypeMismatchException
Documented
ElementType
IncompleteAnnotationException
Inherited
Retention
RetentionPolicy
Target
Quadro 2 – Pacotes java.lang.annotation suportados pelo GWT
Fonte: GOOGLE WEB… (2011).
Pacotes Java.util
AbstractCollection
AbstractList
AbstractMap
AbstractQueue
AbstractSequentialList
AbstractSet
ArrayList
Arrays
Collection
Collections
Comparator
ConcurrentModificationException
Date
EmptyStackException
EnumMap
EnumSet
Enumeration
EventListener
EventObject
HashMap
HashSet
IdentityHashMap
Iterator
LinkedHashMap
LinkedHashSet
LinkedList
List
ListIterator
Map
Map.Entry
Quadro 3 – Pacotes java.util suportados pelo GWT
Fonte: GOOGLE WEB… (2011).
MissingResourceException
NoSuchElementException
PriorityQueue
Queue
RandomAccess
Set
SortedMap
SortedSet
Stack
TooManyListenersException
TreeMap
TreeSet
Vector
41
Pacotes java.io
FilterOutputStream
PrintStream
OutputStream
Serializable
Quadro 4 – Pacotes java.io suportados pelo GWT
Fonte: GOOGLE WEB… (2011).
Pacotes java.sql
Date
Timestamp
Time
Quadro 5 – Pacotes java.sql suportados pelo GWT
Fonte: GOOGLE WEB… (2011).
Pacotes extras para prover funcionalidades ao GWT:

com.google.gwt.i18n.client.DateTimeFormat e
com.google.gwt.i18n.client.NumberFormat prove funções para formatação.

com.google.gwt.core.client.Duration prove funções de timing.

com.google.gwt.user.client.Random função para substituir java.util.Random.

com.google.gwt.user.client.Timer função para substituir java.util.Timer.
3.3 UI LIBRARY
GWT prove um grande conjunto de widgets e painéis. Usar widgets é similar a usar
swing em aplicações desktop, mas não há gerenciador de layout, e painéis ou CSS são usados
para posicionar os objetos.
Widgets são mapeados dentro do browser como objetos, e compartilha o aspecto
visual de cada navegador web. Estilos podem ser aplicados a cada objeto separadamente ou
genericamente usando CSS que é a solução preferencial. Na Figura 13 é mostrado os nomes
dos widgers do GWT 2.1.
42
Figura 13 – Nomes dos widgets GWT 2.1
Fonte: Adaptado de WIDGET... (2011).
Exemplo: Criação de um Date Picker. Na Figura 14 é mostrado a imagem de um date
picker.
Figura 14 – Date Picker.
Fonte: DATE… (2011).
43
.gwt-DatePicker {
border: 1px solid #A2BBDD;
cursor: default;
}
.gwt-DatePicker td,
.datePickerMonthSelector td:focus {
outline: none
}
.datePickerMonthSelector td:focus {
outline: none
}
.datePickerDays {
width: 100%;
background: white;
}
.datePickerDay,
.datePickerWeekdayLabel,
.datePickerWeekendLabel {
font-size: 75%;
text-align: center;
padding: 4px;
outline: none;
}
.datePickerWeekdayLabel,
.datePickerWeekendLabel {
background: #C3D9FF;
padding: 0px 4px 2px;
cursor: default;
}
.datePickerDay {
padding: 4px;
cursor: hand;
cursor: pointer;
}
.datePickerDayIsToday {
border: 1px solid black;
padding: 3px;
}
.datePickerDayIsWeekend {
background: #EEEEEE;
}
.datePickerDayIsFiller {
color: #888888;
}
.datePickerDayIsValue {
background: #aaccee;
}
.datePickerDayIsDisabled {
color: #AAAAAA;
font-style: italic;
}
.datePickerDayIsHighlighted {
background: #F0E68C;
}
.datePickerDayIsValueAndHighlighted {
background: #bbddd9;
}
.datePickerMonthSelector {
background: #C3D9FF;
width: 100%;
44
}
.datePickerPreviousButton,
.datePickerNextButton {
font-size: 120%;
line-height: 1em;
color: blue;
cursor: hand;
cursor: pointer;
padding: 0px 4px;
}
td.datePickerMonth {
text-align: center;
vertical-align: center;
white-space: nowrap;
font-size: 70%;
font-weight: bold;
color: blue;
}
.gwt-DateBox input {
width: 8em;
}
.dateBoxFormatError {
background: #ffcccc;
}
.dateBoxPopup {
}
Código 4 – Folha de estilo do date picker
Fonte: DATE… (2011).
/**
* The constants used in this Content Widget.
*/
public static interface CwConstants extends Constants {
String cwDatePickerBoxLabel();
String cwDatePickerDescription();
String cwDatePickerLabel();
String cwDatePickerName();
}
/**
* An instance of the constants.
*/
private final CwConstants constants;
/**
* Initialize this example.
*/
@SuppressWarnings("deprecation")
@Override
public Widget onInitialize() {
// Create a basic date picker
DatePicker datePicker = new DatePicker();
final Label text = new Label();
// Set the value in the text box when the user selects a date
datePicker.addValueChangeHandler(new ValueChangeHandler<Date>() {
public void onValueChange(ValueChangeEvent<Date> event) {
45
Date date = event.getValue();
String dateString = DateTimeFormat.getMediumDateFormat().format(date);
text.setText(dateString);
}
});
// Set the default value
datePicker.setValue(new Date(), true);
// Create a DateBox
DateTimeFormat dateFormat = DateTimeFormat.getLongDateFormat();
DateBox dateBox = new DateBox();
dateBox.setFormat(new DateBox.DefaultFormat(dateFormat));
// Combine the widgets into a panel and return them
VerticalPanel vPanel = new VerticalPanel();
vPanel.add(new HTML(constants.cwDatePickerLabel()));
vPanel.add(text);
vPanel.add(datePicker);
vPanel.add(new HTML(constants.cwDatePickerBoxLabel()));
vPanel.add(dateBox);
return vPanel;
}
Código 5 – Fonte do DatePicker Java/GWT
Fonte: DATE… (2011).
O código java acima mostra a criação de um date picker, onde os objetos são
inseridos em um painel (vPanel) e ele é retornado pelo método publico widget. Caso esta
função seja chamada por um JavaScript em uma página HTML o Date Picker será desenhado
no local chamado.
A coleção de Widgets GWT nativos ainda é limitada, espaço que acaba sendo
preenchido por bibliotecas de terceiros como Ext-Sencha, Smart-GWT e GWT Mosaic. Na
Figura 15 é ilustrada a biblioteca Smart-GWT com 300 exemplos de uso de widgets
(SMART…, 2011).
46
Figura 15 – Biblioteca Smart-GWT
Fonte: SMART... (2011).
3.4 SETTING UP GWT
O Plug-in do Google para o Eclipse (Figura 16 e 17) é a maneira mais rápida de
começar o desenvolvimento de aplicativos do Google Web Toolkit e do Google App Engine.
Com a instalação do plug-in é possível a implementação de um ―Hello World‖ Ajax em
questão de minutos. Basta instalar o plug-in e começar. O estudo de caso deste trabalho usará
o Eclipse 3.6 (Helios). Os detalhes para obtenção do Eclipse e dos plugins estão descritos em
GOOGLE CODE. Na Figura 18 é mostrada a instalação dos plugins do GWT no eclipse, o
Google Plugin para o Eclipse 3.6 está na versão 1.4.2, o Google App Engine Java SDK está
na versão 1.4.0 e o Google Web ToolKit DSK está na versão 2.1.1, as ultimas versões
disponíveis até este momento.
47
Figura 16 – Eclipse Helios 3.6
Fonte: Autoria própria.
Figura 17 – IDE Eclipse Helios 3.6 com os ícones do GWT e App Engine
Fonte: Autoria própria.
Uma preocupação no uso do GWT é conhecer as melhores práticas ao desenvolver
aplicações, para escrever código desacoplado, testável e manutenível. Ray Ryan um dos
arquitetos do GWT no Google I/O em 2009 e 2010 (Figura 19) discutiu a inexistência de uma
API nativa implementando estas melhores práticas, ficava a cargo do desenvolvedor
interpretá-las e programar a sua própria arquitetura caseira. Com o GWT 2.1 a Google
começa a preencher estas lacunas, entre as novidades da nova versão está o Data Presentation
Widgets, o Data Binding com editors e o Framework GWT-MVP, baseado em Atividades e
Lugares (Activities e Places).
48
Figura 18 – Detalhes da instalação do GWT e App Engine no Eclipse 3.6
Fonte: Autoria própria.
Figura 19 – Ray Ryan no Google I/O 2009.
Fonte: GOOGLE I/O... (2009).
49
3.5 PROJETO E DESENVOLVIMENTO
Depois de tudo instalado localmente, pois o eclipse ainda não trabalha nas nuvens,
basta criar um novo projeto informando o local no HD (workspace) em que será gravado e seu
nome. Na Figura 20 é ilustrada a janela de criação de um projeto GWT.
Figura 20 - Criação de um projeto GTW.
Fonte: Autoria própria.
50
A ferramenta GWT cria uma estrutura de diretórios como a ilustrada na Figura 21.
Figura 21 – Estrutura de diretórios de um projeto GTW
Fonte: Autoria própria.
Todo o código Java desenvolvido como classes Java e servlets fica residente no
diretório src (source) que é dividido pelos sub-diretórios client (código que é executado no
browser do usuário), shared (código que pode ser executado tanto do lado cliente como do
lado servidor) e o diretório server (código que é executado exclusivamente no lado do
servidor). As classes de teste ficam no diretório test. No pacote META INF ficam as
configurações XML para persistência, no pacote App Engine SDK ficam o SDK para o
desenvolvimento em cloud, no pacote JRE ficam o Java runtime no pacote WEB-INF contém
a pasta lib para agregar drivers e frameworks do projeto.
O código gerado pela ferramenta para distribuição da aplicação fica no diretório war
(Web Archive). Os arquivos com extensão war são um compactado de todo o código para
implantação no servidor de aplicação. No diretório ―war‖ também ficam os arquivos estáticos
como os de formatação CSS, HTML e imagens por exemplo.
A unidade básica do GWT são os módulos. Estes módulos são usados pela aplicação
cliente ou para criação de bibliotecas que serão usadas por outras aplicações. A definição dos
módulos estão no arquivo gwt.xml, como exemplificado no Código 6.
51
<?xml version="1.0" encoding="ISO-8859-1"?>
<module rename-to='cotacaoacoes'>
<!-- Inherit the core Web Toolkit stuff.
<inherits name='com.google.gwt.user.User'/>
-->
<!-- Inherit the default GWT style sheet. You can change
-->
<!-- the theme of your GWT application by uncommenting
-->
<!-- any one of the following lines.
-->
<inherits name='com.google.gwt.user.theme.standard.Standard'/>
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<!-- Other module inherits
-->
<!-- Specify the app entry point class.
-->
<entry-point class='com.dvillela.gwt.cotacaoacoes.client.CotacaoAcoes'/>
<!-- Specify the paths for translatable code
<source path='client'/>
<source path='shared'/>
-->
</module>
Código 6 - Exemplo de um arquivo gwt.xml para definição de módulos
Fonte: Autoria própria, utilizando o Eclipse.
Nesta definição de módulo o código, encoding="ISO-8859-1" permite o uso de
caracteres em português, <module rename-to='cotacaoacoes'> define o nome do módulo,
<inherits name='com.google.gwt.user.User'/> indica herança das classes gwt.user, <entrypoint class='com.dvillela.gwt.cotacaoacoes.client.CotacaoAcoes'/> especifica o módulo de
entrada
quando
o
aplicativo
for
executado
e
<inherits
name=
'com.google.gwt.user.theme.standard.Standard'/> especifica o uso do estilo default para os
widgets.
Depois de tudo desenvolvido, a fase de testes basta executar o projeto como uma
aplicação Web. Na Figura 22 é ilustrada a forma de entrar em modo de desenvolvimento e
teste da aplicação. Na janela Console é informado os erros de compilação ou as mensagens de
compilação com sucesso. Na janela Development Mode é informada a URL para teste local, a
ferramenta de desenvolvimento simula um servidor de aplicação (Jetty), que compõem o
desenvolvimento para cloud computing utilizando o Google Application Engine.
52
Figura 22 – Modo de desenvolvimento do GWT no Eclipse
Fonte: Autoria própria.
Depois de testada a aplicação, é necessário definir o Application ID e sua versão
(controle de versões) para fazer a implantação no Data da Google. A versão do SDK do App
Engine no servido da Google está na versão 1.4.1 neste momento, e no ambiente de
desenvolvimento está disponível a versão 1.4.0. Na Figura 23 é ilustrada esta janela.
53
Figura 23 – Configuração dos parâmetros para implantação
Fonte: Autoria própria.
Finalmente para terminar a implantação no Data Center é necessário o uso de uma
conta no Google, pode ser a mesma do Gmail. Na Figura 24 é ilustrada esta janela. Todo este
processo está descrito em detalhes no Google Code.
Figura 24 – Implantação da aplicação no Data Center da Google
Fonte: Autoria própria.
54
3.6 TRABALHANDO COM BROWERS
Um problema para as aplicações escritas com a ferramenta GWT é voltar à tela
anterior no browser usando Alt+Backspace, combo ou botão do browser, porque as aplicações
GWT são executadas em uma única janela criada dinamicamente e sendo modificada
conforme a necessidade, e esta ação provavelmente farão uma desconexão da aplicação com o
usuário, ou algo inesperado de difícil tratamento.
O usuário não pode esperar que uma aplicação GWT se comporte de forma diferente
das outra aplicações Web, o desenvolvedor não tem como desabilitar o Alt+Backspace, por
este motivo o GWT possui métodos para tratar de históricos.
Para usar as classes de gerenciamento de históricos do GWT é necessário inserir no
corpo <body> da página HTML o seguinte código JavaScript.
<!-- OPTIONAL: include this if you want history support -->
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1'
style="position: absolute; width: 0; height: 0; border: 0">
</iframe>
Código 7 – Ativação do gerenciamento de histórico de navegação do GWT.
Fonte: Autoria própria.
Outro problema encontrado é a bloqueio de execução de JavaScript na configuração
dos navegadores. O que o desenvolvedor pode fazer no máximo é gerar uma exceção no
código HTML, informando o usuário para habilitar a execução de códigos JajaScript, ou a
aplicação não será executada. Para fazer isto basta acrescentar ao código HTML o seguinte
código. O Código 8 faz com que o navegador do cliente emita uma mensagem caso ele não
esteja habilitado para executar JavaScript.
<!-- RECOMMENDED if your web app will not function without JavaScript enabled -->
<noscript>
<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; border: 1px
solid red; padding: 4px; font-family: sans-serif">
Your web browser must have JavaScript enabled in order for this
application to display correctly.
</div>
</noscript>
Código 8 – Código para exibir mensagem do status do navegador
Fonte: Autoria própria.
55
O resultado caso a execução de JavaScript não esteja habilitada, é a mensagem que
aparece no navegador como a mostrada na figura 25, alertando que a execução de JavaScript
não está habilitada.
Figura 25 - Mensagem no browser
Fonte: Autoria própria.
3.7 DESENVOLVIMENTO DE INTERFACE COM O USUÁRIO
O padrão de desenvolvimento clássico de interface com o usuário é o MVC (ModelView-Controller), que surgiu com o Smalltalk na década de 80, tinha como principal objetivo
implementar uma alta independência entre os módulos do modelo,a view, a apresentação e a
lógica. Basicamente o padrão MVC é composto de:

Model, aqui se encontram toda a lógica de negócios da aplicação, Para sistemas baseados
em Web, isto significa servlets, web services ou qualquer outra forma de implementação
de requisitos do sistema no lado do servidor de aplicação.

View, aqui estão todos os widgets necessários para interação com o usuário. Para sistemas
Web a camada de view reside no lado do cliente.

Controller, sua função é traduzir as ações do usuário para a camada de modelo.
Dependendo do framework usado ele pode se encontrar o lado cliente ou no lado servidor,
mas isto não é relevante aqui.
Com o surgimento de novas tecnologias como o GWT, e o aperfeiçoamento dos
frameworks de interface, o modelo MVC ficou mais difícil de ser seguido pelas aplicações
que utilizem estes componentes, os próprios componentes passaram a ter agora meios
melhores de manipulação de eventos realizados pelos usuários, e o padrão MVC não permite
que a camada view possa ser manipulada diretamente como acontece com JSP, por exemplo,
ou seja, precisamos disparar um evento e deixar que a servlet trate esta mudança (recarregar a
56
págiana web). Desta forma a camada de Controller passou a cair em desuso, já que caso fosse
utilizado os componentes estariam sendo subtilizados (CAMILO, 2010)
Para solucionar este problema, surge o modelo MVP (Model View Presenter), uma
variação do padrão MVC clássico, porém mais adequada para as novas tecnologias como o
GWT. Neste modelo, as responsabilidades que eram do Controller são redistribuídas entre as
camadas View e o Presenter, a View se encarrega de lidar com as entradas dos usuários, e o
Presenter se encarrega de interagir com o Modelo, desta forma, o Presenter tem direito de
interagir diretamente com a View. Basicamente o padrão MVP é composto de:

Model, tem a mesma regra do modelo MVC, mas somente se comunica com a camada
Presenter.

View, tem regra similar ao modelo MVC, mas não de comunica com a camada Model.
Sempre que o usuário dispara um evento, esta camada informa o Presenter sobre o evento,
que pode pedir para a camada View se atualizar.

Presenter, é a novidade deste padrão, por ser uma ponte entre a camada de Model e a
camada View. Em resposta para eventos de usuários esta camada pode se comunicar com
o Model e dependendo da resposta pode enviar comandos para a camada de View.
Na Figura 26 é ilustrado o relacionamento das camadas nos modelos MVC e MVP.
Figura 26 – Modelos MVC e MVP
Fonte: Camilo (2010).
57
No padrão MVP a camada View é muito simples e praticamente não tem código, terá
somente código para criar widgets, pegar e setar seus valores e disparar eventos para a camada
Presenter. Se o usuário entrar com um valor em um widget, a camada View não fará sua
validação, disparando um evento para a camada Presenter validar.
Antes de implementar o padrão MVP, é necessário conhecer o conceito de callback.
Nas aplicações em uma arquitetura de objetos distribuídos como é o caso do GWT, nem
sempre a comunicação no estilo cliente-servidor é suficiente para atender aos requisitos da
aplicação. É usual que o servidor RMI (Remote Method Invocation) aja algumas vezes com o
cliente, invertendo os papéis com o cliente RMI original.
Por exemplo, um applet cliente RMI. Nesse applet, não há como saber se outro
cliente do mesmo objeto remoto na rede realizou alguma atualização no valor de um atributo
deste mesmo objeto usado pelo applet a não ser pressionando o botão Get, e verificando se
houve mudança. Essa é uma situação típica em muitas aplicações, sendo clara a necessidade
de realizar tais notificações de forma automática.
A tecnologia para atingir esse objetivo é utilizar a estratégia de callback. Esta técnica é
utilizada quando a aplicação cliente requer um retorno do servidor, mas não quer permanecer
bloqueada aguardando a resposta enquanto o servidor a processa. Através dessa tecnologia, o
servidor obtém uma referência para o cliente para poder invocar remotamente um método do
objeto cliente. Assim, quando o processamento do serviço solicitado for concluído o servidor
pode notificar o cliente através da invocação do método disponibilizado pelo cliente para uso
remoto.
Assim como para o objeto servidor RMI, o cliente deve oferecer uma interface remota
para o servidor (que é o cliente agora) a fim de permitir que o servidor tenha acesso ao serviço
de atualização do cliente. Com callback, ambos cliente e servidor devem implementar o
serviço remoto especificado.
Um exemplo bem simples de callback são os métodos contidos nos aparelhos de
telefônica celular, em que a operadora deve ter acesso ao método de tocar do celular, ou seja,
neste caso o celular é o servidor e a operadora o cliente.
Outro conceito utilizado no GWT é Generics, ou programação genérica, que serve
para determinar ao compilador qual tipo de classe deve ser interpretada.
Na Figura 27 é ilustrado um modelo de classes escrito na linguagem de modelagem
unificada (UML) utilizando a ferramenta JUDE professional, de um projeto de tela de login
no padrão MVP. As classes SimpleCallback e Presenter são classes genéricas, e é a classe
LoginFormPresenter que determina o tipo de objetos que elas vão manipular.
58
A Classe Model tem diversos métodos para acessar os serviços do lado do servidor.
Figura 27 – Diagrama de classes UML para o padrão MVP da tela de login
Fonte: Autoria própria.
A classe de abstrata SimpleCallback listada
no Código 9, possibilita escrever
códigos Java mais curtos, pois ela é genérica para qualquer outro projeto.
import com.google.gwt.user.client.rpc.AsyncCallback;
public abstract class SimpleCallback<T> implements AsyncCallback<T> {
@Override
public final void onFailure(Throwable caught) {
// Nunca deverá ser usado
59
}
@Override
public final void onSuccess(T result) {
goBack(result);
}
public abstract void goBack(T result);
}
Código 9 – Implementação da classe SimpleCallback
Fonte: Kereki (2010).
A interface AsyncCallback requer a implementação de ambos os métodos onFailure
e onSuccess. Contudo não há necessidade de lidar com falhas, somente com sucessos. Esta
classe abstrata SimpleCallback define os métodos onFailure e onSuccess finais, portanto não
necessidade de ser implementado, e o método goBack como abstrato que necessita ser
implementado futuramente.
Na classe Presenter<D> descrita no Código 10, é injetado via construtor o apropriado
Environment e View. A classe Presenter injeta os callbacks na classe View através do método
definido na interface Display.
abstract public class Presenter<D> {
private String params;
private D display;
private Environment environment;
private KeyValueMap kvm;
public Presenter() {
}
public Presenter(String someParams, D aDisplay, Environment anEnvironment) {
super();
params = someParams;
display = aDisplay;
environment = anEnvironment;
kvm = new KeyValueMap(params);
}
public D getDisplay() {
return display;
}
public Environment getEnvironment() {
return environment;
}
public KeyValueMap getKvm() {
return kvm;
}
}
Código 10 – Classe Presenter<D>
Fonte: Kereki (2010).
60
Na classe LoginFormPresenter listada no Código 11, a string PLACE serve para o
bookmark e gerenciamento de histórico
import com.fkereki.mvpproject.client.Environment;
import com.fkereki.mvpproject.client.Presenter;
import com.fkereki.mvpproject.client.SimpleCallback;
import com.fkereki.mvpproject.client.rpc.LoginServiceAsync;
import com.google.gwt.user.client.rpc.AsyncCallback;
public class LoginFormPresenter extends Presenter<LoginFormDisplay> {
public static String PLACE = "login";
LoginServiceAsync loginService;
SimpleCallback<String> loginSuccessCallback;
public LoginFormPresenter(
final String params, final LoginFormDisplay loginDisplay,
final Environment environment,
final SimpleCallback<String> callback) {
super(params, loginDisplay, environment);
loginSuccessCallback = callback;
loginService = getEnvironment().getModel().getRemoteLoginService();
loginDisplay.setName("domingos");
loginDisplay.setPassword("");
loginDisplay.setLoginCallback(new SimpleCallback<Object>() {
@Override
public void goBack(final Object result) {
final String name = LoginFormPresenter.this.getDisplay().getName();
final String pass = LoginFormPresenter.this.getDisplay().getPassword();
loginService.getSomething(name, pass,new AsyncCallback<String>() {
public void onFailure(final Throwable caught) {
LoginFormPresenter.this.getEnvironment().showAlert("Failed login");
loginSuccessCallback.onFailure(new Throwable());
}
public void onSuccess(final String result) {
loginSuccessCallback.goBack(result);
}
});
}
});
}
}
Código 11 – Classe LoginFormPresenter
Fonte: Kereki (2010).
61
O Código 12 mostra a listagem da interface LoginFormDisplay que herda os
métodos de Display.
import com.fkereki.mvpproject.client.Display;
import com.fkereki.mvpproject.client.SimpleCallback;
public interface LoginFormDisplay extends Display {
/**
* Access the Name field
*
* @return Whatever the user entered in the Name field
*/
String getName();
/**
* Initialize the Name field
*
* @param s
*
Set the name field to s; most commonly just "" or possibly a saved
*
name from an earlier session.
*/
void setName(String s);
/**
* Access the Password field
*
* @return Whatever the user entered in the Password field
*/
String getPassword();
/**
* Initialize the Password field
*
* @param s
*
Set the password field to s; usually just ""
*/
void setPassword(String s);
/**
* Initialize the login callback, which shall be executed when the user clicks
* the "Login" button
*
* @param acb
*
Set the login callback to acb. The Presenter will have to get the
*
Name and Password fields (by using the methods above) and perform
*
the needed checks.
*/
void setLoginCallback(SimpleCallback<Object> acb);
}
Código 12 – Interface LoginFormDisplay
Fonte: Kereki (2010).
62
O Código 13 mostra a listagem da interface Display.
import com.google.gwt.user.client.ui.Widget;
/**
* @author fkereki
*/
public interface Display {
public Widget asWidget();
}
Código 13 – Interface Display
Fonte: Kereki (2010).
O Código 14 mostra a listagem da classe LoginFormView que por sua vez herda
View que herda Composite, e implementa LoginFormDisplay.
import com.fkereki.mvpproject.client.SimpleCallback;
import com.fkereki.mvpproject.client.View;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.TextBox;
/**
* Defines a Login Form.
*/
public class LoginFormView extends View implements LoginFormDisplay {
private AsyncCallback<Object> loginCallback;
private final TextBox nameTextBox = new TextBox();
private final TextBox passwordTextBox = new PasswordTextBox();
private final Button loginButton = new Button("Log in");
private final FlexTable flex = new FlexTable();
private final DockPanel dock = new DockPanel();
/**
* Defines the view for the Login Form. Since this will be shown in the main
* screen, we take care of centering the fields (by using a DockPanel) so it
* will look nicer.
*/
public LoginFormView() {
loginButton.addClickHandler(new ClickHandler() {
public void onClick(final ClickEvent event) {
loginCallback.onSuccess(null);
}
});
flex.setWidget(0, 0, new Label("User name:"));
flex.setWidget(0, 1, nameTextBox);
63
flex.setWidget(1, 0, new Label("Password:"));
flex.setWidget(1, 1, passwordTextBox);
flex.setWidget(2, 1, loginButton);
dock.setWidth("100%");
dock.setHeight("100%");
dock.setHorizontalAlignment(DockPanel.ALIGN_CENTER);
dock.setVerticalAlignment(DockPanel.ALIGN_MIDDLE);
dock.add(flex, DockPanel.CENTER);
initWidget(dock);
}
@Override
public final String getName() {
return nameTextBox.getValue();
}
@Override
public final String getPassword() {
return passwordTextBox.getValue();
}
@Override
public final void setLoginCallback(final SimpleCallback<Object> acb) {
loginCallback = acb;
}
@Override
public final void setName(final String s) {
nameTextBox.setValue(s);
}
@Override
public final void setPassword(final String s) {
passwordTextBox.setValue(s);
}
}
Código 14 – Classe LoginFormView
Fonte: Kereki (2010).
O Código 15 mostra a listagem da classe View.
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
/**
* @author fkereki
*/
public abstract class View extends Composite {
public final Widget asWidget() {
return this;
}
}
Código 15 – Classe View
Fonte: Kereki (2010).
64
Há uma forma de evitar que o código de criação dos widgets não fique dentro da
classe LoginFormView vinculado a interface de usuário a duas ou três linhas de código por
widget, e que facilita o trabalho com um grande número de elementos de interface. Outro
problema é entender o layout produzido pelo código Java, e a comunicação entre o projeto da
interface do usuário feita em HTML, CSS e XML e o código GWT.
O GWT 2 criou o UiBinder que atenua o problema, permitindo que a interface com o
usuário seja feita declarativamente usando linguagem de marcação XML, que é transformada
em código Java pelo compilador. UiBinder aceita estilos CSS e internacionalização.
Na Figura 28 é ilustrada a criação de um UiBinder pelo plugin do GWT no eclipse.
Figura 28 – Criação de um arquivo UiBinder
Fonte: Autoria própria.
Uma versão do exemplo de login usando UiBinder é listado no Código 16.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE u:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<u:UiBinder xmlns:u='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' >
<g:HTMLPanel>
<h1>LoginFormView3</h1>
<table>
<tr>
<td><g:Label text="User Name:"/></td>
<td><g:TextBox u:field='nameTextBox'/></td>
65
</tr>
<tr>
<td><g:Label text="Password:"/></td>
<td><g:PasswordTextBox u:field='passwordTextBox'/></td>
</tr>
<tr>
<td></td>
<td><g:Button text='Login' u:field='loginButton'/></td>
</tr>
</table>
</g:HTMLPanel>
</u:UiBinder>
Código 16 – Exemplo de arquivo XML para definição de interface gráfica.
Fonte: Kereki (2010).
O compilador faz uma referencia cruzada entre o arquivo UiBinder e a nova classe
LoginFormView é mostrada o Código 17.
import com.fkereki.mvpproject.client.SimpleCallback;
import com.fkereki.mvpproject.client.View;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.TextBox;
/**
* Defines a Login Form.
*/
public class LoginFormView extends View implements LoginFormDisplay {
@UiTemplate("UiLoginFormView.ui.xml")
interface Binder extends UiBinder<HTMLPanel, UiLoginFormView> { }
AsyncCallback<Object> loginCallback;
AsyncCallback<Object> nameBlurCallback;
AsyncCallback<Object> passwordBlurCallback;
@UiField TextBox nameTextBox;
@UiField PasswordTextBox passwordTextBox;
@UiField Button loginButton;
private static final Binder binder = GWT.create(Binder.class);
public LoginFormView() {
HTMLPanel dlp = binder.createAndBindUi(this);
initWidget(dlp);
}
@Override
66
public void enableLoginButton(final boolean b) {
loginButton.setEnabled(b);
}
@Override
public final String getName() {
return nameTextBox.getValue();
}
@Override
public final String getPassword() {
return passwordTextBox.getValue();
}
@Override
public final void setLoginCallback(final SimpleCallback<Object> acb) {
loginCallback = acb;
}
@Override
public final void setName(final String s) {
nameTextBox.setValue(s);
}
@Override
public void setNameBlurCallback(final SimpleCallback<Object> acb) {
nameBlurCallback = acb;
}
@Override
public final void setPassword(final String s) {
passwordTextBox.setValue(s);
}
@Override
public void setPasswordBlurCallback(final SimpleCallback<Object> acb) {
passwordBlurCallback = acb;
}
@UiHandler("nameTextBox")
void uiOnBlurName(BlurEvent event) {
nameBlurCallback.onSuccess(null);
}
@UiHandler("passwordTextBox")
void uiOnBlurPassword(BlurEvent event) {
passwordBlurCallback.onSuccess(null);
}
@UiHandler("loginButton")
void uiOnLoginButton(ClickEvent event) {
loginCallback.onSuccess(null);
}
}
Código 17 – Classe LoginFormView usando UiBinder
Fonte: Kereki (2010).
67
3.8 COMUNICAÇÃO COM O SERVIDOR DE APLICAÇÕES
Para a implementação de comunicação entre o lado cliente e o lado servidor, existe
duas tecnologias a RPC e RMI. Marshalling é o processo de se empacotar uma coleção de
objetos em um formato específico para sua transmissão em uma mensagem, e Unmarshalling
é o processo inverso.
RMI (Remote Method Invocation) é uma tecnologia para chamadas de métodos em
objetos remotos. Para se comunicar com objetos remotos, são usados stubs e skeletons, o stub
funciona semelhante a um proxy para o objeto remoto. Quando um objeto local invoca um
método num objeto remoto, o stub fica responsável por enviar a chamada ao método do objeto
remoto. Os passos do stub quando é invocado são:

Iniciar conexão com a Virtual Machine que contém o objeto remoto.

Escrever (Marshalling) e transmitir os parâmetros para a Virtual Machine remota.

Esperar pelos resultados da invocação do método.

Ler os resultados retornados.

Retornar os valores ao objeto que executou a chamada.
Na Virtual Machine remota, cada objeto deve ter um skeleton correspondente ao
stub. O skeleton é responsável por enviar a chamada ao objeto remoto. Passos do skeleton
quando recebe uma chamada:

Ler os parâmetros (Unmarshalling) enviados pelo stub.

Invocar o método no objeto remoto.

Escrever (Marshalling) e transmitir o resultado ao objeto que executou a chamada.
No paradigma orientado a objetos a distribuição física dos objetos é, natural. RMI é
uma interface de programação que permite a execução de chamadas remotas em aplicações
desenvolvidas em Java RMI, OMG CORBA (Common Object Request Broker Architecture)
ou Microsoft DCOM (Distributed Common Object Model). É uma das abordagens da
plataforma Java para prover as funcionalidades de objetos distribuídos. Esse sistema de
objetos distribuídos faz parte do núcleo básico de Java desde a versão JDK 1.1, com sua API
68
sendo especificada através do pacote java.rmi. A Figura 29 ilustra o funcionamento desta
tecnologia.
Figura 29 – Tecnologia Remote Method Invocation
Fonte: Adaptado RMI-IIPO (2011).
O RPC, (Remote Procedure Call) é uma tecnologia de comunicação entre processos
que torna possível a um programa de computador chamar um método em outro computador,
conectado por uma rede. O desenvolvedor não precisa se preocupar com detalhes de
implementação dessa interação remota. Do ponto de vista do código, a chamada se assemelha
às chamadas de procedures locais.
RPC é uma tecnologia para a implementação do modelo cliente-servidor de
computação distribuída. Uma chamada de procedimento remoto é iniciada pelo cliente
enviando uma mensagem para um servidor remoto para executar um método específico, uma
resposta é retornada ao cliente. A implementação de chamadas a procedimento remoto é feita
com os seguintes passos:

O procedimento cliente chama localmente o stub cliente;

Stub cliente constrói (Marshalling) a mensagem e chama o SO local;

O SO local envia a mensagem ao SO remoto;

O SO Remoto entrega a mensagem ao stub servidor;

O stub servidor desempacota (Unmarshalling) os parâmetros e chama o procedimento
servidor;

O servidor realiza o trabalho retornando o resultado ao stub;

O stub servidor empacota (Marshalling) o resultado em uma mensagem e chama o SO
local;
69

O SO do servidor envia a mensagem ao SO do cliente;

O SO do cliente entrega a mensagem ao stub cliente;

O stub cliente desempacota (Unmarshalling) o resultado e o retorna ao cliente.
RPC permite ao desenvolvedor GWT escrever código Java como se o lado cliente e o
lado servidor estivesse residente na mesma máquina, permitindo que a conexão fique
praticamente invisível. Na Figura 30 é ilustra no mecanismo de comunicação utilizado pelo GWT.
Figura 30 – Arquitetura do GWT.
Fonte: DEVELOPER´S... (2011).
A mais importante diferença entre o RMI e o RPC é a forma de sincronismo, no RMI
o processo de comunicação é síncrono ou seja ele bloqueia o processo chamador até que o
processo servidor responda, e no RPC o processo de comunicação é assíncrono ou seja o
processo chamador não fica bloqueado.
No modelo RPC utilizado pelo GWT há algumas diferenças, por exemplo, o código do
lado servidor pode usar qualquer pacote do Java, enquanto do lado cliente o código é limitado.
Para implementação o RPC usa Ajax e o GWT prove as classes clientes HTTP. No
lado servidor servlets são usadas estendendo a classe RemoteServiceServlet e não há limites,
nesta arquiterua pode-se usar EJB (Enterprise Java Beans) ou serviços Restful (técnica de
engenharia de software para sistemas hipermídia distribuídos como o www).
O uso mais comum de RPC é acessar servles ou EJB no lado servidor, código
particionado desta forma reduz o tempo de carga da aplicação.
70
Uma principal diferença entre as aplicações AJAX e aplicações web tradicionais em
HTML é que nos aplicativos Ajax não é necessário buscar novas páginas HTML, enquanto eles
executam. Como as páginas Ajax realmente funcionam mais como aplicações dentro do navegador,
não há necessidade de solicitar novo HTML do servidor para fazer atualizações de interface com o
usuário. No entanto, como todas as aplicações cliente/servidor, aplicações Ajax geralmente
precisam buscar dados do servidor. Quando usado corretamente, RPCs pode mudar toda a lógica da
interface do usuário para o cliente sem recarregar a página, resultando em um desempenho muito
melhorado, diminuindo a largura de banda, e reduzindo a carga do servidor web.
O código server-side que é chamado do cliente é muitas vezes referida como um
serviço, portanto o ato de fazer uma chamada de procedimento remoto é por vezes referido
como chamar um serviço. A palavra ―serviço‖ neste contexto não é o mesmo que web service
no conceito geral. Em particular, os serviços do GWT não estão relacionados com o Simple
Object Access Protocol (SOAP).
Na arquitetura do GWT a interface publica YourService fica do lado cliente, e é a
interface YourServiceAsync que implementa o stub é quem intermediará com o servidor o
qual passa o resultado para o chamador via AsyncCallback. É na classe publica
YourServiceImp que ficará todo o código Java que implementa os serviços do lado servidor.
O Código 18 mostra o arquivo war/WEB-INF/lib/web.xml que fornece dados sobre
a servlet remota, usando <servlet> e <servlet-mapping>.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE web-app (View Source for full doctype...)>
<web-app>
<!-- Servlets -->
<servlet>
<servlet-name>loginServlet</servlet-name>
<servlet-class>com.fkereki.mvpproject.server.LoginServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>loginServlet</servlet-name>
<url-pattern>/mvpproject/login</url-pattern>
</servlet-mapping>
<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>Mvpproject.html</welcome-file>
</welcome-file-list>
</web-app>
Código 18 – Web.xml
Fonte: Kereki (2010).
71
Serialização é usada transparentemente pelo GWT, de forma genérica a serialização
é uma técnica usada para persistir objetos (gravar objetos em disco ou banco de dados) ou
fazer a transmissão remota de objetos via rede.
Serializar é simplesmente colocar os valores dos atributos que o objeto está utilizando
juntamente com suas propriedades de uma forma que fique em série (seqüencial). Objeto
serializavel, tem privilégios para que o mesmo possa ser gravado em disco ou enviado por rede.
Portanto a serialização é o processo de transformar um objeto, incluindo todos os atributos
públicos e privados em um stream (fluxo de dados em um sistema computacional) para ser
transportado. Na Figura 31 é ilustrada a gravação de um objeto em um arquivo no HD.
Figura 31 – Serialização de um objeto, e persistência em disco rígido
Fonte: Pereira (2010).
O GWT tem seus próprios métodos de serialização, a regra para definição dos tipos
serializáveis são simples. Todos os tipos primitivos (char, byte, short, int, long), tipos
enumerados (string,e data), e arrays são serializáveis. Uma classe será serializável se todos
seus atributos são de tipos serializáveis, com exceção dos atributos transientes e finais. No
Código 19 está a listagem de um exemplo de uma classe serializável pelo GWT.
import com.google.gwt.user.client.rpc.IsSerializable;
public class ClientCityData implements IsSerializable {
public String countryCode;
public String stateCode;
public String cityName;
public String cityAccentedName;
public int population;
public float latitude;
public float longitude;
/**
* An empty constructor method is required for serializable classes... see
* <a>http://blog.js-development.com/2008/08/strange-gwt-compiler-error-when- trying.html</a >
* <a>http://code.google.com/p/google-web-toolkit/issues/detail?id=540</a>
*/
public ClientCityData() {
}
72
public ClientCityData(
final String pCountryCode, final String pStateCode,
final String pCityName, final String pCityAccentedName,
final int pPopulation, final float pLatitude,
final float pLongitude) {
countryCode = pCountryCode;
stateCode = pStateCode;
cityName = pCityName;
cityAccentedName = pCityAccentedName;
population = pPopulation;
latitude = pLatitude;
longitude = pLongitude;
}
/**
* Perform client-side validations. The code here is limited to the GWT
* client-side available packages.
*
* @return "" if the client data is OK, or an error description otherwise
*/
public String validationProblems() {
if (countryCode.isEmpty()) {
return "No country specified";
} else if (stateCode.isEmpty()) {
return "No region specified";
} else if (cityName.isEmpty()) {
return "No city name specified";
} else if (cityAccentedName.isEmpty()) {
return "No accented city name specified";
} else if (population < 0) {
return "Negative population";
} else if (latitude < -90 || latitude > 90) {
return "Latitude outside -90..+90";
} else if (longitude < -180 || longitude > 180) {
return "Longitude outside -180..+180";
} else {
return "";
}
}
}
Código 19 – Exemplo de classe serializável
Fonte: Kereki (2010).
O Código 20 lista o código da interface YourService.java
import java.util.LinkedHashMap;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
@RemoteServiceRelativePath("world")
public interface WorldService extends RemoteService {
public String addCity(ClientCityData cd);
public Boolean cityExists(
String pCountry,
String pRegion,
73
String pCity);
public LinkedHashMap<String, ClientCityData> getCities(
String pCountry,
String pRegion,
int pFrom,
int pQuantity);
public LinkedHashMap<String, ClientCityData> getCitiesStartingWith(
String pCountry,
String pRegion,
String pStart);
public LinkedHashMap<String, String> getCountries();
public LinkedHashMap<String, String> getStates(String pCountry);
}
Código 20 – Inferface YourService.java
Fonte: Kereki (2010).
Abaixo a listagem correspondente a Async interface derivado de WorldService. Pode
ser criada automaticamente pelo plugin do GWT no Eclipse.
import java.util.LinkedHashMap;
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface WorldServiceAsync {
void addCity(ClientCityData cd, AsyncCallback<String> callback);
void cityExists(
String pCountry,
String pRegion,
String pCity,
AsyncCallback<Boolean> callback);
void getCities(
String pCountry,
String pRegion,
int pFrom,
int pQuantity,
AsyncCallback<LinkedHashMap<String, ClientCityData>> callback);
void getCitiesStartingWith(
String pCountry,
String pRegion,
String pStart,
AsyncCallback<LinkedHashMap<String, ClientCityData>> callback);
void getCountries(
AsyncCallback<LinkedHashMap<String, String>> callback);
void getStates( String pCountry,
AsyncCallback<LinkedHashMap<String, String>> callback);
}
Código 21 – Inferface WorldServiceAsync
Fonte: Kereki (2010).
74
Finalmente abaixo está a listagem da implementação dos serviços no lado servidor,
pode-se usar JPA ou Hibernate nesta implementação. No Google Application Engine deve-se
usar o Java Data Objects.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.LinkedHashMap;
import com.fkereki.mvpproject.client.rpc.ClientCityData;
import com.fkereki.mvpproject.client.rpc.WorldService;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
public class WorldServiceImpl extends RemoteServiceServlet implements WorldService {
private static final long serialVersionUID = 1L;
/*
* MySQL and JDBC related constants and variables
*/
static String jdbc_url = "jdbc:mysql://127.0.0.1/gwtdb";
static String mysql_user = "gwtuser";
static String mysql_password = "gwtpass";
private Connection conn = null;
/**
* Tries to add a new city to the database.
*
* @return "" if the city was added, or an error message otherwise
*/
public String addCity(final ClientCityData cd) {
final ServerCityData scd = new ServerCityData(cd);
final String svp = scd.validationProblems();
if (!svp.isEmpty()) {
return svp;
} else {
try {
connectToDatabase();
final PreparedStatement ps = conn
.prepareStatement("INSERT INTO cities (countryCode, stateCode, "
+ "cityName, cityAccentedName, population, latitude, longitude) "
+ "VALUES (?,?,?,?,?,?,?)");
ps.setString(1, scd.countryCode);
ps.setString(2, scd.stateCode);
ps.setString(3, scd.cityName);
ps.setString(4, scd.cityAccentedName);
ps.setInt(5, scd.population);
ps.setFloat(6, scd.latitude);
ps.setFloat(7, scd.longitude);
ps.executeUpdate();
ps.close();
disconnectFromDatabase();
} catch (final Exception e) {
return "Error adding city: " + e.getMessage();
75
}
return "";
}
}
public Boolean cityExists(
final String pCountryCode,
final String pStateCode,
final String pCityName) {
boolean result = false;
try {
connectToDatabase();
final Statement stmt = conn.createStatement();
final ResultSet rs = stmt
.executeQuery("SELECT COUNT(*) FROM cities WHERE countryCode='"
+ pCountryCode
+ "' AND stateCode='"
+ pStateCode
+ "' AND cityName='" + pCityName + "'");
rs.first();
result = rs.getInt(1) > 0;
stmt.close();
disconnectFromDatabase();
} catch (final Exception e) {
e.printStackTrace();
}
return new Boolean(result);
}
/**
* Establish a connection to the local database and set up a statement
*/
private void connectToDatabase()
throws Exception {
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Class.forName("com.mysql.jdbc.Driver").newInstance();
conn = DriverManager.getConnection(jdbc_url, mysql_user,
mysql_password);
}
/**
* Disconnect from the database, closing everything
*/
private void disconnectFromDatabase()
throws Exception {
conn.close();
}
public LinkedHashMap<String, ClientCityData> getCities(
final String pCountryCode,
final String pStateCode,
final int pFrom,
final int pQuantity) {
final LinkedHashMap<String, ClientCityData> citiesList = new LinkedHashMap<String, ClientCityData>();
try {
76
connectToDatabase();
final Statement stmt = conn.createStatement();
final ResultSet rs = stmt
.executeQuery("SELECT * FROM cities WHERE countryCode='"
+ pCountryCode + "' AND stateCode='" + pStateCode
+ "' ORDER BY cityName LIMIT " + pFrom + "," + pQuantity);
while (rs.next()) {
citiesList.put(rs.getString("cityName"), new ClientCityData(rs
.getString("countryCode"), rs.getString("stateCode"), rs
.getString("cityName"), rs.getString("cityAccentedName"),
rs.getInt("population"), rs.getFloat("latitude"), rs
.getFloat("longitude")));
}
stmt.close();
disconnectFromDatabase();
} catch (final Exception e) {
e.printStackTrace();
}
return citiesList;
}
public LinkedHashMap<String, ClientCityData> getCitiesStartingWith(
String pCountryCode,
String pStateCode,
String pStart) {
final LinkedHashMap<String, ClientCityData> citiesList = new LinkedHashMap<String, ClientCityData>();
try {
connectToDatabase();
final Statement stmt = conn.createStatement();
final ResultSet rs = stmt
.executeQuery("SELECT * FROM cities WHERE countryCode='"
+ pCountryCode + "' AND stateCode='" + pStateCode
+ "' AND cityName LIKE '" + pStart
+ "%' ORDER BY cityName");
while (rs.next()) {
citiesList.put(rs.getString("cityName"), new ClientCityData(rs
.getString("countryCode"), rs.getString("stateCode"), rs
.getString("cityName"), rs.getString("cityAccentedName"),
rs.getInt("population"), rs.getFloat("latitude"), rs
.getFloat("longitude")));
}
stmt.close();
disconnectFromDatabase();
} catch (final Exception e) {
e.printStackTrace();
}
return citiesList;
}
public LinkedHashMap<String, String> getCountries() {
final LinkedHashMap<String, String> countriesList = new LinkedHashMap<String, String>();
77
try {
connectToDatabase();
final Statement stmt = conn.createStatement();
final ResultSet rs = stmt
.executeQuery("SELECT countryCode,countryName "
+ "FROM countries ORDER BY 2");
while (rs.next()) {
countriesList.put(rs.getString(1), rs.getString(2));
}
stmt.close();
disconnectFromDatabase();
} catch (final Exception e) {
e.printStackTrace();
}
return countriesList;
}
public LinkedHashMap<String, String> getStates(
final String pCountryCode) {
final LinkedHashMap<String, String> statesList = new LinkedHashMap<String, String>();
try {
connectToDatabase();
final Statement stmt = conn.createStatement();
final ResultSet rs = stmt
.executeQuery("SELECT stateCode,stateName FROM states "
+ "WHERE countryCode='" + pCountryCode + "' ORDER BY 2");
while (rs.next()) {
statesList.put(rs.getString(1), rs.getString(2));
}
stmt.close();
disconnectFromDatabase();
} catch (final Exception e) {
e.printStackTrace();
}
return statesList;
}
}
Código 22 – WorldServiceImpl
Fonte: Kereki (2010).
3.9 MISTURANDO JAVASCRIPT E GWT
JavaScript é para o GWT o que assembler é para um compilador clássico como
linguagem C++, e misturar código JavaScript com código Java pode ser útil.
Muitas vezes, você vai precisar para integrar o GWT com JavaScript existentes
desenvolvidos em biblioteca de terceiros. Ocasionalmente pode ser necessária para acesso de
78
baixo nível a funcionalidade do navegador, não expostos pela classe GWT API. O JavaScript
Native Interface (JSNI) do GWT pode resolver ambos os problemas, permitindo-lhe integrar o
JavaScript diretamente em seu aplicativo de código-fonte Java.
O compilador GWT traduz-fonte Java em JavaScript. Às vezes é muito útil para
misturar manualmente JavaScript em seu código-fonte Java. Por exemplo, a funcionalidade de
nível mais baixo de certas classes core do GWT são escritas em JavaScript. GWT empresta do
Java Native Interface (JNI) o conceito para implementar o JavaScript Native Interface (JSNI).
Escrevendo métodos JSNI é uma técnica poderosa, mas deve ser usado com moderação, pois
escrever código JavaScript é visivelmente complicado. Código JSNI é potencialmente menos
portável entre os navegadores, diminui as chances de estouro de memória, e é mais difícil para
o compilador otimizar.
Pensamos JSNI como o equivalente web de código assembly inline, pode-se usá-lo
de muitas maneiras:

Implementar um método Java diretamente no JavaScript

Chamada de código JavaScript em código Java e vice-versa

Lançar exceções para além das fronteiras Java / JavaScript

Ler e escrever campos de Java a partir de JavaScript

Usar o modo de desenvolvimento para depurar a fonte Java (com um depurador Java)
e
JavaScript (com um depurador de script)
O Código 23, por exemplo, ilustra a função sayHello(name) escrita em JavaScript
declarada na página HTML que pode ser chamada de qualquer elemento dentro de um
módulo do GWT.
<html>
<head>
<script>
function sayHello(name) {
alert("Hello from JavaScript, " + name);
}
</script>
<-- Include the GWT module called "Spiffy" -->
<script src="org.example.yourcode.Spiffy.nocache.js">
</script>
</head>
...
Código 23 – Função JavaScript sayHello(name)
Fonte: Kereki (2010).
79
O Código 24 mostra no código fonte Java GWT, a chamada da função sayHello()
JavaScript através de JSNI.
// A Java method using JSNI
native void sayHelloInJava(String name) {
$wnd.sayHello(name); // $wnd is a JSNI synonym for 'window'
};
Código 24 – Função JavaScript sayHello(name)
Fonte: Kereki (2010).
Agora o contrário acessar uma função GWT no JavaScript. O Código 25 mostra a
listagem da função fornatAsCurrency escrita em linguagem Java no GWT.
package org.example.yourcode.format.client;
public class DateFormatterLib implements EntryPoint {
// Expose the following method into JavaScript.
private static String formatAsCurrency(double x) {
return NumberFormat.getCurrencyFormat().format(x);
}
// Set up the JS-callable signature as a global JS function.
private native void publish() {
$wnd.formatAsCurrency =
@org.example.yourcode.format.client.DateFormatterLib::formatAsCurrency(D);
};
// Auto-publish the method into JS when the GWT module loads.
public void onModuleLoad() {
publish();
}
}
Código 25 – Função formatAsCurrency
Fonte: Kereki (2010).
O Código 26 ilustra a página HTML acessando a função GWT criada.
<html>
<head>
<-- Include the GWT module that publishes the JS API -->
<script src="org.example.yourcode.FormatLib.nocache.js"></script>
<-- Write some JS that uses that GWT code -->
<script>
function doStuff() {
alert(formatAsCurrency(1530281));
}
</script>
</head>
...
Código 26 – Exemplo de função GWT acessada pelo HTML
Fonte: Kereki (2010).
80
Usando JSNI, pode-se misturar JavaScript, bibliotecas externas JavaScript, e código
Java livremente de qualquer maneira.
JSON (JavaScript Object Notation) é uma forma de intercâmbio de dados leve, uma
alternativa ao formato XML:

É fácil para os desenvolvedores Java a ler e escrever.

É fácil para as máquinas de analisar e gerar.

É composto por um subconjunto da linguagem de programação JavaScript.

JSON é um formato de texto, que é independente das linguagens de programação, mas usa
convenções que são familiares para os desenvolvedores de C, incluindo C ++, C#, Java,
JavaScript, Perl, Python, e outros. Estas propriedades tornam JSON uma linguagem de
troca de dados ideal.

GWT suporta este protocolo, GWT2 inclui várias classes e métodos para facilitar o
processamento JSON.
JSON é composto de uma coleção de pares nome / valor. Em várias linguagens, isto
é implementado como um objeto, dicionário, hash, tabela com chave primária, ou uma lista
ordenada de valores. Estas estruturas de dados são universais. Praticamente todas as
linguagens de programação modernas as usam de alguma forma. Faz sentido que um formato
de dados, que é intercambiável entre linguagens de programação também basear-se nestas
mesmas estruturas.
JSON é um conjunto desordenado de pares nome / valor. Um objeto que começa com
{(chave esquerda) e termina com } (chave direita). Cada nome é seguido por: (dois pontos) e
os pares nome / valor são separados por, (vírgula). Na Figura 32 é ilustrada a sintaxe do
JSON.
81
Figura 32 – Sintaxe do JSON
Fonte adaptado de INTRODUÇÃO... (2011).
O Código 27 ilustra um arquivo JSON gerado pelo serviço disponível na URL
<http://search.yahooapis.com/NewsSearchService/V1/newsSearch?appid=YahooDemo&quer
y=tablet&result=3 &language=en&output=json>, o Yahoo gera um arquivo no format JSON
com as informações de notícias sobre tablets.
{"ResultSet":{"totalResultsAvailable":"3253","totalResultsReturned":10,"firstResultPosition":"1","Result":[{"Ti
tle":"4Q Tablet Shipments Double From 3Q; Apple's Lead Declines - Researcher","Summary":"Worldwide
tablet computer shipments more than doubled sequentially in the fourth quarter, with Apple Inc.'s (AAPL) iPad
the declining market leader, researcher Strategy Analytics estimated
Monday.","Url":"http:\/\/www.foxbusiness.com\/markets\/2011\/01\/31\/q-tablet-shipments-double-q-appleslead-declines-researcher\/","ClickUrl":"http:\/\/www.foxbusiness.com\/markets\/2011\/01\/31\/q-tabletshipments-double-q-apples-lead-declines-researcher\/","NewsSource":"FOX
Business","NewsSourceUrl":"http:\/\/www.foxbusiness.com
... omitido parte da resposta ...
\/","Language":"en","PublishDate":"1296565231","ModificationDate":"1296565646"},{"Title":"5 Ways
Google's Honeycomb Tablet OS Could Beat Apple's Mighty iPad","Summary":"We offer five ways Google can
smoke the iPad on the feature front with its Honeycomb tablet-centric
OS","Url":"http:\/\/www.pcworld.com\/article\/218376\/5_Ways_Googles_Honeycomb_Tablet_Could_Beat_Ap
ple_s_Mighty_iPad.html?tk=rss_news","ClickUrl":"http:\/\/www.pcworld.com\/article\/218376\/5_Ways_Googl
es_Honeycomb_Tablet_Could_Beat_Apple_s_Mighty_iPad.html?tk=rss_news","NewsSource":"PC
World","NewsSourceUrl":"http:\/\/www.pcworld.com\/","Language":"en","PublishDate":"1296581452","Modifi
cationDate":"1296581454"}]}}
Código 27 – Exemplo de um arquivo no formato JSON
Fonte: Autoria própria.
O servidor de notícias gerou um ResultSet com três atributos (totalResultsAvailable,
totalResultsReturned e firstResultPosition) e um outro atributo (Result) que é um array de
82
objetos, cada elemento do array representando uma notícia incluinto o título, resumo, url,
fonte da notícia e linguagem entre outros.
Processando este arquivo JSON em uma página HTML adequadamente, é gerada
uma página como a ilustrada na Figura 33.
Figura 33 – Arquivo JSON processado, com outros widgets acrescentados
Fonte: Autoria própria.
Os serviços para troca de dados entre aplicações via protocolo http já alcançaram bom
nível de maturidade. Hoje, há várias formas de disponibilizar serviços via web, e existem diversas
APIs disponíveis para atender as necessidades como mapas, agenda, autenticação de usuários, ou
integração com redes sociais. Serviços pagos, públicos, serviços com mais de um plano de
licenciamento para atender aos vários tipos de consumidor, hoje já estão prontos para uso.
Em meio às tecnologias para intercambio de dados e comunicação entre aplicativos
pela web como SOAP, REST, ou WSDL, se destacam as APIs que fornecem dados com
simples requisições http diretamente via navegador internet como o JSONP.
AJAX trata as requisições assíncronas remotas por meio dos protocolos
XMLHttpRequest e XMLHttpResponse, que trafegam dados na forma de texto puro ou
83
arquivos XML. Esses dados são processados pelo programa javascript, que monta no browser
cliente seus trechos de html sem o recarregamento da página, o JSONP requisita dados de
forma assíncrona, assim como o AJAX, mas não utiliza os protocolo XMLHttp e só trabalha
com objetos no formato JSON.
JSON é um formato de dados que vem sendo utilizado para transporte de dados entre
aplicações web. Ele está ganhando seu espaço por ser leve e de fácil implementação. O
processamento dos dados em um objeto JSON requer um parse simples (usando o método eval do
javascript) e não é necessário a navegação por DOM entre os nós e atributos de um XML, isto
justifica a preferência pelo JSON ao invés de XML para ajax na web (INTRODUÇÃO, 2011).
Há uma limitação no uso do protocolo XMLHttpRequest em se tratando de
requisições entre diferentes sites (requisições crossdomain), este é modelo de segurança,
implementado pelo javascript, chamdo Same Origin Policy, ou Política de Mesma Origem.
Este modelo de segurança crossdomain impede que um documento leia ou envie dados para
outra origem. Origens diferentes são objetos que estejam em diferentes domínios, diferentes
portas ou que utilizem protocolos de comunicação diferentes entre si. Considerando a url:
―http://www.dcvillea.appspot.com/‖, podemos ter requisições que irão ter sucesso ou falhar
nas seguintes situações:

http://www.dcvillea.appspot.com/diretorio/pagina.html,
funciona,
porque
é
uma
requisição para o mesmo host, usa o mesmo protocolo, e está dentro do mesmo site.

https://www.dcvillea.appspot.com/pagina.html, não funciona, porque os protocolos são
diferentes representam (―http‖,‖https‖);

http://www.dcvillea.appspot.com:81/pagina.html não funciona, porque as portas são
diferentes (―porta 81 e a padrão 80‖);

http://www.google.com/pagina.html, também não funciona, porque se tratam de hosts
diferentes;
JSONP é um pseudo-protocolo que possibilita realizar requisições http e trafegar
dados no formato JSON entre documentos de diversas origens. A implementação do JSONP é
simples, porém é necessário que o serviço responsável pela entrega dos dados tenha a escolha
de entregá-los na estrutura necessária para que eles possam ser processados no cliente. Não há
restrições para o transporte de imagens e scripts de outras origens, por meio do atributo src
das tags. A técnica implementada no JSONP se aproveita dessa possibilidade para carregar
scripts externos conforme a necessidade, manipulando o DOM da página. O que o JSONP faz
84
para funcionar é a inclusão de uma TAG script no header <head> da página HTML. Essa tag
script recebe um atributo src indicando o site externo, que responde pelos objetos no formato
JSON, esse resultado é parseado e fica disponível para processamento via JavaScript. Padding
ou prefix é o nome passado na requisição ao serviço, para que na resposta o método envolva
as informações no formato JSON após a resposta (INTRODUÇÃO..., 2011).
<head>
<script type="text/javascript" src="http://domain1.com/getjson?jsonp=parseResponse" target="_blank">
</script>
…
Código 28 – Exemplo de requisição feita a um servidor JSONP
Fonte: INTRODUÇÃO... (2011).
A palavra parseResponse será a o nome da função que gerará o json, como um
callback. O resultado será algo parecido com Código 28:
parseResponse({―name‖:‖dvillela‖, ‖idade‖:45, esportes:[―corrida‖,‖tenis‖,‖natacao‖]})
Código 29 – Resultado do parseResponse
Fonte: INTRODUÇÃO... (2011).
3.10 ADICIONANDO API
Há muitas bibliotecas JavaScript e serviços web que podem ser incluídos em
aplicações, adicionando-as atravez de JSNI, assim como códigos GWT (que após compilados
são JavaScrits).
Na Figura 34, por exemplo, um dos requisitos da aplicação no estudo de caso será
informar ao usuário onde fica a UTFPR campus Cornélio Procópio e como chegar ao local. A
Google disponibiliza a API para este serviço, bastando fazer a devida chamada ao serviço.
85
Figura 34 – UTFPR no Google Maps
Fonte: Autoria própria.
O Código 30 lista o JavaScript para acessar o serviço Google Maps passando os
parâmetros de latitude e longitude da UTFPR campus Cornélio Procópio, neste caso o mapa
ficará confinado em um frame com 300 X 279 pixel.
<!-- Google Maps Element Code - UTFPR -->
<iframe frameborder=0 marginwidth=0 marginheight=0 border=0 style="border: 0; margin: 0; width: 300px;
height: 279px;"src="http://www.google.com/uds/modules/elements/ mapselement/iframe.html
? maptype=terrain
&latlng=-23.186483809925903%2C-50.657057762145996
&mlatlng=-23.18587%2C-50.655609
&maddress1= Avenida%20Alberto%20Carazzai%2C%201640%20%20Centro&maddress2=Corn%C3%A9lio%20Proc%C3%B3pio%20-%20PR%2C%2086300000%2C%20Brazil
&zoom=15
&mtitle=UTFPR-Universidade%20Tecnol%C3%B3gica%20Federal%20do%20Paran%C3%A1%20
Campus%20Corn%C3%A9lio%20Proc%C3%B3pio&element=true"
scrolling="no" allowtransparency="true">
</iframe>
Código 30 – Código JavaScript para acessar o serviço Google Maps
Fonte: Autoria própria.
86
Outro exemplo é mostrado na Figura 35, onde será desenvolvido uma aplicação
GTW que simulará a cotação de ações.
Figura 35 – Cotação de ações no <div id=‖stokList‖>
Fonte: Autoria própria.
<html>
<head>
<title>Domingos de Carvalho Villela Júnior - Tecnologia Java - UTFPR</title>
<!—Chamada da aplicação GWT cotacaoacoes -->
<script type="text/javascript" language="javascript"
src="cotacaoacoes/cotacaoacoes.nocache.js"></script>
</head>
<body>
…
<div id="stockList"></div>
…
</body>
Código 31 – Código JavaScript para acessar o serviço catacaoacoes
Fonte: Autoria própria.
Com estes recursos e conceitos, o estudo de caso implantará no Google Application
Engine, uma pequena aplicação demonstrando como se pode desenvolver um ERP RIA com o
GWT 2.
87
4 ESTUDO DE CASO
Este estudo de caso foi desenvolvido utilizando-se do conceito de Mashup. Mashup é
uma técnica utilizada em desenvolvimento Web onde uma aplicação usa e combinam dados e
serviços de duas ou mais fontes para criar um novo serviço. Este novo serviço tem como
requisitos funcionais uma página Web em que um usuário de tablet tenha disponível na
nuvem os seguintes serviços:

Cotação on-line de ações na Bovespa.

Notícias da Bloomberg

Notícias da Petrobras

Calendário e agenda

Mapas

E-mail

Editor de textos

Planilha eletrônica

Software para apresentações de slides

Software para desenho

Tradutor entre várias línguas

Teclado virtual
O diagrama de classes do projeto feito em UML para atender o requisito de cotação
on-line de ações na Bovespa é mostrado na Figura 36. Este requisito funcional foi
implementado com o uso do GWT, simulando valores aleatórios para as ações escolhidas pelo
usuário de segundo em segundo, e os demais serviços foram consumidos da Google.
Este diagrama de classes mostra as classes do ―google.gwt.user.client.ui― utilizadas,
e a classe CotacaoAcoes. Estes componentes gráficos serão injetados no código HTML
através de JavaScript em <div id="stockAdd"></div> e <div id="stockList"></div>. No
Apêndice A e B estão as listagens destes códigos e em destaque esta injeção dos dois
VertivalPanel com seus componentes visuais na tag <div/> no HTML da aplicação.
Depois de testada a aplicação ela foi hospedada no Google App Engine, onde pode
ser acessada pela url: < http://www.tccposjavautfpr.appspot.com/ >, a Figura 37 mostra a
aplicação sendo acessada pelo navegador Google Chrome.
88
Figura 36 – Diagrama de classes do projeto simulação de cotação de ações
Fonte: Autoria própria.
Figura 37 – Estudo de caso implantado no app engine
Fonte: Autoria própria.
89
5 CONCLUSÃO
No Quadro 6 estão algumas manchetes relacionadas à computação em nuvens em
sites especializados em TI.
Data
Manchete
Fonte
16/04/2010
Windows Azure é Lançado no Brasil
Microsoft
25/03/2011
Sonda IT se une à VCE para explorar mercado de cloud no país.
Computer World
29/03/2011
Cisco compra empresa de software para cloud computing
TI inside
29/03/2011
Mercado de cloud computing deve crescer 60% ao ano no país.
TI inside
29/03/2011
IBM reforça estratégia de outsoursing
Segundo a organização, o modelo poderá ainda estabelecer bases para o
desenvolvimento de soluções avançadas de cloud computing.
Computer World
31/03/2011
HP aposta em cloud computing para impulsionar crescimento no Brasil
HP Brasil
Mar./Abr.
2011
Plug into the cloud
Artigo relatando cases de uso da solução de cloud da Oracle
Oracle Magazine
04/04/2011
O cloud computing chaga aos bancos
TI inside
04/04/2011
IEEE procura interoperacionalidade no cloud computing
Computer World
05/04/2011
Conferência Gartner Data Center destaca ―Cloud‖ como alternativa para
infraestrutura de TI
Gartner Research
06/04/2011
Cloud deve crescer 7 vezes até 2014, diz IDC
INFO On-line
06/04/2011
Operadoras estão apenas no início dos serviços em cloud
Teletime
08/04/2011
Dell investe milhões de dólares para abrir 10 centros de armazenamento de dados.
―O investimento será feito para expandir o apoio ao cliente e melhorar a aposta no
cloud computing‖
Negócios on-line
12/04/2011
Unisys lança guia para projetos cloud
Unisys
Corporation
15/04/2011
Dell pretende investir US$ 1 bi. Foco é Cloud Computing
itWeb
16/05/2011
Google apresenta o Chromebook versão radical do conceito de netbook
Jornal O Estado de
S. Paulo
15/06/2011
Vida digial - A nuvem é de tijolos - iCloud
Revista VEJA,
edição 2221
Quadro 6 – Manchetes sobre computação em nuvens
Fonte: Adaptado de Ramos (2011).
Pelas manchetes mostradas no Quadro 6, conclui-se que a computação em nuvem
com a venda de serviços sob demanda já é uma realidade, todas as grandes empresas de TI
estão correndo atrás deste mercado, e os profissionais de desenvolvimento de software
também devem se adaptar a este paradigma. Este trabalho foi feito no momento em que está
ocorrendo esta transição, e espera ter contribuído para explorar esta possibilidade de
desenvolvimento em cloud com as ferramentas da Google, que foi junto com a Amazon uma
das primeiras empresas a investir neste conceito.
90
A Google está na frente de seus concorrentes, pois começou a investir em cloud
computing a anos atrás, hoje com conta com Chrome OS, Android 3.0, Google Web Toolkit
2.1, Google App Engine, e seus data centers em terra e em alto mar. Tem mostrado que é uma
empresa confiável e que seus clientes podem entregar os dados e serviços de processamento
de aos seus cuidados. Na Figura 38 é mostrado um tablet da Motorola com Android 3.0, um
Chromebook com Chrome OS e um smartfone da Motorola com Android todos prontos para
operarem em computação em nuvens como propõe este trabalho.
Figura 38 – Equipamentos com software Android e Chrome OS
Fonte: Autoria própria.
Na Figura 39 são mostrados os prós e contras a tecnologia de computação em nuvem
mais comum na literatura, e a projeção de seu crescimento:

Prós: alta escalabilidade e baixo custo, muitas opções de escolha e agilidade, mudanças e
gerenciamento transparentes, estar em cloud e sempre estar sob arquitetura de última
geração.

Contras: menor segurança, menor nível de controle, menor confiabilidade, e imposição
tecnológica (de API, por exemplo).
91
Figura 39 – Prós, contras e crescimento da computação em nuvens
Fonte: Adaptado de Vela (2011).
Com o atual preço dos servidores, custos da conta de TI que uma empresa possui
como manutenção do hardware, banco de dados, redes, técnicos especializados em TI,
problemas de disponibilidade 24 x 7, segurança, resfriamento dos equipamentos de
processamento de dados, backup´s e no-breaks, o desenvolvimento em cloud é uma opção que
deve ser levada em consideração. Além do valor para uma hospedagem em cloud completa
ser baixo, possuir um banco de dados escalado e funcionando juntamente com a aplicação no
modelo 24 x 7, mostra que desenvolver em cloud é a nova forma de desenvolver software e
que ganha espaço a todo o tempo. Futuramente estará aos redores de todo o mercado de
trabalho e de todas as linguagens de programação, a nuvem está em formação há anos e já
mostrou ser a inovação que vai definir o mundo digital nesta década. Finalmente, a Figura 39
mostra a projeção de crescimento da computação em nuvem e que o maior crescimento
ocorrerá nos padrões para desenvolvimento de software que será ditado pelas empresas que
dominarem esta tecnologia, área que abrirá novos caminhos para futuras pesquisas.
92
REFERENCIAS
BILLING and Budgeting Resources. Disponível em: <http://code.google.com/appengine/
docs/billing.html>. Acesso em: 20 jan. 2011.
BORGES, Alexander. JSONP e o “Ajax Crossdomain”. 14 abr. 2010. Disponível em:
<http://afronteirafinal.com/jsonp-e-o-ajax-crossdomain/>. Acesso em: 01 fev. 2011.
CAMILO, Lucio. Introdução ao MVP. Jornal Java, 12 dez. 2010. Disponível em:
<http://www.jornaljava.com/2010/12/introducao-ao-mvp >. Acesso em: 26 jan. 2011.
CARR, Nicholas. Adoção da nuvem depende de segurança, diz Carr. Disponível em:
<http://info.abril.com.br/noticias/corporate/adocao-da-nuvem-depende-de-seguranca-diz-carr01122010-6.shl>. Acesso em: 02 dez. 2010.
CHONG, Frederick; CARRARO, Gianpaolo. Architecture Strategies for Catching the Long
Tail. Microsoft Corporation. abr. 2006. Disponível em:<http://msdn.microsoft.com/enus/library/aa479069.aspx>. Acesso em: 13 jan. 2011.
DATA NUCLEUS. Disponível em:<http://www.datanucleus.org/>. Acesso em: 18 jan. 2011.
DATE Picker. Disponível em: <http://gwt.google.com/samples/Showcase/Showcase.html#!
CwDatePicker>. Acesso em: 20 jan. 2011.
DEVELOPER´S Guide. Disponível em: <http://code.google.com/webtoolkit/doc/latest/Dev
Guide.html>. Acesso em: 20 jan. 2011.
FOSTER, Ian et al. Cloud Computing and Grid Computing 360-Degree Compared. Chicago:
Department of Computer Science, University of Chicago, 2008.
GOOGLE App Engine. Disponível em: <http://code.google.com/appengine/>. Acesso em: 06
dez. 2010.
GOOGLE Data Center revelado ao mundo. 09 abril 2009. Disponível em <http://tek.online.pt/
google-data-center-revelado-ao-mundo/>. Acesso em: 19 jan. 2011.
GOOGLE I/O 2009 – Best Practices for Architeting GWT App. Google Developers, 01 jun.
2009. Disponível em: <http://www.youtube.com/watch?v=PDuhR18-EdM>. Acesso em: 20
jan. 2011.
GOOGLE trends. Disponível em: <http://www.google.com/trends>. Acesso em: 05 jun. 2011.
GOOGLE Web Tool Kit. Disponível em: <http://code.google.com/intl/pt-BR/webtoolkit/>.
Acesso em: 24 jan. 2011.
93
GOOGLE´S Periodic Table of APIs. 27 jan. 2011. Disponível em:
<http://www.browsermedia.co.uk/2011/01/27/googles-periodic-table-of-apis/>. Acesso em:
27 jan. 2011.
HODGSON, Matthew. Beyond Web 2.0. 07 mar. 2008. Disponível em:
<http://www.theappgap.com/beyond-web-20.html>. Acesso em: 19 jan. 2001.
HTML/Dhtml/Xhtml. Disponível em: <http://www.miguel.ms/tecnologias/web/
htmldhtmlxhtml>. Acesso em: 20 jan. 2011.
iGOOGLE. Disponível em: <http://www.google.com/ig>. Acesso em: 06 jun. 2011.
INTRODUÇÃO ao JSON. Disponível em <http://www.json.org/>. Acesso em: 31 jan. 2011.
JAVA Data Objects. About Apache JDO. Disponível em: <http://db.apache.org/jdo/>. Acesso
em: 18 jan. 2011.
KEREKI, Federico. Essential GWT Building for the Web with Google Web Toolkit 2.
Boston: Addison Wesley, 2010.
KOCH, Peter-Paul. The Document Object Model: an Introduction. 14 maio 2001.
Disponível em: <http://www.digital-web.com/articles/the_document_object_model/>. Acesso
em: 18 jan. 2011.
LAST Call: W3C Invites Broad Review of HTML5 and Five Related Specifications. 25 maio
2011. Disponível em: <http://www.w3.org/>. Acesso em: 28 maio 2011.
LIMA, Fernando Cesar. Tópicos Avançados em Tecnologia Java – AJAX. Cornélio
Procópio: UTFPR, 2010. (apostila).
MILLER, Rich. Lonestar 4 Supercomputer Will Boost Research. 20 abr. 2011. Disponível
em: <http://www.datacenterknowledge.com/archives/2011/04/20/lonestar-4-supercomputerwill-boost-research/>. Acesso em: 07 jun. 2011.
MIRANDA, Fábio. Novidades no GWT 2.1! Novos Widgets e o Framework MVP Oficial da
Google. Revista MundoJ, ed. 45, p. 14-24, jan. 2011.
MOREIRA, Denis F. Entenda o que é Web 2.0. 19 nov. 2009. Disponível em:
<http://fontededados.com/entenda-web-2-0/>. Acesso em: 18 jan. 2011.
MÜLLER, Nicolas. O que é cloaking SEO? Disponível em: <http://www.oficinadanet.com.br/
artigo/otimizacao__seo/o-que-e-cloaking-seo>. Acesso em: 13 jan. 2011.
MÜLLER, Victor. Desenvolvimento de aplicações sob o paradigma da computação em
nuvem com ferramentas Google. Florianópolis: UFSC, 2010.
94
PEREIRA, Felipe Alves Lourenço. Serialização e Desserialização de Objetos em Java. 19
dez. 2010. Disponível em: <http://felipealvesgnu.wordpress.com/2010/12/19/serializacao-edesserializacao-de-objetos/>. Acesso em: 20 jan. 2011.
PORTAL GWT. Disponível em: <http://portalgwt.com/>. Acesso em: 07 mar. 2011.
RAMOS, José Yoshiriro Ajisaka. Cloud Computing. Revista MundoJ, Ed. 47, p. 6-11, jun.
2011.
RMI-IIPO. Disponível em: <http://help.sap.com/saphelp_nw04/helpdata/en/97/71c
99065089b4c9542e0b105f1fcce/content.htm>. Acesso em: 20 jan. 2011.
RUN your web application on Googles´s infraestruture. Disponívle em:
<https://www.google.com/accounts/ServiceLogin?service=ah&passive=true&continue=https:
//appengine.google.com/_ah/conflogin%3Fcontinue%3Dhttps://appengine.google.com/&ltmp
l=ae>. Acesso em: 20 jan. 2011.
SCHULLER, Sinclair. Demystifying The Cloud: Where Do SaaS, PaaS and Other
Acronyms Fit In? 01 dez. 2008. Disponível em: <http://www.saasblogs.com/2008/12/01/
demystifying-the-cloud-where-do-saas-paas-and-other-acronyms-fit-in/>. Acesso em: 13 jan.
2011.
SMART GWT Enterprise Edition. Disponível em: <http://www.smartclient.com/product/
sgwtOverview.jsp>. Acesso em: 20 jan. 2011.
USO do armazenamento de dados com JDO. Disponível em <http://code.google.com/intl/ptBR/appengine/docs/java/gettingstarted/usingdatastore.html>. Acesso em: 18 jan. 2011.
VELA, Lorie. Are companies concerned about cloud computing security? 20 jan. 2011.
Disponível em <http://www.collaborationideas.com/2011/01/are-companies-managingproperly-cloud-computing-security/#more-1365>. Acesso em: 29 maio. 2011.
WEISER, Mark. Ubiquitous Computing. 17 mar. 1996. Disponível em:
<http://sandbox.xerox.com/hypertext/weiser/UbiHome.html>. Acesso em: 18 jan. 2011.
WHAT is Cloud Computing? University of Southampton. Disponível em:
<http://tecires.ecs.soton.ac.uk/cloud_computing.php>. Acesso em: 06 jun. 2011.
WIDGET Gallery. Disponível em: <http://code.google.com/webtoolkit/doc/1.6/RefWidget
Gallery.html>. Acesso em: 20 jan. 2011.
95
APÊNDICES
96
APÊNDICE A – class CotacaoAcoes
package com.dvillela.gwt.cotacaoacoes.client;
import java.util.ArrayList;
import java.util.Date;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
com.google.gwt.core.client.EntryPoint;
com.google.gwt.event.dom.client.ClickEvent;
com.google.gwt.event.dom.client.ClickHandler;
com.google.gwt.event.dom.client.KeyCodes;
com.google.gwt.event.dom.client.KeyPressEvent;
com.google.gwt.event.dom.client.KeyPressHandler;
com.google.gwt.i18n.client.DateTimeFormat;
com.google.gwt.i18n.client.NumberFormat;
com.google.gwt.user.client.Random;
com.google.gwt.user.client.Timer;
com.google.gwt.user.client.Window;
com.google.gwt.user.client.ui.Button;
com.google.gwt.user.client.ui.FlexTable;
com.google.gwt.user.client.ui.HorizontalPanel;
com.google.gwt.user.client.ui.Label;
com.google.gwt.user.client.ui.RootPanel;
com.google.gwt.user.client.ui.TextBox;
com.google.gwt.user.client.ui.VerticalPanel;
public class CotacaoAcoes implements EntryPoint {
private
private
private
private
private
private
private
private
private
static final int REFRESH_INTERVAL = 5000;
VerticalPanel mainPanel = new VerticalPanel();
VerticalPanel mainPanelAdd = new VerticalPanel();
FlexTable stocksFlexTable = new FlexTable();
HorizontalPanel addPanel = new HorizontalPanel();
TextBox newSymbolTextBox = new TextBox();
Button addStockButton = new Button("Adicionar");
Label lastUpdatedLabel = new Label();
ArrayList<String> stocks = new ArrayList<String>();
/**
* Entry point method.
*/
public void onModuleLoad() {
// Create table for stock data.
stocksFlexTable.setText(0, 0, "C\u00f3digo");
stocksFlexTable.setText(0, 1, "Pre\u00e7o");
stocksFlexTable.setText(0, 2, "Varia\u00e7\u00e3o");
stocksFlexTable.setText(0, 3, "Remove");
// Add styles to elements in the stock list table.
stocksFlexTable.setCellPadding(6);
stocksFlexTable.getRowFormatter().addStyleName(0, "watchListHeader");
stocksFlexTable.addStyleName("watchList");
stocksFlexTable.getCellFormatter().addStyleName(0, 1,
"watchListNumericColumn");
stocksFlexTable.getCellFormatter().addStyleName(0, 2,
"watchListNumericColumn");
stocksFlexTable.getCellFormatter().addStyleName(0, 3,
"watchListRemoveColumn");
// Assemble Add Stock panel.
addPanel.add(newSymbolTextBox);
addPanel.add(addStockButton);
addPanel.addStyleName("addPanel");
// Assemble Main panel.
mainPanel.add(stocksFlexTable);
mainPanelAdd.add(addPanel);
mainPanel.add(lastUpdatedLabel);
// Associate the Main panel with the HTML host page.
RootPanel.get("stockList").add(mainPanel);
RootPanel.get("stockAdd").add(mainPanelAdd);
97
// Move cursor focus to the input box.
newSymbolTextBox.setFocus(true);
// Listen for mouse events on the Add button.
addStockButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
addStock();
}
});
// Listen for keyboard events in the input box.
newSymbolTextBox.addKeyPressHandler(new KeyPressHandler() {
public void onKeyPress(KeyPressEvent event) {
if (event.getCharCode() == KeyCodes.KEY_ENTER) {
addStock();
}
}
});
// Setup timer to refresh list automatically.
Timer refreshTimer = new Timer() {
@Override
public void run() {
refreshWatchList();
}
};
refreshTimer.scheduleRepeating(REFRESH_INTERVAL);
}
/**
* Add stock to FlexTable. Executed when the user clicks the addStockButton
* or presses enter in the newSymbolTextBox.
*/
private void addStock() {
// TODO Auto-generated method stub
final String symbol = newSymbolTextBox.getText().toUpperCase().trim();
newSymbolTextBox.setFocus(true);
// Stock code must be between 1 and 10 chars that are numbers, letters,
// or dots.
if (!symbol.matches("^[0-9A-Z\\.]{1,10}$")) {
Window.alert("'" + symbol + "' is not a valid symbol.");
newSymbolTextBox.selectAll();
return;
}
newSymbolTextBox.setText("");
// TODO Don't add the stock if it's already in the table.
if (stocks.contains(symbol))
return;
// TODO Add the stock to the table.
int row = stocksFlexTable.getRowCount();
stocks.add(symbol);
stocksFlexTable.setText(row, 0, symbol);
stocksFlexTable.setWidget(row, 2, new Label());
stocksFlexTable.getCellFormatter().addStyleName(row, 1,
"watchListNumericColumn");
stocksFlexTable.getCellFormatter().addStyleName(row, 2,
"watchListNumericColumn");
stocksFlexTable.getCellFormatter().addStyleName(row, 3,
"watchListRemoveColumn");
// TODO Add a button to remove this stock from the table.
Button removeStockButton = new Button("remove");
removeStockButton.addStyleDependentName("remove");
removeStockButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
int removedIndex = stocks.indexOf(symbol);
stocks.remove(removedIndex);
stocksFlexTable.removeRow(removedIndex + 1);
}
});
stocksFlexTable.setWidget(row, 3, removeStockButton);
98
// Get the stock price.
refreshWatchList();
// TODO Get the stock price.
}
/**
* Generate random stock prices.
*/
private void refreshWatchList() {
final double MAX_PRICE = 100.0; // $100.00
final double MAX_PRICE_CHANGE = 0.02; // +/- 2%
StockPrice[] prices = new StockPrice[stocks.size()];
for (int i = 0; i < stocks.size(); i++) {
double price = Random.nextDouble() * MAX_PRICE;
double change = price * MAX_PRICE_CHANGE
* (Random.nextDouble() * 2.0 - 1.0);
prices[i] = new StockPrice(stocks.get(i), price, change);
}
updateTable(prices);
}
/**
* Update the Price and Change fields all the rows in the stock table.
*
* @param prices
*
Stock data for all rows.
*/
@SuppressWarnings("deprecation")
private void updateTable(StockPrice[] prices) {
for (int i = 0; i < prices.length; i++) {
updateTable(prices[i]);
}
// Display timestamp showing last refresh.
lastUpdatedLabel.setText("\u00daltima atualiza\u00e7\u00e3o : "
+ DateTimeFormat.getMediumDateTimeFormat().format(new Date()));
}
/**
* Update a single row in the stock table.
*
* @param price
*
Stock data for a single row.
*/
private void updateTable(StockPrice price) {
// Make sure the stock is still in the stock table.
if (!stocks.contains(price.getSymbol())) {
return;
}
int row = stocks.indexOf(price.getSymbol()) + 1;
// Format the data in the Price and Change fields.
String priceText = NumberFormat.getFormat("#,##0.00").format(
price.getPrice());
NumberFormat changeFormat = NumberFormat
.getFormat("+#,##0.00;-#,##0.00");
String changeText = changeFormat.format(price.getChange());
String changePercentText = changeFormat
.format(price.getChangePercent());
// Populate the Price and Change fields with new data.
stocksFlexTable.setText(row, 1, priceText);
Label changeWidget = (Label) stocksFlexTable.getWidget(row, 2);
changeWidget.setText(changeText + " (" + changePercentText + "%)");
// Change the color of text in the Change field based on its value.
String changeStyleName = "noChange";
if (price.getChangePercent() < -0.1f) {
changeStyleName = "negativeChange";
99
} else if (price.getChangePercent() > 0.1f) {
changeStyleName = "positiveChange";
}
changeWidget.setStyleName(changeStyleName);
}
}
100
APÊNDICE B – Página CotacaoAcoes.html
<!-- ---------------------------------------------------- -->
<!-- Desenvolvido por Domingos de Carvalho Villela Júnior -->
<!-Google Web ToolKit e Google Application Engine
-->
<!-Assis - SP - Brazil - Janeiro/2011
-->
<!-Estudo de caso, monografia Pós Java - UTFPR
-->
<!-Contato: [email protected]
-->
<!-- ---------------------------------------------------- -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<link type="text/css" rel="stylesheet" href="CotacaoAcoes.css">
<title>Domingos de Carvalho Villela Júnior - Tecnologia Java UTFPR</title>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("elements", "1", {
packages : "keyboard"
});
var kbd;
function onLoad() {
kbd = new google.elements.keyboard.Keyboard(
[ google.elements.keyboard.LayoutCode.PORTUGUESE ]);
}
google.setOnLoadCallback(onLoad);
</script>
<script type="text/javascript" language="javascript"
src="cotacaoacoes/cotacaoacoes.nocache.js"></script>
</head>
<body style="background-image: url(images/Fundo.gif);">
<!-- RECOMMENDED if your web app will not function without JavaScript enabled -->
<noscript>
<div
style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; border: 1px
solid red; padding: 4px; font-family: sans-serif">
Your web browser must have JavaScript enabled in order for this
application to display correctly.</div>
</noscript>
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1'
style="position: absolute; width: 0; height: 0; border: 0"></iframe>
<table border="0" bordercolor="000000" width="1230" align="center"
bgcolor="#FFFFFF">
<tr>
<td bordercolor="FFFFFF">
<table border="2" bordercolor="#2062B8" width="100%" align="center">
<tr align="center">
<td bordercolor="#FFFFFF" align="left" width="20%"><a
href="http://code.google.com/intl/ptBR/webtoolkit/overview.html">
<img alt="Projeto GWT 2.1" src="images/TecnoProjWeb.jpg"
width="260"
border="0"></a></td>
<td bordercolor="#2062B8" bgcolor="#B4CDCD"><font
face="Times New Roman" size="+4"
color="#000000">Computação
em Nuvem:</font><br>
<font face="Times New Roman" size="+1" color="#000000">
Desenvolvimento de Aplicações Empresariais Ricas na Internet, na
Arquitetura Java,<br>
101
Google Web Toolkit e Google Application Engine.</font>
<hr width=80% " size="2" noshade color="#2062B8" />
<font face="Times New Roman" size="+1" color="#000000">Estudo
de caso - UTFPR / Cornélio Procópio - 2011<br>
<a href="docs/MonografiaGWT.pdf"> Monografia apresentada no
curso de Especialização em Tecnologia Java</a><br>
<a href="mailto:[email protected]">Domingos de Carvalho
Villela Júnior</a></font></td>
</tr>
</table>
<table border="1" bordercolor="#2062B8" width="100%" align="center">
<tr>
<td align="left" bordercolor="FFFFFF" width="20%"><a
href="http://www.bmfbovespa.com.br/home.aspx?idioma=ptbr"><img
alt="Bovespa" src="images/bmf.jpg" width="360"
border="0"></a></td>
<td bgcolor="#E8E8E8" bordercolor="000000" align="center"
width="35%"><font face="Times New Roman" size="+3"
color="#000000">Cotação de Ações</font><br>
<font face="Times New Roman" size="+1" color="#000000">Entre
com o código das ações para simulação:</font>
<div id="stockAdd"></div>
<script
src="http://www.gmodules.com/ig/ifr?url=http://hosting.gmodules.com/ig/gadgets/file/
115450510581205387922/LaunchGoogleService1.xml&synd=open&w=340&h=65&title=&amp
;border=%23ffffff%7C0px%2C1px+solid+%2382CAFA%7C0px%2C2px+solid+%23BDEDFF%7C0px%2C3px+solid+%2
3E0FFFF&output=js"></script></td>
<td align="right" bordercolor="#2062B8" bgcolor="#E8E8E8">
<div id="stockList"></div>
</td>
</tr>
</table>
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1'
style="position: absolute; width: 0; height: 0; border: 0"></iframe>
<table border="2" bordercolor="#2062B8" width="100%" align="center">
<tr align="center">
<td bordercolor="000000" bgcolor="#B4CDCD"><iframe
frameborder=0 marginwidth=0 marginheight=0 border=0
style="border: 0; margin: 0; width: 300px; height:
300px;"
src="http://www.google.com/calendar/embed?showTitle=0&showTabs=0&showPrint=0&showCal
endars=0&wkst=1&element=true&src=usa__en%40holiday.calendar.google.com"
scrolling="no" allowtransparency="true"></iframe></td>
<td bordercolor="000000" bgcolor="#B4CDCD"><b>Notícias
Bloomberg</b><IFRAME
style="BORDER-RIGHT-WIDTH: 0px; MARGIN: 0px; WIDTH:
300px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; HEIGHT: 254px; BORDER-LEFT-WIDTH: 0px"
id=youtube_news_element_preview marginHeight=0 border=0
src="http://www.google.com/uds/modules/elements/videonews/iframe.html?channel=Bloomb
erg"
frameBorder=0 allowTransparency marginWidth=0
scrolling=no></IFRAME>
Busca on-line assincrona</td>
<td bordercolor="000000" bgcolor="#B4CDCD"><b>Negócios e
Petrobras</b> <iframe frameborder=0 marginwidth=0 marginheight=0
border=0 style="border: 0; margin: 0; width: 300px;
height: 258px;"
src="http://www.google.com/uds/modules/elements/newsshow/iframe.html?rsz=large&forma
t=300x250&ned=pt-BR_br&topic=b&q=petrobras&element=true"
scrolling="no" allowtransparency="true"></iframe> Busca
on-line
assincrona</td>
<td bordercolor="000000" bgcolor="#B4CDCD"><b>UTFPR/Cornélio
Procópio - Brasil</b><br>
<!-- Google Maps Element Code - UTFPR --> <iframe frameborder=0
marginwidth=0 marginheight=0 border=0
style="border: 0; margin: 0; width: 300px; height:
279px;"
102
src="http://www.google.com/uds/modules/elements/mapselement/iframe.html?maptype=terrain&latlng
=-23.186483809925903%2C-50.657057762145996&mlatlng=-23.18587%2C50.655609&maddress1=Avenida%20Alberto%20Carazzai%2C%201640%20%20Centro&maddress2=Corn%C3%A9lio%20Proc%C3%B3pio%20-%20PR%2C%2086300000%2C%20Brazil&zoom=15&mtitle=UTFPRUniversidade%20Tecnol%C3%B3gica%20Federal%20do%20Paran%C3%A1%20Campus%20Corn%C3%A9lio%20Proc%C
3%B3pio&element=true"
scrolling="no" allowtransparency="true"></iframe></td>
</tr>
</table>
<table align="center" border="1" width="100%" bordercolor="#2062B8">
<tr>
<td width="25%" bordercolor="#FFFFFF"><a
href="http://code.google.com/intl/ptBR/appengine/docs/"> <img
border="0"
src="http://code.google.com/appengine/images/appenginenoborder-120x30.gif"
alt="Powered by Google App Engine" /></a></td>
<td align="right" bordercolor="#FFFFFF"><font
face="Times New Roman"><a
href="mailto:[email protected]">[email protected]</a>
» Domingos de Carvalho Villela Júnior, especialização Java
» UTFPR/Cornélio Procópio/PR/Brazil »
Janeiro/2011</font></td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
Download