Google App Engine para Java: Parte 1: Acelerar!

Construindo "killer apps" baseados em Java escaláveis com o App Engine para Java

Você se lembra quando o Google App Engine era apenas para Pythonistas? Aqueles foram dias difíceis. A Google Inc. abriu sua plataforma de computação em nuvem para os desenvolvedores em Java ™ em abril de 2009. Neste série de artigos dividida em três partes, o autor e treinador em tecnologia Java Rick Hightower o introduz nesta plataforma confiável, robusta e divertida para o desenvolvimento baseado em Java. Neste artigo, você terá uma visão geral do porquê o Google App Engine para Java poderia ser a plataforma de implementação para o seu próximo "killer app" altamente escalável, e depois começará a usar o Plug-in do Google para Eclipse para construir dois aplicativos de exemplo: um baseado no Google Web Toolkit (GWT) e outro baseado na API Servlet Java. Você aprenderá por si mesmo a diferença que o Google App Engine para Java faz, tanto na construção de um aplicativo a partir do zero quanto na implementação dele para a sintonia de até cinco milhões de visualizações. (E esta é apenas a versão gratuita.)

Richard Hightower, CTO, Trivera Technologies

Rick Hightower é Diretor de Tecnologia da Mammatus Inc., uma empresa de treinamento especializada em computação em nuvem e desenvolvimento em GWT, Java EE, Spring e Hibernate. Ele é co-autor do popular livro Java Tools for Extreme Programming e autor da primeira edição do Struts Live— o download número um no TheServerSide.com por muitos anos. Ele também escreveu artigos e tutoriais para o IBM developerWorks e faz parte do corpo editorial do Java Developer's Journal, como também é um frequente contribuidor dos tópicos Java e Groovy na DZone.



17/Dez/2009

Uma ideia é como uma coceira: você precisa coçá-la e quando faz isso, se sente melhor. Como desenvolvedores de software, gastamos muito tempo pensando em ideias para diferentes tipos de aplicativos. É divertido, certo? O desafiador é descobrir como fazer um produto de software se concretizar. É gratificante imaginar alguma coisa e depois criá-la. A alternativa (uma coceira não coçada) é simplesmente frustrante.

Uma razão para muitos aplicativos nunca decolarem é a necessidade de infraestrutura. Uma estrutura bem mantida geralmente envolve uma equipe de administradores do sistema, DBAs, e engenheiros de rede, o que, até recentemente, era uma corporação principalmente para os ricos. Mesmo pagar um terceiro para hospedar seu aplicativo não é uma garantia: o que acontece se a popularidade do aplicativo subir vertiginosamente e, de repente, receber vários acessos? O chamadoefeito Slashdot pode afundar uma boa ideia, simplesmente porque é difícil prever picos de carga.

Mas, como todos nós sabemos, isso está mudando. A premissa dos serviços da Web evoluiu, e hoje está trazendo até nos os meios, via computação em nuvem e seu primo mais robusto, a plataforma-como-um-serviço/PAAS, para construir, implementar e distribuir aplicativos mais facilmente. Hoje, quando você escreve o próximo Twitter e o implementa em uma plataforma em nuvem ele irá escalar, meu caro, escalar. Uau, isso parece ótimo!

Neste artigo de três partes, você aprenderá na prática porque a computação em nuvem/PAAS é uma guinada evolucionária importante para o desenvolvimento de software, ao mesmo tempo em que será apresentado a uma nova estimulante plataforma para o desenvolvimento em Java: o Google App Engine para Java, que atualmente está disponível em preview release. Você vai começar com uma visão geral do App Engine para Java, incluindo os tipos de serviços de aplicativo que ele fornece. Depois disso, você mergulhará diretamente num exemplo de aplicativo — o primeiro de dois — usando o plug-in do Google para Eclipse do App Engine para Java.O primeiro exemplo de aplicativo irá potencializar o suporte do App Engine para Java para a API do Servlet Java e o segundo irá potencializar seu suporte para GWT. Na Parte 2, você criará um pequeno aplicativo de gerenciamento de contato usando o suporte do App Engine para Java para servlets e GWT, respectivamente. E na Parte 3, você usará seu aplicativo de construção customizada para explorar o suporte à persistência baseado em Java do App Engine para Java, que se baseia no Java Data Objects (JDO) e na Java Persistence API (JPA).

OK, chega de papo: vamos acelerar!

Sobre o Google App Engine para Java

