Uma introdução ao Google App Engine com GWT - PDF
Download "Uma introdução ao Google App Engine com GWT"
Brian Teixeira Martins
1 : : : : Uma introdução ao Google App Engine com GWT Desenvolvendo Java em Cloud Computing. Luiz Felipe Gomes Teixera É desenvolvedor Java na IPNET Soluções com ênfase em aplicações em cloud computing, é graduando em Análise e Desenvolvimento de Sistemas no Instituto Infnet. Possui 4 anos de experiência em programação e é otimista sobre o desenvolvimento em nuvem. Possui as certificações SCJA, SCJP. O desenvolvimento em nuvem carrega diversos detalhes e configurações de aplicações tanto para otimizações quanto para o simples envio para a estrutura em nuvem. Aqui abordaremos como desenvolver aplicações para a estrutura Google e como gerenciar nossas aplicações. 12
2 desenvolvimento de aplicações em Java mais elaboradas e com mais recursos estão nos obrigando cada vez mais a escalar nossos servidores de aplicações, o que nos leva muitas vezes a ter que realizar outras configurações na nossa infraestrutura. Contudo o mercado para se adequar a estas necessidades começou a utilizar o conceito de Cloud Computing, que hoje já tem o seu espaço e está se desenvolvendo cada vez mais. As principais e mais conhecidas empresas que disponibilizam esse tipo de plataforma para desenvolvimento são a Google e a Amazon, que além de disponibilizar um servidor de aplicação completo e escalado também fornece um banco de dados em formato NoSQL para persistência de dados. Ferramenta Google App Engine (GAE) O Google, por sua grande expansão mundial, foi um dos primeiros a implantar uma plataforma em cloud aberta para desenvolvimento de aplicativos integrados à plataforma. Atualmente, essa infraestrutura possibilita a utilização da linguagem Java ou python. Para o desenvolvimento Web a plataforma GAE disponibiliza também um endereço de hospedagem da sua aplicação. Onde a url para acesso segue da seguinte forma: <suaaplicação>.appspot. com. O ambiente de execução em Java do GAE permite que você crie seu aplicativo usando tecnologias Java convencionais. Qualquer outra linguagem que use um interpretador ou compilador com base na JVM, como javascript ou Ruby, também pode ser integrado à plataforma. Para Saber Mais Para criar uma conta no GAE, você deve acessar o link, e possuir uma conta de do Gmail para se registrar. Após o registro você poderá criar até 10 aplicações na sua conta. Após a criação de uma conta, deve-se utilizar o Googlipse para criar suas aplicações, que é um plugin que se integra ao eclipse para facilitar a criação de aplicativos para a plataforma GAE. A ferramenta utilizada para auxílio ao desenvolvimento com GWT é o GWT Designer, que é um plugin do eclipse adicional, que permite ao desenvolvedor criar interfaces ricas em modo visual, o que facilita a criação de interfaces de acesso de aplicativos e eventos. Pode ser obtido em: tools/gwtdesigner/installation/index. Existem abstrações para o framework GWT. A mais conhecida e utilizada no mercado é o Vaadin que pode ser encontrado em o mesmo já possui vários objetos com a integração do GWT e alguns adicionais que completam a formação de uma interface rica com todos os recursos visuais utilizados geralmente com ajax e javascript. Googlipse é o plugin criado pela Google para facilitar o desenvolvimento de aplicações com as definições solicitadas pela plataforma GAE para hospedar uma aplicação. O plugin está disponível para diversas versões do Eclipse e pode ser obtido em google.com/appengine/downloads.html. Após realizar a instalação, você possuirá integrado ao seu eclipse o Jetty (servidor de aplicação), ferramentas para testes unitários (Junit) e uma SDK que compõe o desenvolvimento para Cloud Computing utilizando GAE. Para criar a primeira aplicação, selecione New > Project > Google > Web Apllication Project. Após avançar, selecione o nome do projeto e pacote e desative a opção Use Google Web Toolkit, que nesse primeiro momento não será abordado. Após isso, um novo projeto será adicionado ao eclipse já com um servlet criado e mapeado como é apresentado na figura 1. Figura 1. Novo projeto utilizando o plugin Googlipse. 13
3 : : : : A estrutura do projeto é a seguinte: Alias para seus pacotes com suas Classes Java, Servlets etc. configurações XML para persistência SDK para o desenvolvimento em cloud Java Runtime pasta direcionada ao acesso a sua aplicação (antigo Web- Content) contém a pasta lib para agregar drivers e frameworks no seu projeto além dos arquivos appengine-web.xml, logging. properties e web.xml. O arquivo contido em META-INF com o título de jdoconfig.xml possui as configurações para tratamento de persistência em cloud utilizando JDO com BigTable que é uma base NoSQL. A princípio, a aplicação Hello Word já está criada e você pode realizar o teste da mesma com o servidor de aplicação integrado. Selecione a pasta do projeto e selecione Run Web Application. Seu servidor de aplicação irá iniciar e será informado em seu console que o servidor já está rodando na porta 8888, no endereço local de sua máquina, acesse para realizar o teste localhost:8888. Persistência - O que é GQL? A hospedagem GAE foi desenvolvida para utilizar sua aplicação 100% em cloud. Logo a preferência é que você utilize a persistência de dados também na mesma infra que a disponibilidade da aplicação. Para isso é disposto para todas as contas registradas um banco NoSQL para qualquer aplicação que você crie. A ferramenta SDC (Security data Connector) permite que você acesse seus dados hospedados em um servidor local para o tratamento em cloud, mas essa ferramenta-formato não será abordado neste artigo. Como persistir em Nuvem? Existem algumas especificações para o desenvolvimento em nuvem integrado na sua aplicação. A plataforma GAE disponibiliza preferencialmente dois: JDO e JPA. Estes podem ser verificados aqui e docs/java/datastore/jpa/. Um conceito diferente do armazenamento que é realizado num banco local é a necessidade de criação de uma entidade para ser persistida no banco, além de registrada anteriormente. Caso esteja acostumado a criar aplicativos modelando a estrutura do banco de dados primeiro (ou seja, imaginar tabelas e seus relacionamentos primeiro), então a modelagem de dados com um armazenamento de dados sem esquemas, como o Bigtable, necessitará que você repense na maneira como faz as coisas. No entanto, caso você crie seus aplicativos começando com um modelo de domínio, então você irá perceber que a estrutura sem usar esquemas do Bigtable é mais natural. Muitos frameworks de persistência, como Hibernate, realizam a criação das entidades para serem persistentes em um banco de dados e opcionalmente, caso seja necessário, é possível utilizar um armazenamento direto com a api jdbc. O que já não é possível utilizando GAE. Todo dado a ser persistido deve ter sua classe persistente registrada na aplicação para que a persistência seja utilizada. Iremos utilizar neste artigo a API Objectify que não é desenvolvida diretamente pela Google, mas é validada para todos os serviços em GAE e por possuir um tratamento mais amigável é a mais cotada entre os desenvolvedores. Dentre essas apis também pode ser utilizada a API do datastore que utiliza um tratamento de baixo nível para realização do tratamento de banco de dados. Para a documentação e download da api Objectify, acesse code.google.com/p/objectify-appengine/. Após realizar o download da mesma, adicione ao buid-path do seu projeto. Para deixar uma classe persistente é necessário implementar a interface serializable e direcionar um atributo da classe para ser o id no banco preferencialmente como Long ou int. Os gets e Sets não precisam ser padrões para esta utilidade. O import da anotação Entity deve ser realizado diretamente da api objectify (Listagem 1). Listagem 1. Implementação da classe para persistência. import java.io.serializable; import javax.persistence.id; import public class Cadastro implements Serializable Long id; private String nome; private String ; private String senha; //gets e sets Com esse formato, a classe Cadastro já pode ser persistida no DataStore disponibilizado para a aplicação. Para realizar o efetivo cadastro de um determinado usuário, é necessário realizar o registro da classe que realiza a criação da entidade no banco de dados como é apresentado na Listagem 3. 14
4 Listagem 2. Interface para cadastro. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>cadastro</title> </head> <body> <h1>cadastro</h1> <form action="mundojava"> Nome : <input type="text" name="nome"> <input type="text" name=" "> Senha : <input type="text" name="senha"> <br/> <input type="submit"> </form> <table> <tr> <td><a href="mundojava">mundojava</a></td> </tr> </table> </body> </html> Listagem 3. Servlet para cadastro. package com.mundojava; import java.io.ioexception; import javax.servlet.http.*; import com.googlecode.objectify.objectify; import com.googlecode.objectify.objectifyservice; import com.model.cadastro; public class MundoJavaServlet extends HttpServlet { public void doget(httpservletrequest req, HttpServletResponse resp) throws IOException { resp.setcontenttype( text/html ); String nome = req.getparameter( nome ); String = req.getparameter( ); String senha = req.getparameter( senha ); Cadastro novocadastro = new Cadastro(); novocadastro.setnome(nome); novocadastro.set ( ); novocadastro.setsenha(senha); //registro de classe no banco DataStore ObjectifyService.register(Cadastro.class); //inicia o servico de persistencia Objectify ofy = ObjectifyService.begin(); //Faz a inserção no Banco de dados ofy.put(novocadastro); Figura 2. Configurando o deploy para Cloud Computing no GAE. Agora, iremos subir nossa aplicação para nosso servidor em cloud. Para realizar isso, iremos selecionar com o botão direito o diretório da aplicação e ir à opção Google > deploy to app engine. Após selecionar essa opção, é necessário configurar sua aplicação para seu autenticado no GAE juntamente com o id da aplicação. A aplicação deve ser criada anteriormente a ser disponibilizada no GAE, pois o id da mesma é utilizado quando realizamos o deploy da mesma (figura 2). 15
5 : : : : Podemos acessar o sistema de cadastro em mundojava.appspot. com para verificar o funcionamento da mesma. Uma parte interessante do armazenamento no GAE é o painel de administração fornecido para o controle de dados persistidos e inserção de dados usando GQL. Essa interface poder ser acessada no endereço Após realizar o login, selecione sua aplicação e após isso selecione o item Data Viewer. Após verificar que os dados foram criados como visto na figura 3, podemos realizar filtros de busca a partir da aplicação, o tratamento de do select tratado pela api objectify também é diferente do convencional. É utilizada a notação de filtros (Listagem 4). Figura 3. Administração do banco de dados No-SQL. Figura 3. Administração do banco de dados No-SQL. Listagem 4. Select no DataStore do GAE. //o método filter é responsavél por fazer as querys de busca //o primeiro parametro é o nome do atributo da entidade //o filtro retorna um array list //registro de classe no banco DataStore ObjectifyService.register(Cadastro.class); //inicia o servico de persistencia Objectify ofy = ObjectifyService.begin(); Query<Cadastro> q = ofy.query(cadastro.class).filter( nome, joao ); ArrayList<Cadastro> findcadastro = new ArrayList<Cadastro>(); for (Cadastro cadastro : q) { findcadastro.add(cadastro); A busca retorna um Array com todas as informações encontradas referente àquela busca realizada e esse fator torna necessária a varredura no mesmo como o tratamento que é realizado em um ResultSet convencional. GWT Poderoso e fácil de usar O Gwt é uma ótima ferramenta para criar web applications de uma forma elegante e prática. A formatação do Gwt já foi elaborada em foco com a utilização da plataforma GAE, pois a padronização da estrutura do projeto facilita escalar a aplicação desenvolvida. Esse framework aos poucos está ganhando seu espaço por sua facilidade de uso e padronização de estruturas de projetos, sendo uma alternativa ao JSF para o desenvolvimento orientado a componentes. Para utilizar o framework, selecione um novo projeto Google e, após isso, marque o checkbox referente ao uso do Google Web Toolkit no seu projeto. A estrutura a ser criada é um pouco diferente da convencional, figura 4, verificada nos projetos Web. Como carro-chefe, o GWT utiliza o protocolo RPC para qualquer tipo de chamada ao servidor que trata de forma mais elegante as requisições realizadas na camada Servidor. A estrutura do GWT possui uma formatação que divide o seu projeto em: 16
6 Cliente: todas as classes que ficam disponíveis para o cliente (Viewer). Servidor: todas as classes que são usadas como servidor ou que realizam acesso a um. Shared: todas as classes compartilhadas no seu projeto, como, por exemplo, uma validação de campos UI. <Projeto>.gwt.xml: possui as configurações do módulo que está sendo desenvolvido. Teste: pacote que armazena suas classes de teste. Figura 5. GWTDesigner módulo de exemplo. Figura 4. Estrutura GWT. Crie um novo projeto, selecione New Project > WindowBuider > GWTDesigner. É interessante após clicar em avançar selecionar o modelo ImageViewer que já apresenta um modelo de projeto desenvolvido com GWT + GWTDesigner como apresentado na figura 5. Após a criação desse módulo, para que seja utilizado o plugin do GWT designer (figura 6), é necessário selecionar a classe que contém a camada visual e utilizar a aba Design que fica disposta nas abas auxiliares. Caso o mesmo ainda não esteja disponível, na camada de visualização selecione a opção Open with Window- Builder Editor, que a opção para designer ficará disponível. Para que seja criado o acesso ao servidor, selecione no seu pacote do projeto a opção Google Web Toolkit e new GWT remote service. Essa opção irá criar uma estrutura RPC simples para fazer a comunicação com o servidor. Para que a API Objectify seja utilizada é necessário que esta seja declarada no.xml que guarda as configurações do módulo como mostra a Listagem 5. Figura 6. GWT designer. 17
7 : : : : Listagem 5. Módulo GWT com objectify. <module> <inherits name= com.google.gwt.user.user /> <inherits name= com.google.gwt.user.theme.standard.standard /> <inherits name= com.googlecode.objectify.objectify /> <entry-point class= com.mycompany.project.client.imageviewer /> </module> Após a adição do inherit se torna possível realizar a persistência dos dados, sendo necessária a criação da classe persistente e rpc que fará a chamada para uma das funções crud no servidor, Listagem 6. Listagem 6. Classe persistente GWT com objectify. import javax.persistence.entity; import public class Animal implements Serializable Long id; private String tipo; private String cor; public void settipo(string tipo) { this.tipo = tipo; public String gettipo() { return tipo; public void setcor(string cor) { this.cor= cor; public String getcor() { return cor; Listagem 7. Classe de Visualização GWT com objectify. package com.exemplo.myproject.client; import com.google.gwt.core.client.entrypoint; //outros imports... public class GWTObjectify implements EntryPoint { // Criando campos UI VerticalPanel mainverticalpanel = new VerticalPanel(); HorizontalPanel hp1 = new HorizontalPanel(); //... // Instanciando a classe que realiza a chamada assincrona para o servidor private final PersistentServiceAsync persistentservice = GWT.create(PersistentService.class); public void onmoduleload() { //criando os inputs de texto hp1.add(corlabel); hp1.add(cortextbox); //... //adicionando à janela principal mainverticalpanel.add(hp1); mainverticalpanel.add(hp2); mainverticalpanel.add(submit); hp1.setspacing(5); hp2.setspacing(5); mainverticalpanel.setspacing(5); A criação da classe de visualização deve ser auxiliada pelo GWT designer que possui funções para criações de métodos e eventos como é apresentado na Listagem 7. Toda chamada ao servidor necessita que seja criada uma interface de comunicação síncrona e uma assíncrona que se comunicam antes de realizar o callserver como é apresentado nas Listagens 8 e 9. Listagem 8. Interface de Serviço GWT com objectify. package com.exemplo.myproject.client; import com.google.gwt.user.client.rpc.remoteservice; import com.google.gwt.user.client.rpc.remoteservicerelativepath; // RemoteServiceRelativePath annotation precisa ser declarada para uso na configuracao da URL //no persistentservice ) public interface PersistentService extends RemoteService { void persistanimal(string cor, String tipo) throws IllegalArgumentException; //Adicionando evento no botão. Quando clicado //faz a chamada RPC usando o serviço de persistencia. submit.addclickhandler(new ClickHandler() { public void onclick(clickevent event) { persistentservice.persistanimal(cortextbox.gettext(), tipotextbox.gettext(), new AsyncCallback<Void>() public void onfailure(throwable excessao) { System.out.println( A chamada falhou + public void onsuccess(void result) { System.out.println( RPC bem sucedido ); ); ); RootPanel.get( container ).add(mainverticalpanel); 18
8 Listagem 9. Interface assíncrona de Serviço GWT com objectify. package com.example.myproject.client; import com.google.gwt.user.client.rpc.asynccallback; public interface PersistentServiceAsync { void persistanimal(string cor, String tipo, AsyncCallback<Void> callback); A classe que fica disposta no pacote server sempre deve possuir o complemento Impl mostrado na Listagem 10, que define a implementação do servidor e o framework utiliza essa notação para diferenciar se a classe é Server ou não depois de compilada. Listagem 10. Classe Servidor GWT com objectify. package com.exemplo.myproject.server; import com.exemplo.myproject.client.persistentservice; import com.exemplo.myproject.client.entities.animal; import com.google.gwt.user.server.rpc.remoteserviceservlet; import com.googlecode.objectify.objectify; import serial ) public class PersistentServiceImpl extends RemoteServiceServlet implements PersistentService { //Metodo precisa existir na Interface de servico e na Interface Assincrona public void persistanimal(string cor, String tipo) { //registro da classe animal, na api objectify ObjectifyService.register(Animal.class); Objectify ofy = ObjectifyService.begin(); Listagem 11. Web XML GWT com objectify. <servlet> <servlet-name>persistenceservlet</servlet-name> <servlet-class>com.exemplo.myproject.server.persistentserviceimpl </servlet-class> </servlet> <servlet-mapping> <servlet-name>persistenceservlet</servlet-name> <url-pattern>/gwtobjectify/persistentservice</url-pattern> </servlet-mapping> Após realizada essa configuração, seu projeto já está pronto para ser enviado para o GAE, que recebe o projeto usando GWT da mesma forma que um projeto comum. A velocidade para a criação das camadas UI são bem otimizadas assim como toda a manipulação do banco de dados que por se localizar na mesma infraestrutura e possuir formato No-SQL no facilita quanto a escalabilidade do banco de dados e custos de administração geral. Considerações finais Com o preço atual dos servidores e custos gerais que uma empresa possui, o desenvolvimento em cloud é uma ótima opção. Além do valor para a uma hospedagem mais completa ser baixo, possuir um banco de dados escalado e sempre funcionando juntamente com a aplicação mostra que desenvolver em cloud é a nova forma de desenvolver que ganha espaço a todo tempo e que futuramente estará aos redores de todo o mercado de trabalho e todo o universo de linguagens de programação. Dentro desta estrutura de desenvolvimento, temos também a segurança que nossa aplicação rodará 24 x 7 sem nos preocuparmos diretamente com nossos servidores, resfriamento, custos de hardware o que deixa a tecnologia mais atrativa para ser utilizada. Animal animal = new Animal(); animal.setcor(cor); animal.settipo(tipo); //insert com objectify ofy.put(animal); O mapeamento do servlet deve sempre mapear a classe Impl, ou seja, apontar para o seu servidor. Que no nosso caso é o acesso ao banco de dados usando a api objectify (Listagem 11). Referências GUJ Discussões sobre o tema do artigo e assuntos relacionados Discuta este artigo com 100 mil outros desenvolvedores em 19