Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Primi passi con Google Web Toolkit ed Eclipse

Scrivere codice Ajax direttamente in Java
Scrivere codice Ajax direttamente in Java
Link copiato negli appunti

Le attuali applicazioni Web (2.0 si intende), sono ricche di funzioni lato client e relativo codice JavaScript da scrivere. L'aumento di complessità fa aumentare anche la probabilità di errore e può rallentare la produttività degli sviluppatori. Inoltre bisogna sempre tener conto della compatibilità cross-browser. Fortunatamente esistono alcuni framework che ci permettono di aggirare molti di questi problemi.

Il Google Web Toolkit (GWT), è un framework open source, sviluppato dalla Google, che permette di creare applicazioni Web con AJAX, scrivendo le proprie pagine esclusivamente in linguaggio JAVA. Sarà compito della libreria GWT tradurre il codice Java e produrre le pagine HTML e JavaScript corrispondenti.

Possiamo scaricare il toolkit dal sito ufficiale del progetto dove, per rendere il tutto ancora più semplice, Google ha messo a disposizione anche plugin per Eclipse.

In questo articolo, installeremo il plugin e realizzeremo la classica applicazione "Hello World" per iniziare a prendere familiarità con il framework.

Installare il plugin su Eclipse

L'installazione del plugin è molto semplice. Dal menu Help di Eclipse (Ganymede), selezioniamo la voce Software Updates....

Figura 1. Software Updates di Eclipse
Software Updates di Eclipse

Nella finestra che appare, selezioniamo la tab Available Software e clicchiamo sul pulsante Add Site. Quindi aggiungiamo l'URL:

URL del Google Web Toolkit per Eclipse 3.4 (Ganymede)

http://dl.google.com/eclipse/plugin/3.4
Figura 2. Inserire il nuovo sito per gli aggiornamenti
Inserire il nuovo sito per gli aggiornamenti

È disponibile anche la versione del plugin per Eclipse 3.3 (Europa) all'URL:

URL del Google Web Toolkit per Eclipse 3.3 (Europa)

http://dl.google.com/eclipse/plugin/3.3

Una volta aggiunto il sito, possiamo selezionare il plugin e l'SDK nell'elenco degli aggiornamenti disponibili e cliccare su Install per dare il via all'installazione. È consigliato scaricare, oltre al plugin e all'SDK, anche l'application engine. Questo componente non è fondamentale, ma torna utile per testare l'applicazione.

Figura 3. Installare il plugin e l'SDK
Installare il plugin e l'SDK

Una volta scaricato ed installato il tutto, è necessario riavviare l'ambiente per rendere attive le modifiche. Al riavvio, noteremo un nuovo gruppo di icone nella barra degli strumenti.

Figura 4. Nuove icone sulla barra degli strumenti
Nuove icone sulla barra degli strumenti

Creare un progetto

Per creare il nostro primo progetto GWT, clicchiamo sulla prima dell nuove icone (New Web Application Project).

Assegniamo un nome al progetto (HtmlExample) e stabiliamo un package di riferimento (it.html). La sezione Google SDKs, permette di selezionare la versione GWT da utilizzare e l'application Engine con il quale testare il nostro applicativo. Lasciamo invariate tali opzioni e confermiamo con il tasto Finish.

Figura 5. Creare un progetto
Creare un progetto

GWT genererà la struttura del nostro progetto, tralasciamo per un attimo i dettagli e vediamo come testare l'applicazione appena creata. Nella barra degli strumenti dobbiamo ancora esplorare le due icone:

  • GWT Compile, che permette di compilare l'applicazione e generare il codice HTML+JavaScript corrispondente
  • Deploy to App Engine, che permette di effettuare il deploy dell'applicativo all'interno dell'application Engine di Google

Le applicazioni sviluppate mediante Google Web Toolkit possono essere eseguite in due modalità differenti: Hosted mode e Web mode.

Mediante la modalità Hosted mode, l'applicazione viene lanciata come bytecode Java all'interno della Java Virtual Machine. In questa modalità, sono utilizzabili tutti gli strumenti di debug disponibili nell'ambiente di sviluppo. Come supporto alla modalità Hosted Mode, GWT fornisce uno speciale Browser Web.