O Google (também o marcador de algum tipo de mecanismo de procura, creio eu) liberou o Google App Engine pela primeira vez em abril de 2008. Para o desânimo de muitos desenvolvedores em Java, o release inicial era puramente o domínio dos programadores de Python — pessoas que acham que espaço em branco deve ser usado para blocos! (Eu escrevi um livro sobre Python, por isso eu sei.) O Google respondeu à demanda popular liberando o Google App Engine para Java em abril de 2009.

O Google App Engine para Java fornece uma solução de ponta a ponta para o desenvolvimento em Java corporativo: uma GUI Ajax baseada em navegador para facilidade de uso, suporte à ferramenta Eclipse, e Google App Engine no back end. Facilidade de uso e ferramentas são vantagens do Google App Engine para Java sobre outras soluções de computação em nuvem.

O desenvolvimento de aplicativo no App Engine para Java significa usar os recursos do Google para armazenar e recuperar objetos Java. O armazenamento de dados é baseado na BigTable, mas com as interfaces JDO e JPA que permitem escrever código que não está diretamente ligado à BigTable. De fato, o Google fornece suporte baseado em padrões para muitas APIs para que você possa escrever código que não esteja 100% ligado à plataforma App Engine para Java.

O App Engine para Java conta com as seguintes APIs Java padrão:

  • java.net.URL para buscar serviços (por meio de comunicação com outros hosts usando os protocolos HTTP e HTTPS)
  • JavaMail para enviar mensagens de e-mail
  • Um interface JCache (JSR 107) com Memcache para fornecer armazenamento distribuído temporário e rápido para armazenar em cache consultas e cálculos

Implementando o App Engine para Java no WebSphere/DB2

Quando eles anunciaram o App Engine para Java, repr6esentantes do Google e da IBM® implementaram o mesmo aplicativo de amostra no DB2® /WebSphere®. A IBM está trabalhando para fornecer suporte de API do Google de baixo nível para o Tivoli® LDAP e DB2 para que os aplicativos construídos para o App Engine para Java também possam executar na pilha do IBM WebSphere/DB2.

Além disso, o App Engine para Java fornece suporte para os seguintes serviços de aplicativo:

  • Autenticação e autorização de usuário
  • CRON
  • Importação/exportação de dados
  • Acesso a dados do firewall

A importação/exportação de dados é importante para mover dados de outras origens para o seu aplicativo App Engine para Java. Esta é outra maneira pela qual você não está ligado ao App Engine para Java. O suporte de CRON do Google se baseia em uma URL interna que é acessada numa determinada programação, tornando este um bom serviço que não tem muito ligação com o App Engine para Java. O mecanismo de autenticação e autorização de usuário é específico para o App Engine para Java, mas você poderia escrever um ServletFilter, aspecto, ou plug-in Spring Security para minimizar esse forte acoplamento.

Crie o seu primeiro aplicativo App Engine para Java

Se você leu até aqui, está pronto para começar a construir o seu primeiro aplicativo App Engine para Java. Sua primeira etapa é instalar o Plug-in do Google para Eclipse para o App Engine para Java; feito isso, você está pronto para prosseguir.

Abra o seu Eclipse IDE e verá três novos botões no seu Eclipse IDE ao lado do botão de Impressora: Um G em uma bola azul, um G em uma caixa de ferramentas vermelha, e um mini-jato do App Engine para Java, como mostrado na Figura 1:

Figura 1. Novos botões brilhantes no seu Eclipse IDE
Novos botões brilhantes no seu Eclipse IDE

Aqui está o que esses botões fazem:

  • A bola azul permite acessar o assistente de criação de projeto do App Engine para Java.
  • A caixa de ferramentas vermelha permite compilar um projeto GWT.
  • O mini-jato é a sua chave para implementar um projeto App Engine.

Você usará o assistente de criação de projeto para criar dois novos projetos: um baseado em servlets e o outro construído usando GWT. Você usará a funcionalidade da caixa de ferramentas para compilar um projeto GWT. Você ativará o mini-jato quando estiver pronto para implementar o projeto App Engine, dando vida a ele.

Agora inicie criando um projeto App Engine para Java. Primeiro, clique na bola azul para acessar o assistente de criação de projeto. Depois, crie um aplicativo chamado SimpleServletApp usando o pacote chamado gaej.example, como mostrado na Figura 2:

Figura 2. Iniciando um novo projeto
Iniciando um novo projeto

Note como o suporte de GWT está desmarcado para este primeiro exemplo simples. Após concluir esta etapa, o assistente de criação de projeto criará um aplicativo baseado em servlet simples apresentando um sevlet do tipo Hello World. A Figura 3 mostra uma captura de tela do projeto:

Figura 3. O projeto SimpleServletApp
O projeto SimpleServletApp

