Eu acredito que boa parte de vocês já viu os demos do GWT na sua página oficial, ficou encantado, baixou o GWT, rodou os samples, criou um projeto simples, fez passo-a-passo algum tutorial “Hello World” e ficou mais encantado ainda.
Porém “o mundo é cruel”, e quando nós caÃmos no mundo real e tentamos desenvolver uma aplicação mais robusta do que um Hello World nos deparamos com alguns problemas um pouco mais complicados.
Vou tentar escrever alguns posts falando de algumas experiências que eu tive com GWT, os problemas que surgiram e como eu resolvi estes problemas.
O primeiro problema que eu tive foi quando tentei utilizar uma biblioteca javascript pré-existente, ou quando eu tentei utilizar alguma funcionalidade que há nos objetos providos pelos browser via javascript (window, document, etc) mas está implementada nos mesmos objetos no nÃvel GWT.
A forma que encontrei para resolver este (e mais um monte de problemas) foi utilizar JSNI – Java Script Native Interface. JSNI está para GWT assim como JNI (Java Native Interface) está para Java. Com JSNI é possÃvel implementar o corpo de métodos GWT utilizando Java Script.
Vejamos um exemplo. Vamos supor que, por alguma razão esquisita, eu queira escrever um método que faça o mesmo que o Window.alert. Vamos chamar este método de meuAlert:
[java]
public native void meuAlert(String mensagem) /*-{
alert(mensagem);
}-*/;
[/java]
Apesar de este não ser um exemplo muito funcional (na realidade ele não é funcional de jeito nenhum) dá pra entender a “mecânica da coisa”. Todo método JSNI deve ser declarado como native (assim como métodos cuja implementação será feita em JNI, utilizando Java convencional). A implementação do método deve vir em um bloco comentado localizado entre o fim da lista de parâmetros do método e o seu ponto-e-vÃrgula. O bloco de código JSNI é delimitado por “-{” e “}-”, desta forma o tradutor Java/Java Script do GWT irá saber que este bloco de comentários trata-se na realidade de instruções Java Script.
Vimos como fazer chamadas do lado Java para Java Script, vamos ver agora como fazer o caminho contrário, chamar métodos Java de dentro de código JSNI.
Para isto, basta chamar o método de qualquer classe seguindo a convenção:
[instância.]@nomeDaClasseCompleto::nomeDoMetodo(assinaturaDosParametros)(argumentos)
Onde:
- instância (atributo opcional) – Referente a instância da qual o método será chamado, caso não seja informada uma instância, será assumido que a chamada será feita de forma estática;
- nomeDaClasseCompleto – “full qualified class name”, ou seja, o nome da classe completo (toda a árvore de pacotes seguido do nome da classe);
- nomeDoMetodo – Nome do método que será chamado;
- assinaturaDosParametros – Assinatura dos parâmetros no formato JNI;
- argumentos – Lista de valores passados como parâmetros para o método.
Vamos fazer outro exemplo simples:
[java]
package br.com.gwt.client;
public class TesteJSNI {
public void exibeMensagem(String nome, int idade) {
Window.alert(”nome: ” + nome + ” – idade: ” + idade);
}
public native void callJavaMethod(TesteJSNI teste, String nome, int idade) /*- {
teste@br.com.gwt.client.TesteJSNI::exibeMensagem(Ljava/lang/String;I)(nome, idade);
}-*/;
}
[/java]
Por fim, JSNI define dois objetos implÃcitos $wnd e $doc, que nos permitem, respectivamente acessar os contextos da janela e do documento principais. Estes objetos são importantes pois, como o código GWT é executado em um iframe oculto, se você tentar utilizar window e document diretamente, você não irá acessar a janela e o documento principais, mas sim do iframe oculto do GWT. Outro motivo, é que estes objetos devem ser utilizados quando se quiser criar funções nomeadas que o programador queira chamar posteriormente em um outro ponto do código. A razão para isto é que o código gerado pelo GWT é ofuscado, então, qualquer nome de função atribuÃdo diretamente via JSNI será ofuscado, tornando impossÃvel de “adivinhar” qual será esse nome em tempo de compilação.
Vamos a alguns exemplos:
Definição de uma função:
[java]
public native void criaFuncao() /*{-
$wnd[meuAlert] = function() {
$wnd.alert(’Teste’);
}-}*/;
public native void chamaFuncao() /*-{
$wnd[meuAlert]();
}-*/;
[/java]
Adicionando um listener ao documento:
[java]
public void trackMousePosition() /*-{
$doc.addMouseMoveListener(function(evt) {
$wnd.title = ‘x: ‘ + evt.x + ‘ – y: ‘ + evt.y;
});
}-*/;
[/java]
Por enquanto é só. No próximo post eu vou mostrar como se faz uma invocação JSONP utilizando os conceitos mostrados aqui.
One Response to “JSNI – Java Script Native Interface”
Leave a Reply
You must be logged in to post a comment.
Março 6th, 2008 at 12:14:54
Fala Bruno blzs! Gostei muito dos tutoriais sobre javascript nativo, e a maneira de integrá-lo com GWT, até então não conhecia essa possibilidade. Só estou com algumas dúvidas em JSONP, mas já postei lá, espero que você possa me ajudar que sou macaco novo no assunto.
PS.: Vou tirar o email do kara da minha página ahuahu
, vlw a dica, eu havia copiado meu CV diretamente lá, daí o email foi junto.