Mediante la modalità Web mode, invece, l'applicazione viene eseguita come una classica applicazione Web. Il compilatore GWT (Java-to-JavaScript) genera il codice HTML e JavaScript, interpretabile dal browser Web.

Per eseguire la nostra applicazione in hosted mode, clicchiamo col tasto destro sul nome del progetto, poi sulla voce Run As > Web Application.

Figura 6. Lanciare l'applicazione
Lanciare l'applicazione

Eclipse visualizzerà due nuove finestre: la prima rappresenta la console dell'application engine di google (l'analogo di Tomcat o Jboss), mentre la seconda è il browser di Google nel quale possiamo ammirare la nostra Web application, costituita da una classica pagina contenente un semplicissimo campo di testo. Inserendo il proprio nome e cliccando sul tastino Send, viene visualizzato un semplice messaggio di notifica.

Ora che abbiamo visto il risultato finale, facciamo un passo indietro, e analizziamo le singole classi che hanno prodotto questo risultato.

Uno sguardo al codice

Il progetto è suddiviso in due package: it.html.client e it.html.server. Il package client contiene tre classi: HtmlExample, GreetingService e GreetingServiceAsync. Il package server contiene un'unica classe: GreetingServiceImpl.

Figura 7. Struttura del progetto
Struttura del progetto

La classe principale è it.html.client.HtmlExample che implementa l'interfaccia com.google.gwt.core.client.EntryPoint. L'unico metodo definito dall'interfaccia, è onModuleLoad. Questo metodo viene richiamato dal framework nel momento in cui la pagina viene caricata. In questo metodo, con una filosofia simile a quella che si utilizza per le applicazioni swing, viene creata la struttura di quella che sarà la pagina HTML corrispondente.

Analizziamo il metodo riga per riga:

package it.html.client;

import com.google.gwt.core.client.EntryPoint;
/* saltiamo gli altri 'import' */

public class HtmlExample implements EntryPoint 
{
  private static final String SERVER_ERROR = "An error occurred ... bla bla";
  
  private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
  
  public void onModuleLoad()
  {
    // crea il bottone Send e gli assegna uno stile
    final Button sendButton = new Button("Send");
    sendButton.addStyleName("sendButton");
    
    // crea un campo di testo e ne inizializza il contenuto
    final TextBox nameField = new TextBox();
    nameField.setText("GWT User");
    
    // aggiunge i due elementi precedenti alla pagina
    RootPanel.get("nameFieldContainer").add(nameField);
    RootPanel.get("sendButtonContainer").add(sendButton);
    
    // assegna il focus al campo di testo
    nameField.setFocus(true);
    nameField.selectAll();
    
    // crea una finestra di dialogo
    final DialogBox dialogBox = new DialogBox();
    dialogBox.setText("Remote Procedure Call");
    
    // la finestra viene resa trascinabile
    dialogBox.setAnimationEnabled(true);
    
    // crea un bottone Close e gli assengna un id
    final Button closeButton = new Button("Close");
    closeButton.getElement().setId("closeButton");
    
    // crea una label
    final Label textToServerLabel = new Label();
    
    // crea una label contenente una stringa HTML
    final HTML serverResponseLabel = new HTML();
    
    // creazione di un pannello al quale, oltre ad una stringa di testo,
    // vengono aggiunte le due label create precedentemente
    VerticalPanel dialogVPanel = new VerticalPanel();
    dialogVPanel.addStyleName("dialogVPanel");
    dialogVPanel.add(new HTML("<strong>Sending name to the server:</strong>"));
    dialogVPanel.add(textToServerLabel);
    dialogVPanel.add(new HTML("<br /><strong>Server replies:</strong>"));
    dialogVPanel.add(serverResponseLabel);
    
    dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
    
    // il bottone viene aggiunto al pannello
    dialogVPanel.add(closeButton);
    
    // il pannello viene aggiunto alla finestra di dialogo
    dialogBox.setWidget(dialogVPanel);
    
    // viene assegnato un handler di tipo click al bottone Close
    closeButton.addClickHandler(new ClickHandler() 
    {
      public void onClick(ClickEvent event)
      {
        //nasconde la finestra di dialogo
        dialogBox.hide();
        
        //abilita il bottone Send e gli viene assegnato il focus
        sendButton.setEnabled(true);
        sendButton.setFocus(true);
      }
    });
    
    // creazione di un handler di tipo click o keyUp
    class MyHandler implements ClickHandler, KeyUpHandler
    {
      // metodo richiamato in seguito ad un evento di tipo click
      public void onClick(ClickEvent event)
      {
        sendNameToServer();
      }
      
      // metodo richiamato in seguito ad un evento di tipo key up
      public void onKeyUp(KeyUpEvent event)
      {
        // soltanto in caso in cui il comando inviato è di tipo enter
        if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER)
        {
          sendNameToServer();
        }
      }
      
      private void sendNameToServer()
      {
        // il bottone Send viene disabilitato
        sendButton.setEnabled(false);
        
        // viene letto il valore del campo di testo
        String textToServer = nameField.getText();
        
        // assegnazione del valore alla label
        textToServerLabel.setText(textToServer);
        
        serverResponseLabel.setText("");
        
        greetingService.greetServer(textToServer, new AsyncCallback<String>()
        {
          // questo metodo viene richiamato nel caso in cui la chiamata va in errore
          public void onFailure(Throwable caught)
          {
            // viene abilitata la finestra di dialogo precedentemente definita
            dialogBox.setText("Remote Procedure Call - Failure");
            serverResponseLabel.addStyleName("serverResponseLabelError");
            
            // nella finestra di dialogo viene stampato il messaggio di errore
            serverResponseLabel.setHTML(SERVER_ERROR);
            dialogBox.center();
            closeButton.setFocus(true);
          }
          
          // questo metodo viene richiamato nel caso in cui la chiamata va a buon fine
          
          public void onSuccess(String result)
          {
            // viene abilitata la finestra di dialogo precedentemente definita
            dialogBox.setText("Remote Procedure Call");
            serverResponseLabel.removeStyleName("serverResponseLabelError");
            
            // nella finestra di dialogo viene stampato un messaggio contenente
            // il valore inserito dall'utente nel campo di testo
            serverResponseLabel.setHTML(result);
            dialogBox.center();
            closeButton.setFocus(true);
          }
        });
      }
    }
    