Note os arquivos JAR que são automaticamente incluídos neste novo projeto baseado em servlet:

  • datanucleus-*.jar: Para acessar o armazenamento de dados do App Engine para Java usando o JDO padrão ou a API da BigTable de baixo nível.
  • appengine-api-sdk.1.2.0.jar: Para usar serviços de aplicativo do App Engine para Java não-padrão como o App Engine para Java Security
  • geronimo-*.jar Para usar APIS Java padrão como Java Transaction Management API (JTA) e JPA
  • jdo2-api-2.3-SNAPSHOT.jar: Para usar a API JDO

Você aprenderá como usar as APIs de persistência do App Engine para Java e alguns dos serviços de aplicativo do App Engine para Java que começam na Parte 2 deste artigo.

Também note o arquivo para configurar o contêiner de tempo de execução para o Google App Engine, chamado appengine.xml. Neste exemplo, appengine.xml está sendo usado para configurar o arquivo logging.properties para a criação de log com o App Engine para Java.

Primeiro olhe para um aplicativo de servlet do App Engine para Java

Depois de configurar tudo no assistente de criação de projeto, o App Engine para Java apresenta os elementos essenciais de um aplicativo de servlet no estilo Hello World. Olhe o código e depois veja como executar o aplicativo usando as ferramentas do Eclipse do App Engine para Java. O principal ponto de entrada para este aplicativo é o SimpleServletAppServlet, como mostrado na Listagem 1:

Listagem 1. SimpleServletAppServlet
package gaej.example;

import java.io.IOException;
import javax.servlet.http.*;

@SuppressWarnings("serial")
public class SimpleServletAppServlet extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        resp.setContentType("text/plain");
        resp.getWriter().println("Hello, world");
    }
}

O servlet é mapeado sob a URI /simpleservletapp no web.xml, como mostrado na Listagem 2:

Listagem 2. web.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
    <servlet>
        <servlet-name>simpleservletapp</servlet-name>
        <servlet-class>gaej.example.SimpleServletAppServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>simpleservletapp</servlet-name>
        <url-pattern>/simpleservletapp</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
</web-app>

O assistente de criação de projeto também fornece um arquivo index.html que tem um link para o novo servlet, como mostrado na Listagem 3:

Listagem 3. index.html gerado pelo assistente de criação de projeto
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- A declaração HTML 4.01 Transitional DOCTYPE-->
<!-- acima definida no topo do arquivo definirá    
 --><!-- o mecanismo de renderização do navegador para-->
<!-- "Modo Quirks". Substituir esta declaração--> 
<!-- por um tipo de documento "Modo Standards" é suportado, -->
<!-- mas pode levar a algumas diferenças no layout.   -->

<html>
  <head>
    <meta http-equiv="content-type" content="text/html; 
	charset=UTF-8">

    <!--                                           
	-->
    <!-- Qualquer título está bem--> <!--                                          
	-->
    <title>Olá, App Engine</title>
  </head>

  <!--                                           -->
  <!-- O corpo pode ter html arbitrário, ou      -->
  <!-- você pode deixar o corpo vazio se desejar-->
  <!-- para criar uma UI completamente dinâmica.        -->
  <!--                                           -->
  <body>
    <h1>Olá, App Engine!</h1>

    <table>
      <tr>
        <td colspan="2" style="font-weight:bold;">Servlets Disponíveis:</td>
      </tr>
      <tr>
        <td><a href="simpleservletapp"/>SimpleServletAppServlet</td>
      </tr>
    </table>
  </body>
</html>

O que mais funciona com o App Engine para Java?

O Google mantém uma listagem de ferramentas e estruturas que funcionam bem com o App Engine para Java (consulte Recursos). Por exemplo, o App Engine para Java suporta muitos linguagens JVM, incluindo BeanShell, Groovy, Scala, JRuby, Jython e Rhino. Porque o App Engine para Java suporta poucas APIs Java SE e Java EE — como Servlets, JSP, JPA, JavaMail, e a API Java para Processamento XML (JAXP) — muitas estruturas existentes funcionam no App Engine para Java imediatamente. Por exemplo, é possível usar a estrutura Spring, porém você precisará de algumas soluções alternativas para usar o Spring ORM. Tapestry, Wicket, DWR, Tiles, SiteMesh e Grails também funcionam. O Struts 2 funcionam com uma pequena correção. Algumas estruturas que não funcionam no App Engine para Java são Hibernate e JDBC (nenhum suporte para bancos de dados relacionais), JMX, Java WebServices, JAX-RPC ou JAX-WS, JCA, JNDI, JMS, EJB e Java RMI.

