Nesse post vou escrever um pouco sobre o Compilador do Google Web Toolkit, qual é o seu papel no kit, além de algumas dicas para o dia-a-dia no desenvolvimento com a tecnologia.
Como exemplo vou usar um novo Projeto Web no Eclipse criado a partir do Google Plugin para desenvolvimento GWT e/ou App Engine, acesse aqui mais informações e download.
Depois de instalar o plugin, dentro do Eclipse siga a sequência para criar o projeto:
New - Others - Google - Web Application Project - Defina o nome do projeto e a estrutura raiz de pacotes - Finish.
Vou adotar como nome do projeto appGWT e pacote br.com.globalcode. O plugin gera uma aplicativo pronto que permite ao usuário preencher um campo e realizar o envio ao servidor de forma assíncrona (Ajax), quando o servidor responde um Dialog é apresentado com a mensagem de retorno. Para testar a aplicação é só executar o projeto com a opção Wep Application. Veja:
O GWT, como já foi comentado, adota um conceito bem interessante para construir sofisticadas soluções web (RIA) usando Java nas camadas Client/View (Browser) e Server. Repare na estrutura de nosso aplicativo exemplo, as classes dentro do pacote br.com.globalcode.client são transformadas em JavaScript, enquanto dentro de br.com.globalcode.server o conteúdo permanece em Java rodando dentro do web-server.
Essa transformação é possível através do Compilador do GWT, que diferente do javac, transforma/traduz o código da camada Client escrito em Java para JavaScript. Além dessa transformação o GWT também otimiza o código gerado, removendo método que nunca é usado ou que sempre retorna o mesmo valor.
Para analisarmos um pouco de como o Compilador se comporta, podemos escrever o seguinte código na classe AppGWT.java:
/**
* Entry point classes define onModuleLoad().
*/
public class AppGWT implements EntryPoint {
...public String getTextoPadrao() {
return "Testando GWT";
}
public void onModuleLoad() {
final Button sendButton = new Button("Send");
final TextBox nameField = new TextBox();
nameField.setText(getTextoPadrao());
...
}
...
}
AppGWT.java é o ponto de entrada (EntryPoint) da aplicação, ou seja, o código executado quando o usuário acessa a página.
Agora é só compilar! Por padrão o código JavaScript gerado é compactado e ofuscado, inviabilizando a analise. Durante o desenvolvimento pode ser interessante ler o conteúdo JavaScript, por isso é possível indicar ao compilador que a geração do código deve ser em um formato legível. [Importante: Esse recurso deve ser usado somente durante o desenvolvimento]
Com botão direito do mouse sob o nome do projeto selecione Google - GWT Compile - modifique o Output Style de Obfuscated para Pretty - Clique em Compile. Veja:
O conteúdo gerado pelo compilador GWT fica dentro da pasta /war/appgwt . Após o compilador encerrar a execução, atualize o conteúdo da pasta war e verifique os arquivos gerados. O código JavaScript de startup fica no arquivo appgwt.nocache.js, comum a todos os Navegadores ("userAgent"). O GWT também gera alguns arquivos html - extensão .cache.html - com o JavaScript gerado a partir do Java, cada arquivo com conteúdo suportado por um Navegador .
No arquivo appgwt.nocache.js temos o seguinte trecho:
...
if (!strongName) {
try {
unflattenKeylistIntoAnswers(['safari'], '2B012280038ECE4F899173361F1A5AEF.cache.html');
unflattenKeylistIntoAnswers(['opera'], '16C2FF59D1A299AD6194A71D9D33861F.cache.html');
unflattenKeylistIntoAnswers(['gecko'], '578F90996AD9305BA987E10AF37C8645.cache.html');
unflattenKeylistIntoAnswers(['gecko1_8'], 'B6DDD0AD31CB650064F7B6DC35EBE762.cache.html');
unflattenKeylistIntoAnswers(['ie6'], 'C46730CF80EA3F49ED2C299E016471DF.cache.html');
strongName = answers[computePropValue('user.agent')];
}
catch (e) {
return;
}
}
...
Nesse pedaço é feito o mapeamento do Navegador e o seu arquivo .cache.html correspondente. Todo esse mecanismo é chamado de Deffered Binding, com ele o GWT resolve as incompatibilidades de JavaScript com hacks e workarounds (jeito mais elegante de dizer gambiarra) para cada navegador. O Deferred Binding seria uma alternativa para Reflection suportada no Java, o detalhe que esse vinculo ou ligação é feito estaticamente, já que o ambiente JavaScript não suporta Dynamic Class Loading.
Uma curiosidade, o GWT nomeia os arquivos .cache.html usando um MD5 sum de acordo com o conteúdo Java, no caso do Firefox (gecko1_8) o arquivo é B6DDD0AD31CB650064F7B6DC35EBE7 62.cache.html. Abra esse arquivo e veja o seguinte trecho:
...
var _;
function equals_2(other){
return this === (other == null?null:other);
}
function hashCode_4(){
return this.$H || (this.$H = ++sNextHashId);
}
function Object_0(){
}
_ = Object_0.prototype = {};
_.equals$ = equals_2;
_.hashCode$ = hashCode_4;
_.typeMarker$ = nullMethod;
_.typeId$ = 1;
function $AppGWT(this$static){
this$static.greetingService = $GreetingService_Proxy(new GreetingService_Proxy());
return this$static;
}
function $onModuleLoad(this$static){
var closeButton, dialogBox, dialogVPanel, handler, nameField, sendButton, serverResponseLabel, textToServerLabel;
sendButton = $Button_0(new Button(), 'Send');
nameField = $TextBox(new TextBox());
nameField.element['value'] = 'Testando GWT !' != null?'Testando GWT !':'';
setStyleName(sendButton.element, 'sendButton', true);
$add(get_0('nameFieldContainer'), nameField);
$add(get_0('sendButtonContainer'), sendButton);
$setFocus(nameField, true);
$selectAll(nameField);
...
}
...
Essa é a tradução do método onModuleLoad() da classe AppGWT, mas repare que o compilador não considerou o método getTextoPadrao(), passando o conteúdo 'Testando GWT' na property do input. Se você achou esse código JavaScript complexo e dificil compile novamente a aplicação no estilo Obfuscated e experimente visualizar os fontes! Ainda bem que no dia-a-dia não precisamos nos preocupar com isso, a proposta é justamente deixar o JavaScript por conta do GWT.
Um outro detalhe da compilação é que o GWT organiza código Java no modelo AST (Abstract Syntax Tree), aonde cada elemento sintático do código é um objeto (nó) Java na árvore, Podemos fazer uma breve comparação desse modelo de organização ao DOM (Document Object Model).
O processo de compilação ainda é caro por isso o GWT disponibiliza o Hosted Mode, que permite economizar um bom tempo além deixar a construção e manutenção mais produtiva. O Hosted Mode emula código Java como JavaScript sem realizar a compilação.
Durante o desenvolvimento uma dica que pode agilizar a compilação seria gerar JavaScript para um navegador, o Firefox por exemplo. Podemos indicar isso ao GWT com a seguinte linha no arquivo de configurações do projeto, AppGWT.gwt.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.7.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.7.0/distro-source/core/src/gwt-module.dtd"> <module rename-to='appgwt'> ... <define-property name="user.agent" values="gecko1_8" /> ... </module>
A Globalcode disponibiliza um mini-curso sobre GWT, o MC56, não perca!
Eder Magalhães
http://twitter.com/edermag
http://www.yaw.com.br
Eder Magalhães
http://twitter.com/edermag
http://www.yaw.com.br



Comentários
Estou até assustado. Hahahaha.
Acho q nao entendi a coisa mas me parece q o codigo continua aberto e nao compilado.
Eu escondia os jss codificando mais uns 4 a 5 um chamando o outro.
Adoro Javascript e nao entendo por q ainda nao hesiste compilador pra ele. Buáááá
Tenho progs incríveis em JS.
Abraços, fui.
Paschoal, Vila Velha, Esp. Santo.