    // viene associato al bottone send e al comando ENTER l'handler precedentemente definito
    MyHandler handler = new MyHandler();
    sendButton.addClickHandler(handler);
    nameField.addKeyUpHandler(handler);
  }
}

Il passaggio principale, sul quale vale la pena soffermarci, è costituito dalla chiamata:

greetingService.greetServer(...)

Per capire meglio il funzionamento, però, è necessario analizzare prima le altre classi e interfacce necessarie all'applicazione, ad esempio il servizio che consumiamo:

public interface GreetingService extends RemoteService 
{
  String greetServer(String name);
}
public interface GreetingServiceAsync 
{
  void greetServer(String input, AsyncCallback<String> callback);
}
public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService 
{
  public String greetServer(String input)
  {
    String serverInfo = getServletContext().getServerInfo();
    String userAgent = getThreadLocalRequest().getHeader("User-Agent");
    return "Hello, " + input + "!<br /><br />I am running " + serverInfo
           + ".<br /><br />It looks like you are using:<br />" + userAgent;
	}
}

L'interfaccia GreetingService estende l'interfaccia RemoteService, e contiene il metodo utilizzato per inviare la richiesta al server. L'unico parametro di ingresso è rappresentato dalla stringa inserita nel campo di testo dall'utente.

L'interfaccia GreetingServiceAsync definisce un metodo analogo al precedente ma, ha come secondo parametro di ingresso, una classe di tipo AsyncCallback<String> che rappresenta la funzione di ritorno.

La classe GreetingServiceImpl estende la classe RemoteServiceServlet ed implementa l'interfaccia GreetingService.

Il metodo greetServer di questa classe, riceve il testo inserito nel campo di testo dall'utente, e restituisce un'altra stringa contenente alcune informazioni sul server e sul browser utilizzato. Inoltre viene aggiunto il classico messaggio di benvenuto con il nome dell'utente.

Facciamo un passo indietro ed analizziamo la seguente riga di codice del metodo onModuleLoad:

greetingService.greetServer(textToServer, new AsyncCallback<String>()...

greetingService è una variabile d‘istanza della classe HtmlExample che viene inizializzata nel seguente modo:

private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);