Agora você tem um aplicativo de servlet simples construído usando somente APIs Java. E este é o ponto: o App Engine para Java envolve a funcionalidade do App Engine usando APIs Java padrão, possibilitando ao App Engine suportar o funcionamento de estruturas disponíveis para a plataforma Java.

Implementando o aplicativo

Para executar o seu aplicativo baseado em servlet com as ferramentas do Eclipse do App Engine para Java, primeiro dê um clique com o botão direito no projeto e selecione o menu Executar Como , depois selecione "Aplicativo da Web" com a bola azul dentro dele, como mostrado na Figura 4:

Figura 4. Executando o servidor de desenvolvimento do App Engine para Java
Executando o servidor de desenvolvimento do App Engine para Java

Agora você deve estar apto para navegar para http://localhost:8080/simpleservletapp no seu navegador e ver o aplicativo com a mensagem Hello World.

GWT versus aplicativos da Web em Java tradicional

Ao trabalhar no GWT, você compila código Java para JavaScript e depois executa a GUI do aplicativo da Web no navegador. O resultado é muito mais parecido com um aplicativo de GUI tradicional do que com um aplicativo da Web em Java tradicional. O GWT tem um componente do cliente que executa no navegador.O componente do cliente conversa com o seu código do lado do servidor Java através de um conjunto de classes Java em estilo RMI que você escreve.

Crie um App Engine para Java/aplicativo GWT

Você teve uma ideia de como um simples aplicativo servelt do App Engine para Java funciona, assim, a seguir, vamos explorar as ferramentas do Eclipse do App Engine para Java para aplicativos GWT. Comece clicando na bola azul na sua barra de ferramentas do Eclipse IDE para ativar o assistente de criação de projeto do Google. Desta vez, selecione suporte para GWT, como mostrado na Figura 5:

Figura 5. Criando um aplicativo GWT simples com o assistente de criação de projeto do App Engine para Java
Criando um aplicativo GWT simples com o assistente de criação de projeto do App Engine para Java

Como você pode ver na Figura 6, o App Engine para Java fornece muito mais artefatos de código para um aplicativo GWT do que para um aplicativo simples baseado em servlet. O aplicativo de exemplo é uma GUI feita no GWT que conversa com um aplicativo de serviço de saudação.

Figura 6. Artefatos de código fornecidos para um aplicativo GWT
Artefatos de código fornecidos para um aplicativo GWT

Existe um JAR extra para o aplicativo GWT que não foi necessário para o aplicativo baseado em servlet, chamado gwt-servlet.jar.

Os outros artefatos são os seguintes:

  • src/gaej/example: SimpleGWTApp.gwt.xml: descritor do módulo GWT
  • src/gaej.example.server: GreetingServiceImpl.java: Implementação do serviço de saudação
  • src/gaej.example.client: GreetingService.java: API síncrona para o serviço de saudação
  • src/gaej.example.client: GreetingServiceAsync.java: API assíncrona para o serviço de saudação
  • src/gaej.example.client: SimpleGWTApp.java: Ponto de entrada principal que também constrói a GUI inicializadora
  • war/WEB-INF: web.xml: Descritor de implementação que configura GreetingServiceImpl
  • war: SimpleGWTApp.html: Página HTML que exibe a GUI do GWT
  • war: SimpleGWTApp.css: Folha de estilo para a GUI do GWT

Antes de detalhar a arquitetura do aplicativo e o código de origem, veja o que acontece quando você o executa. Para executar o aplicativo, clique na caixa de ferramentas vermelha na sua barra de ferramentas, e depois clique no botão Compilar . Agora dê um clique com o botão direito do mouse no projeto e selecione o item de menu Executar Como—> Aplicativo Web como você fez antes. Desta vez, porque você está trabalhando em um aplicativo GWT, um Console de Modo Hospedado GWT e um navegador aparecerão.Avance e use a aplicativo da Web para inserir seu nome e ver a resposta. Eu recebi a resposta mostrada na Figura 7:

Figura 7. Executando o aplicativo GWT de amostra
Executando o aplicativo GWT de amostra

Nas próximas seções, eu o levarei através do aplicativo GWT de amostra. Se você desejar saber mais sobre o GWT (ou executar o tutorial do GWT), consulte Recursos.

Dentro do aplicativo GWT

Baseado na configuração fornecida, a ferramenta GWT do Eclipse cria um aplicativo inicializador que apresenta um front end HTML (SimpleGWTApp.html, mostrado na Listagem 10) que carrega simplegwtapp.js e simplegwtapp.nocache.js. Isto é código JavaScript que é gerado pelo GWT a partir do seu código Java; a saber, o código que está no diretório src sob o pacote gaej.example.client (consulte as Listagens 6, 7, e 8).

