Desenvolvendo Java em Cloud Computing. · public void doGet (HttpServletRequest req,...
Transcript of Desenvolvendo Java em Cloud Computing. · public void doGet (HttpServletRequest req,...
12
: : www.mundoj.com.br : :
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.
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.
Google App Engine GWTUma introdução ao
comDesenvolvendo Java em Cloud Computing.
13
desenvolvimento de aplicações em Java mais elabora-das 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 disponibili-zam 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 for-mato 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 infraestru-tura 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. Qual-quer 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
e-mail 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: http://code.google.com/webtoolkit/tools/gwtdesigner/installation/index.
Existem abstrações para o framework GWT. A mais co-nhecida e utilizada no mercado é o Vaadin que pode ser encontrado em http://vaadin.com, o mesmo já possui vários objetos com a integração do GWT e alguns adicio-nais 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 desenvol-vimento de aplicações com as definições solicitadas pela platafor-ma GAE para hospedar uma aplicação. O plugin está disponível para diversas versões do Eclipse e pode ser obtido em http://code.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 ma-peado como é apresentado na figura 1.
Figura 1. Novo projeto utilizando o plugin Googlipse.
14
: : www.mundoj.com.br : :
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 en-dereço local de sua máquina, acesse para realizar o teste http://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 persis-tê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 trata-mento em cloud, mas essa ferramenta-formato não será abordado neste artigo.
Como persistir em Nuvem?
Existem algumas especificações para o desenvolvimento em nu-vem integrado na sua aplicação. A plataforma GAE disponibiliza preferencialmente dois: JDO e JPA.
Estes podem ser verificados aqui http://code.google.com/appengi-ne/docs/java/datastore/jdo/ e http://code.google.com/appengine/docs/java/datastore/jpa/. Um conceito diferente do armazenamen-to 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 mode-lando 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 coi-sas. 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 co-tada 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 http://code.google.com/p/objectify-appengine/. Após realizar o downlo-ad 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 com.googlecode.objectify.annotation.Entity;
@Entity
public class Cadastro implements Serializable {
@Id Long id;
private String nome;
private String email;
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 regis-tro da classe que realiza a criação da entidade no banco de dados como é apresentado na Listagem 3.
15
Listagem 2. Interface para cadastro. Listagem 3. Servlet 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"> Email : <input type="text" name="email"> Senha : <input type="text" name="senha"> <br/> <input type="submit"> </form> <table> <tr> <td><a href="mundojava">MundoJava</a></td> </tr> </table> </body></html>
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 email = req.getParameter(“email”);
String senha = req.getParameter(“senha”);
Cadastro novoCadastro = new Cadastro();
novoCadastro.setNome(nome);
novoCadastro.setEmail(email);
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);
}
}
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 e-mail 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).
Figura 2. Configurando o deploy para Cloud Computing no GAE.
16
: : www.mundoj.com.br : :
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 http://appengine.google.com. 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 tratamen-to 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 com-ponentes.
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 di-ferente 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:
17
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 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.
Figura 5. GWTDesigner módulo de exemplo.
Figura 6. GWT designer.
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 ser-vice. 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.
18
: : www.mundoj.com.br : :
Listagem 5. Módulo GWT com objectify.
Listagem 6. Classe persistente – GWT com objectify.
Listagem 8. Interface de Serviço – GWT com objectify.
Listagem 7. Classe de Visualização – 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>
import javax.persistence.Entity;import javax.persistence.Id;@Entitypublic class Animal implements Serializable { @Id 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; }}
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 servlet
@RemoteServiceRelativePath(“persistentservice”)
public interface PersistentService extends RemoteService {
void persistAnimal(String cor, String tipo) throws IllegalArgumentException;
}
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);
//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>() {
@Override
public void onFailure(Throwable excessao) {
System.out.println(“A chamada falhou “+ excessao);
}
@Override
public void onSuccess(Void result) {
System.out.println(“RPC bem sucedido”);
}
});
}
});
RootPanel.get(“container”).add(mainVerticalPanel);
}
}
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, Lis-tagem 6.
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.
19
Listagem 9. Interface assíncrona de Serviço – GWT com ob-jectify.
Listagem 10. Classe Servidor – GWT com objectify.
Listagem 11. Web XML – 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);}
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 com.googlecode.objectify.ObjectifyService;
@SuppressWarnings(“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(); Animal animal = new Animal(); animal.setCor(cor); animal.setTipo(tipo); //insert com objectify ofy.put(animal); }}
<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>
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.
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).
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 empre-sa 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 univer-so de linguagens de programação.
Dentro desta estrutura de desenvolvimento, temos também a se-gurança que nossa aplicação rodará 24 x 7 sem nos preocuparmos diretamente com nossos servidores, resfriamento, custos de har-dware o que deixa a tecnologia mais atrativa para ser utilizada.
Referências
GUJ – Discussões sobre o tema do artigo e assuntos relacionados
Discuta este artigo com 100 mil outros desenvolvedores em www.guj.com.br/MundoJ