L'unico metodo a nostra disposizione è, naturalmente, quello definito nell'interfaccia GreetingServiceAsync. Questo metodo riceve in ingresso, come detto in precedenza, una stringa e un'istanza della classe AsyncCallback.

Effettivamente AsyncCallback è un'interfaccia nella quale sono definiti i due seguenti metodi:

  • void onFailure (java.lang.Throwable caught) che viene invocato nel caso in cui la chiamata asincrona fallisce
  • void onSuccess (T result) che viene invocato nel caso in cui l'elaborazione va a buon fine. La variabile result rappresenta l'oggetto di ritorno della chiamata effettuata. Nel nostro caso, la variabile result, è la stringa contenente il messaggio di benvenuto

Compilare il progetto

Nella prima parte dell'articolo abbiamo realizzato il nostro applicativo e lo abbiamo testato in modalità hosted mode. Ora vediamo come compilare il progetto utilizzando il compilatore GWT.

Clicchiamo sull'icona rossa presente nella toolbar di eclipse.

Figura 8. Icona del compilatore GTW
Icona del compilatore GTW

L'IDE dovrebbe aver impostato già tutti i parametri per la compilazione, ma possiamo comunqu selezionare, attraverso il classico tastino Browse (sfoglia), il progetto da compilare, il livello di log da utilizzare e lo stile di output del log (Obfuscated, Pretty oppure Detailed).

Figura 9. Impostazioni di compilazione
Impostazioni di compilazione

Durante la fase di compilazione, il compilatore GWT traduce il codice Java in HTML e JavaScript, compatibile con tutti i browser attualmente disponibili.

Le applicazioni scritte in GWT, risultano sicuramente più performanti, rispetto ad un'applicazione Ajax sviluppata manualmente, poiché il compilatore GWT, durante la fase di generazione del codice JavaScript, sfrutta al massimo le funzionalità che ogni singolo browser implementa nativamente.

Il risultato della compilazione è disponibile nella cartella war del nostro progetto. In questa cartella troviamo tutti i file necessari per il deploy dell'applicazione, in un qualsiasi Web server Java:

  • il descrittore web.xml
  • le librerie gwt
  • il file di configurazione log4j
  • tutti i file HTML e JavaScript

Unica cosa da osservare, per il momento, è il file XML, nel quale viene definita la Servlet greetServlet. Questa Servlet verrà interrogata dalle funzioni JavSscript generate da GWT, mediante richieste asincrone, tipiche di Ajax.

<?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>

  <welcome-file-list>
    <welcome-file>HtmlExample.html</welcome-file>
  </welcome-file-list>
  
  <servlet>
    <servlet-name>greetServlet</servlet-name>
    <servlet-class>
      it.html.server.GreetingServiceImpl
    </servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>greetServlet</servlet-name>
    <url-pattern>/htmlexample/greet</url-pattern>
  </servlet-mapping>

</web-app>

Tralasciamo il resto del contenuto della cartella war, rinominiamola in HtmlExample, e copiamola nella cartella webapps di Tomcat. Avviamo il nostro Web server e carichiamo l'applicazione all'indirizzo http://localhost:8080/HtmlExample.

Come possiamo vedere, l'applicazione è praticamente identica a quella che abbiamo eseguita in modalità hosted mode. Adesso però, stiamo eseguendo la nostra applicazione direttamente nel browser, quindi stiamo eseguendo esclusivamente codice HTML e JavaScript.

Traduciamo la nostra applicazione in termini tecnici. Nel momento in cui l'utente connesso clicca sul tastino Send, viene invocata una funzione JavaScript che invoca, in modo asincrono, la greetServlet. Il messaggio di ritorno viene intercettato e stampato in una classica finestra di output. Quando l'utente clicca sul tasto close di questa finestra, viene invocata un'altra funzione javascript che nasconde la finestra.

Scrivere un'applicazione utilizzando il framework Google Web Toolkit, è molto semplice. Non occorre avere particolari conoscenze di HTML o JavaScript ma esclusivamente codice java. Questo rende il tutto molto semplice e manutenibile. Naturalmente gli strumenti messi a disposizione del tool sono diversi. In questo articolo ci siamo limitati a mostrare esclusivamente il risultato finale e cercare di far capire la potenzialità del framewoork.

Ti consigliamo anche