O ponto de entrada principal para a criação da GUI é gaej.example.client.SimpleGWTApp, mostrado na Listagem 8. Esta classe cria os elementos da GUI e os associa aos elementos DOM HTML no SimpleGWTApp.html (consulte a Listagem 10). O SimpleGWTApp.html define dois elementos DOM denominadosnameFieldContainer e sendButtonContainer (colunas em uma tabela). A classe SimpleGWTApp usa RootPanel.get("nameFieldContainer") para acessar o painel associada com esses elementos DOM e os substitui pelos elementos GUI. A classe SimpleGWTApp então define uma caixa de texto e um botão, que você pode usar para inserir o nome de alguém e enviá-los para uma saudação (consulte a Listagem 10).

O GWT conhece a classeSimpleGWTApp no ponto de entrada principal para o aplicativo porque SimpleGWTApp.gwt.xml o especifica tanto quanto o elemento de ponto de entrada.

SimpleGWTApp conecta o botão, chamadosendButton, para que quando receber um clique SimpleGWTApp chame o método greetServer em GreetingService. A interfaceGreetingService é definida em src/gaej.example.client.GreetingService.java (Listagem 6).

Porque o Ajax é assíncrono por herança, o GWT define uma interface assíncrona para acessar os serviços remotos. O SimpleGWTApp usa a interface assíncrona definida em src/gaej.example.client.GreetingServiceAsync.java (Listagem 7). O GreetingServiceImpl (src/gaej.example.server.GreetingServiceImpl.java) implementa o método greetServer definido em GreetingService (Listagem 5). O método GreetingServiceImpl.greetServer retorna uma mensagem de saudaçãoString que o SimpleGWTApp usa para exibir a mensagem de saudação na caixa de diálogo que ele cria.

O descritor do módulo GWT declara o ponto de entrada principal para o aplicativo GUI, a saber, gaej.example.client.SimpleGWTApp, como mostrado na Listagem 4:

Listagem 4. Descritor do módulo GWT (src/gaej/example/SimpleGWTApp.gwt.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN"

"http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/
  distro-source/core/src/gwt-module.dtd">


<module rename-to='simplegwtapp'>
  <!-- Herda principais elementos do Kit de Ferramentas da Web.                        -->
  <inherits name='com.google.gwt.user.User'/>

  <!-- Herda a folha de estilo GWT padrão.  É possível mudar       -->
  <!-- o tema do seu aplicativo GWT removendo o comentário-->
  <!-- de qualquer uma das seguintes linhas.                            -->
  <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'/>     -->

  <!-- Outro módulo herda          -->
  <!-- Especifique a classe do ponto de entrada do aplicativo.                         -->
  <entry-point class='gaej.example.client.SimpleGWTApp'/>
</module>

GreetingServiceImpl é a implementação real do aplicativo de serviço de saudação, mostrado na Listagem 5. Ele executa no lado do servidor e o código do cliente o chama via uma chamada de procedimento remota.

Listagem 5. Implementação do aplicativo de serviço de saudação (src/gaej.example.server.GreetingServiceImpl.java)
package gaej.example.server;

import gaej.example.client.GreetingService;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * A implementação do lado do servidor do serviço RPC.
 */
@SuppressWarnings("serial")
public class GreetingServiceImpl extends RemoteServiceServlet implements
        GreetingService {

    public String greetServer(String input) {
        String serverInfo = getServletContext().getServerInfo();
        String userAgent = getThreadLocalRequest().getHeader("User-Agent");
        return "Olá, " + input + "!<br><br>Eu estou executando " + serverInfo
                + ".<br><br>Parece que você está usando:<br>" + userAgent; }
}

GreetingService, mostrado na Listagem 6, é a interface para a chamada de procedimento remoto usada pelo código do cliente:

Listagem 6. API síncrona (src/gaej.example.client.GreetingService.java)
package gaej.example.client;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

/**
 * O stub do lado do cliente para o serviço RPC.
 */
@RemoteServiceRelativePath("greet")
public interface GreetingService extends RemoteService {
    String greetServer(String name);
}

GreetingServiceAsync é a interface real que o código do cliente usará, como mostrado na Listagem 7. Cada método fornece um objeto de retorno de chamada para que você seja notificado assincronicamente quando a chamada de procedimento remoto for concluída. Sob o capuz, o GWT usa o Ajax. Ao usar o Ajax no cliente, é melhor se você não bloquear o cliente e, assim, as chamadas assíncronas. O bloqueio anularia o propósito do uso do Ajax.

Listagem 7. API assíncrona (src/gaej.example.client.GreetingServiceAsync.java)
package gaej.example.client;

import com.google.gwt.user.client.rpc.AsyncCallback;

/**
 * A contraparte assíncrona de<code>GreetingService</code>.
 */
public interface GreetingServiceAsync {
    void greetServer(String input, AsyncCallback<String> callback);
}

O SimpleGWTApp é onde a maior parte da ação ocorre. Ele registra os eventos GUI, e depois envia os pedidos do Ajax para o GreetingService.

Listagem 8. Este ponto de entrada principal para o aplicativo também constrói a GUI inicializadora (src/gaej.example.client.SimpleGWTApp.java)
package gaej.example.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * Classes de ponto de entrada definem <code>onModuleLoad()</code>.
 */
public class SimpleGWTApp implements EntryPoint {
    /**
     * A mensagem exibida para o usuário quando o servidor não pode ser atingido ou 
	 * retorna um erro.
     */
    private static final String SERVER_ERROR = "Um erro ocorreu durante"
            + "tentativa de entrar em contato com o servidor. Verifique sua conexão de"
            + "rede e tente novamente.";

    /**
     * Crie um proxy de serviço remoto para conversar com o serviço de Saudação do lado 
	 do servidor.
     */
    private final GreetingServiceAsync greetingService = GWT
            .create(GreetingService.class);

    /**
     * Este é o método do ponto de entrada.
     */
    public void onModuleLoad() {
        final Button sendButton = new Button("Send");
        final TextBox nameField = new TextBox();
        nameField.setText("GWT User");

        // É possível incluir nomes de estilos para widgets 
		sendButton.addStyleName("sendButton");

        // Inclua o nameField e sendButton no RootPanel
        // Use RootPanel.get() 
para obter o elemento do corpo de entrada
   RootPanel.get("nameFieldContainer").add(nameField);
   RootPanel.get("sendButtonContainer").add(sendButton);

   // Foque o cursor no campo de nome quando o aplicativo carregar 
		nameField.setFocus(true);
        nameField.selectAll();

        // Crie a caixa de diálogo pop-up
        final DialogBox dialogBox = new DialogBox();
        dialogBox.setText("Chamada de Procedimento Remoto"); 
		dialogBox.setAnimationEnabled(true);
        final Button closeButton = new Button("Fechar");
        // 
		É possível configurar o ID de um widget 
		acessando seu
		Elemento closeButton.getElement().setId("closeButton");
        final Label textToServerLabel = new Label();
        final HTML serverResponseLabel = new HTML();
        VerticalPanel dialogVPanel = new VerticalPanel();
        dialogVPanel.addStyleName("dialogVPanel");
        dialogVPanel.add(new HTML("<b>
		Enviando nome para o servidor:</b>"));
        dialogVPanel.add(textToServerLabel);
        dialogVPanel.add(new HTML("<br><b>Servidor responde:</b>"));
        dialogVPanel.add(serverResponseLabel);
        dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
        dialogVPanel.add(closeButton);
        dialogBox.setWidget(dialogVPanel);

        // Inclua um manipulador para fechar o DialogBox
        closeButton.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                dialogBox.hide();
                sendButton.setEnabled(true);
                sendButton.setFocus(true);
            }
        });

        // Crie um manipulador para o sendButton e nameField class 
		MyHandler implements ClickHandler, KeyUpHandler {
            /**
             * Disparado quando o usuário clica no sendButton.
             */
            public void onClick(ClickEvent event) {
                sendNameToServer();
            }

            /**
             * Disparado quando o usuário digite no nameField.
             */
            public void onKeyUp(KeyUpEvent event) {
                if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
                    sendNameToServer();
                }
            }

            /**
             * Envie o nome do nameField para o servidor e aguarde uma resposta.
             */
            private void sendNameToServer() {
                sendButton.setEnabled(false);
                String textToServer = nameField.getText();
                textToServerLabel.setText(textToServer);
                serverResponseLabel.setText("");
                greetingService.greetServer(textToServer,
                        new AsyncCallback<String>() {
                            public void onFailure(Throwable caught) {
            // Mostre a mensagem de erro de RPC para a dialogBox do usuário
               .setText("Chamada de Procedimento Remoto - Falhou");
                                serverResponseLabel
                     .addStyleName("serverResponseLabelError");
                            serverResponseLabel.setHTML(SERVER_ERROR);
                                dialogBox.center();
                                closeButton.setFocus(true);
                            }

                            public void onSuccess(resultado da Cadeia) {
                           dialogBox.setText
						   ("Chamada de Procedimento Remoto"); 
						   serverResponseLabel
                             .removeStyleName("serverResponseLabelError");
                              serverResponseLabel.setHTML(resultado);
                              dialogBox.center();
                              closeButton.setFocus(true);
                            }
                        });
            }
        }

        // Inclua um manipulador para enviar o nome para o servidor 
		MyHandler handler = new MyHandler(); 
		sendButton.addClickHandler(handler);
        nameField.addKeyUpHandler(handler);
    }
}

O descritor de implementação da Web (web.xml, mostrado na Listagem 9) mapeia GreetingService como um recurso da Web baseado em servlet. Ele mapeia o servlet GreetingService sob o nome /simplegwtapp/greet para que o SimpleGWTApp possa carregá-lo e fazer chamadas para ele. O descritor de implementação da Web também denota que SimpleGWTApp.html é a página de boas-vindas para o aplicativo, assim ela sempre carrega.

Listagem 9. Descritor de implementação que configura GreetingServiceImpl (war/WEB-INF/web.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

  <!-- Página padrão para servidor -->
  <welcome-file-list>
    <welcome-file>SimpleGWTApp.html</welcome-file>
  </welcome-file-list>

  <!-- Servlets -->
  <servlet>
    <servlet-name>greetServlet</servlet-name>
    <servlet-class>gaej.example.server.GreetingServiceImpl</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>greetServlet</servlet-name>
    <url-pattern>/simplegwtapp/greet</url-pattern>
  </servlet-mapping>

</web-app>

O front end HTML é SimpleGWTApp.html, mostrado na Listagem 10. Esta é a página que carrega simplegwtapp.js e simplegwtapp.nocache.js, que é código JavaScript gerado pelo GWT a partir do seu código Java. Como mencionado anteriormente, este código vive no diretório src sob o pacote gaej.example.client (das Listagens 6, 7e 8).

Listagem 10. A página HTML que exibe a GUI do GWT (war/SimpleGWTApp.html)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- A declaração HTML 4.01 Transitional DOCTYPE-->
<!-- acima definida no topo do arquivo definirá     
--><!-- o mecanismo de renderização do navegador para-->
<!-- "Modo Quirks". 
Substituir esta declaração--> 
<!-- por um tipo de documento "Modo Standards" é suportado, -->
<!-- mas pode levar a algumas diferenças no layout.   -->

<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">

    <!--                                                               -->
    <!-- Considere inlining CSS para reduzir o número de arquivos pedidos -->
    <!--                                                               -->
    <link type="text/css" rel="stylesheet" href="SimpleGWTApp.css">

    <!--                                           -->
    <!-- Qualquer título está bem--> <!--                                           -->
    <title>Projeto Inicializador de Aplicativo da Web</title>
    <!--                                           -->
    <!-- Este script carrega seu módulo compilado.   -->
    <!-- Se você incluir qualquer meta tag do GWT, eles devem   -->
    <!-- ser incluídos antes desta linha.                -->
    <!--                                           -->
    <script type="text/javascript" language="javascript" 
  src="simplegwtapp/simplegwtapp.nocache.js"></script>
  </head>

  <!--                                           -->
  <!-- O corpo pode ter html arbitrário, ou      -->
  <!-- você pode deixar o corpo vazio se desejar-->
  <!-- para criar uma UI completamente dinâmica.        -->
  <!--                                           -->
  <body>

    <!-- OPCIONAL: inclua este se desejar suporte de histórico -->
    <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1'
  style="position:absolute;width:0;height:0;border:0"></iframe>

    <h1>Projeto Inicializador de Aplicativo da Web</h1>
    <table align="center">
      <tr>
        <td colspan="2" style="font-weight:bold;">Insira o seu nome:</td>
      </tr>
      <tr>
        <td id="nameFieldContainer"></td>
        <td id="sendButtonContainer"></td>
      </tr>
    </table>
  </body>
</html>

Com o GWT, você controla a aparência do seu aplicativo através do CSS, como demonstrado na Listagem 11:

Listagem 11. Folha de estilo para a GUI do GWT (war/SimpleGWTApp.css)
/** Inclua regras css aqui para o seu aplicativo. */


/** Regras de exemplo usadas pelo aplicativo de modelo 
(remover para o seu aplicativo) */ h1 { font-size: 2em;
  font-weight: bold;
  color: #777777;
  margin: 40px 0px 70px;
  text-align: center;
}

.sendButton {
  display: block;
  font-size: 16pt;
}

/** A maioria dos widgets do GWT já tem um nome de estilo definido */ .gwt-DialogBox {
  width: 400px;
}

.dialogVPanel {
  margin: 5px;
}

.serverResponseLabelError {
  color: red;
}

/** Defina IDs usando widget.getElement().setId("idOfElement") */
#closeButton {
  margin: 15px 6px 6px;
}

Implementando para Google App Engine

Depois de criar o próximo aplicativo killer do mundo (porque realmente precisamos de um aplicativo de saudação fácil e simples), vamos querer implementá-lo. A questão do uso do Google App Engine é que você pode implementar o seu aplicativo na infraestrutura sólida do Google, tornado-o fácil de escalar. O Google App Engine é projetado para fornecer uma plataforma para a construção de aplicativos escaláveis "que cresçam de um para milhões de usuários sem dores de cabeça de infraestrutura" (como declarado na página inicial do App Engine). Para usar esta infraestrutura, você precisa de um Google App Engine para conta Java.

Como muitas coisas na vida, a primeira vez é grátis. A versão gratuita do App Engine para Java fornece a um aplicativo implementado CPU, largura de banda e armazenamento suficientes para servir cerca de 5 milhões de visualizações de página. Além disso, é pago à medida que você progredir. (Também lembre-se que o que está disponível a partir desse texto é um preview release do App Engine para plataforma Java.)

Depois que você tiver a conta, deve ver uma lista vazia de aplicativos nosite do App Engine para Java. Clique no botão Criar Novo Aplicativo e um formulário como o da Figura 8 deve aparecer. Insira um nome de aplicativo exclusivo e uma descrição, e depois disso você verá uma mensagem de confirmação com o identificador do seu aplicativo.

O identificador também pertence ao arquivo app.yaml do seu aplicativo. Note que o identificador não pode ser alterado. Se você usar autenticação do Google para o seu aplicativo, "Artigo GAEj para Parte 1 de Rick" será exibido na páginas Conectar quando você acessar o seu aplicativo. Você usará gaejarticleforrick para implementar o aplicativo para o Google App Engine com o plug-in Eclipse do App Engine para Java.

Figura 8. Criando um novo aplicativo App Engine para Java
Criando um novo aplicativo App Engine para Java

Após configurar o ID do aplicativo, é possível implementar o seu aplicativo a partir do Eclipse. Primeiro, pressione o botão da barra de ferramentas que se parece com o logotipo do Google App Engine (um motor de jato com asas e cauda), mostrado na Figura 9:

Figura 9. Plug-in do Eclipse para o App Engine para Java
Plug-in do Eclipse para o App Engine para Java

Você pode precisar certificar-se de que o seu projeto App Engine para Java está selecionado antes de clicar em Implementar no diálogo mostrado na Figura 10. Suas credenciais do Google serão solicitadas, que são o seu endereço de e-mail e nome de usuário.

Figura 10. Implementando o projeto
Implementando o projeto

O diálogo na Figura 10 tem um link para "Configuração de Projeto do App Engine." Clique neste link (também acessível a partir do arquivo de configurações do projeto) e insira o ID do aplicativo (neste caso gaejarticleforrick), como mostrado na Figura 11. Após preencher o ID do aplicativo, clique emOKe depois emImplementar.

Figura 11. Configuração do projeto para o Google App Engine
Configuração do projeto para o Google App Engine

Após ter implementado o seu aplicativo, ele estará disponível emhttp://<application id>.appspot.com/. Também é possível ver o aplicativo em funcionamento emhttp://gaejarticleforrick.appspot.com/.

Conclusão

Isso conclui a Parte 1 de minha introdução ao Google App Engine para Java. Até aqui, você teve uma visão geral do que é o App Engine para Java e deu os primeiros passos no uso do Plug-in do Google para Eclipse do App Engine para Java. Você criou dois pequenos aplicativos inicializadores (um baseado em servlet e o outro baseado em GWT) e depois implementou o aplicativo GWT para a plataforma do Google App Engine.

Os exemplos até aqui demonstraram as ferramentas e funcionalidade que facilitam a criação e implementação de aplicativos baseados em Java que escalam — potencialmente até para o tamanho do YouTube ou Facebook. Na Parte 2você continuará a explorar as oportunidades disponíveis aos desenvolvedores em Java que trabalham no App Engine para Java. Afastando-se dos aplicativos de exemplo demonstrados neste artigo, você construirá um aplicativo de gerenciamento de contato customizado. Este aplicativo também será o núcleo dos exercícios na Parte 3, que se aprofunda no armazenamento de dados e front end da GUI do App Engine para Java.

Recursos

Aprender

Obter produtos e tecnologias

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Tecnologia Java, Software livre, Cloud computing
ArticleID=457465
ArticleTitle=Google App Engine para Java: Parte 1: Acelerar!
publish-date=12172009