Yagwto
Upcoming SlideShare
Loading in...5
×
 

Yagwto

on

  • 2,409 views

by Davide Cerbo e Stefano Linguerri...

by Davide Cerbo e Stefano Linguerri

La programmazione web sta facendo passi da gigante e oggi l’utente si aspetta che l’esperienza di utilizzo si avvicini sempre di più a quella a cui è abituato nei classici applicativi desktop. Il mondo degli sviluppatori ha risposto inventanto una nuova sigla: RIA, cioè Rich Internet Application. Google non è stata a guardare e ha fornito la sua risposta a questa esigenza donando alla community Google Web Toolkit. Questo nuovo framework permette di sviluppare in Java tutta l’interfaccia utente per poi ottenere un codice javascript che funzionerà su qualsiasi browser web senza l’installazione di plugin aggiuntivi. In questa presentazione vedremo:

* perchè sviluppare applicazioni RIA
* perchè usare GWT
* come GWT utilizza AJAX per comunicare con il server
* le ottimizzazione che avremo utilizzando GWT
* come uscire dal browser con Google Gear e Mozilla Prism
* e non solo…

Statistics

Views

Total Views
2,409
Views on SlideShare
2,396
Embed Views
13

Actions

Likes
2
Downloads
18
Comments
0

2 Embeds 13

http://www.jugroma.it 11
http://www.slideshare.net 2

Accessibility

Categories

Upload Details

Uploaded via as OpenOffice

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Yagwto Yagwto Presentation Transcript

  • YA GWT O GOOGLE WEB TOOLKIT
  • YA GWT O GOOGLE WEB TOOLKIT
  • RIA? RICH INTERNET APPLICATION UNA NUOVA USER EXPERIENCE!
  • Problematiche Gli sviluppatori possono impiegare anche il 90% del loro tempo per:
      • problemi di compatibilità tra i browser
      • mantenere molto codice Javascript
      • gestire il ciclo di vita del software
      • utilizzare correttamente AJAX
  • La risposta è GWT Cosa non saranno più nostre preoccupazioni?
      • incompatibilità tra i browser
      • gestione corretta della history del browser
      • localizzazione senza refresh della pagina
      • offuscamento del codice
      • riduzione del codice
      • image bundle
      in poche parole OTTIMIZZAZIONE
  • GWT = JAVA TO JAVASCRIPT Perchè Java? Una sola risposta: TOOL
  • GWT contro tutti VS.
  • Hello JUG! applicationCreator it.pronetics.gwt. client .HelloJUGApp  
  • Moduli *.gwt.xml In GWT è possibile definire dei moduli . Ogni modulo è configurato in un file con estensione: gwt.xml     < module >     < inherits name =&quot;com.google.gwt.user.User&quot;/>     < entry-point class =&quot;com.example.foo.MyModule&quot;/>  </ module >   Qui definiamo l'entry-point MyModule che sarà il &quot;main&quot; del nostro applicativo
  • Tags *.gwt.xml <inherits name=&quot;logical-module-name&quot; /> : Per importare altri moduli   <entry-point class=&quot;classname&quot; /> : La classe entry point dell'applicazione   <source path=&quot;path&quot; //> : Definisce in quale package riesodo i sorgenti della parte client, per default il package è client <public path=&quot;path&quot;/> : Il percorso dove risiedono le componenti statiche e componenti di terze parti (javascript, html, immagini, etc, etc).   <servlet path=&quot;url-path&quot; class=&quot;classname&quot;/> : Definisce il componente lato server per le chiamate RPC.   <script src=&quot;js-url&quot;/>,<stylesheet src=&quot;css-url&quot;/> : Per includere javascript e css   <extend-property name=&quot;client-property-name&quot; values=&quot;comma-separated-values&quot;/> : Per aggiungere delle proprietà
  • Creare moduli esterni
      • I moduli esterni stanno a GWT   come le librerie a Java
      • Hanno in comune l'estensione JAR
      • Il nostro progetto li può includere tramite il tag inherits . Nelle prossime slide useremo:
        • <inherits name=&quot;com.google.gwt.json.JSON&quot; />
        • <inherits name=&quot;com.google.gwt.http.HTTP&quot; />
      • Il jar deve avere la seguente struttura :
        • it/pronetics/module/Test.gwt.xml
        • it/pronetics/module/client/.../*.java
        • it/pronetics/module/client/.../*.class
      • il package client è obbligatorio, se ne usiamo uno diverso lo dobbiamo specificare tramite il tag source :
        • <source path=&quot;util&quot; />
  • EntryPoint
      • Le classi definite come EntryPoint devono implementare l'omonima interfaccia e definire il metodo public void onModuleLoad() Questo è il metodo che viene invocato quando viene richiesta la url dell'entry point dell'applicazione per la prima volta.
      • RootPanel rappresenta, nella pagina, il contenitore di più alto livello (body html o un elemento div da noi definito). Per aggiungere elementi a RootPanel è sufficente chiamare:
           RootPanel.get().add(myPanel);
  • Vi ricordate Swing?
  • Hello JUG! ./HelloJUG-shell
  • Ecco il codice!   public void onModuleLoad() { Image img = new Image( &quot;http://code.google.com/webtoolkit/logo-185x175.png&quot; ); Button button = new Button( &quot;Click me&quot; ); ... VerticalPanel vPanel = new VerticalPanel(); ... vPanel.add(button); // Add image and button to the RootPanel RootPanel.get().add(vPanel); // Create the dialog box final DialogBox dialogBox = new DialogBox(); dialogBox.setText( &quot;Welcome to GWT!&quot; ); dialogBox.setAnimationEnabled(true); Button closeButton = new Button( &quot;close&quot; ); VerticalPanel dialogVPanel = new VerticalPanel(); ... closeButton.addClickListener( new ClickListener() { public void onClick(Widget sender) { dialogBox.hide(); } }); dialogBox.setWidget(dialogVPanel); button.addClickListener( new ClickListener() { public void onClick(Widget sender) { dialogBox.center(); dialogBox.show(); } }); } }
  • Architettura classica
  • Remote Procedure Call Una Remote Procedure Call è una funzione implementata lato server invocata dal client.   GWT RPC NON è la stessa tecnologia su cui sono basati i web services SOAP o REST .
  • RPC gwt.xml   Nel nostro file gwt.xml dovremmo configurare la classe che implementa il servizio lato server.   Dobbiamo mappare inoltre anche la path alla quale tale implementazione risponderà   ... <servlet path=&quot; /countVisitors &quot;  class=&quot; it.jk.server.VisitorsCountServiceImpl &quot;/> ...
  • RPC diagrama del'interazione Cosa ci serve?
    • L'interfaccia del servizio MyService
    • L'interfaccia MyServiceAsync
    • L'implementazione lato server MyServiceImpl
  • RPC interfaccie package it.jk.client; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;   @RemoteServiceRelativePath(&quot;countVisitors&quot;) public interface VisitorsCountService extends RemoteService {     public String getVisitors (String name); } package it.jk.client; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; import com.google.gwt.user.client.rpc.AsyncCallback; public interface VisitorsCountServiceAsync {     void getVisitors (String name, AsyncCallback async); }
  • RPC Server package it.jk.server; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import it.jk.client.VisitorsCountService; @RemoteServiceRelativePath(&quot;countVisitors&quot;) public class VisitorsCountServiceImpl extends RemoteServiceServlet implements VisitorsCountService {     public String getVisitors (String name) {         VISITORS++;         return &quot;Ciao &quot; + name + &quot; è il click numero &quot; + VISITORS;     }     private static int VISITORS = 0; }
  • RPC Client private void getVisitorInfo(String userName) {         // Iniziallizza il proxy per il servizio         if (visitorCountService == null) {             visitorCountService = GWT.create(VisitorsCountService.class) ;         }         // Prepara l'ogetto per la callback         AsyncCallback <String> callback = new AsyncCallback <String>() {             public void onFailure(Throwable caught) {                 // TODO: Gestione errore             }             public void onSuccess(String result) {                 salutoLabel.setText(result);             }         };         // Chiama il metodo per sapere quante visite ci sono state         visitorCountService.getVisitors(userName, callback);     }
  • Screenshot esempio RPC  
  • Maven?   Archetype per la generazione del progetto mvn archetype:create -DarchetypeGroupId=com.totsp.gwt -DarchetypeArtifactId=maven-googlewebtoolkit2-archetype -DarchetypeVersion=1.0.4 -DremoteRepositories=http://gwt-maven.googlecode.com/svn/trunk/mavenrepo -DgroupId=myGroupId -DartifactId=myArtifactId Comando per eseguire l'applicazione mvn com.totsp.gwt:maven-googlewebtoolkit2-plugin:gwt Vantaggi
    • Compila anche la componente lato server
    • Generazione automatica file WAR
    • Gestione dipendenze
    • Scarica in automatico GWT da un repository di Maven
  • Flickr Mash-up Miliardi di informazioni sparse per la rete   Fare un applicativo Mash-up vuol dire sviluppare  un software capace di aggregarle in un solo punto
  • Ringraziamo le API...                 ...e vediamo quelle che usa Flickr http://www.flickr.com/services/api/   REST + JSON
  • Prima prova di contatto... String url =  &quot; http://www.flickr.com/services/rest/?format=json& method =flickr.interestingness.getList& api_key =a1234567a1ce1bd1aba1234 aaec123e1& user_id =1234567@N01 &quot;; RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, apiUrl); Request req = builder.sendRequest(null, new JsonRequestCallBack());     public class JsonRequestCallBack implements RequestCallback {      public void onError(Request request, Throwable exception) {             //gestisco richiesta in errore          }          public void onResponseReceived(Request req, Response response) {             //gestisco richiesta avvenuta con successo         } }        
  • ...ma non funziona AJAX non permette richieste CROSS-SITE Questo a causa del principio di sicurezza SOP (same origin policy) Abbiamo 3 soluzioni:   1) configurare un alias dell'host remoto in modo da poterlo chiamare come se fosse localhost   2) Creare un componente server-side che faccia da proxy   3) Imbrogliare : l'unica risorsa che possiamo richiedere esternamente è Javascript...uhm...interessante
  • Ok, imbrogliamo! L'output dei servizi REST+JSON di Flickr (ma anche Google e altri) può avvenire in due modi:  
      • jsonFlickrApi({&quot;photos&quot;:{&quot;page&quot;:1, &quot;pages&quot;:5, &quot;perpage&quot;:100, &quot;total&quot;:500, &quot;photo&quot;:[{&quot;id&quot;:&quot;3123...)
      •   myCallbackFunction ({&quot;photos&quot;: {&quot;page&quot;:1, &quot;pages&quot;:5, &quot;perpage&quot;:100, &quot;total&quot;:500, ...)
      myCallbackFunction sarà il nome di una funzione Javascript a cui sarà passato l'oggetto JSON ritornato da Flickr   L'url è diventato: String url =  &quot; http://.../rest/?format=json& method =...& api_key =a...1& user_id =1234567@N01& jsoncallback = myCallbackFunction &quot;;
  • Un problema ed una soluzione: JSNI Problema
      • il nome del metodo di callback deve essere predefinito  
      • GWT rinomina i metodi per ridurre le dimensioni del js
    Soluzione   Con JSNI definiamo codice Javascript in una una classe public native static void getJson(String callback , String url, MyHandler h ) /*-{ var script = document.createElement(&quot;script&quot;);  script.setAttribute(&quot;src&quot;, url+ callback ); script.setAttribute(&quot;type&quot;, &quot;text/javascript&quot;); window[callback] = function(jsonObj){ h .@ it.pronetics.MyHandler::handle (Lcom/google/gwt/core/client/JavaScriptObject;)( obj );     window[callback + &quot;done&quot;] = true; }        document.body.appendChild(script); }-*/;
  • Ancora J ava S cript N ative I nterface package it.pronetics; ...   public class MyHandler {      public void handle(JavaScriptObject javaScriptObject) {         //creiamo l'oggetto JSON         JSONObject object = new JSONObject(javaScriptObject);         // isObject() e isArray() ritornano null in caso di errore,         // il valore recuperato in caso di successo         JSONArray photos = object.get( &quot;photos&quot; ).isObject().get( &quot;photo&quot; ).isArray();         String thumbnail = buildPhotoUrl(photoJson, &quot;s&quot;);         ....         Image image = new Image(thumbnail);         gallery.setWidget(row, column, image);      } ... bla bla bla ... }
  • Finalmente...
  • Il mio widget public class ImageSlide extends Composite { //estendere la classe Composite come consigliato da GWT public ImageSlide(String thumbnail, String preview, final String link) {          VerticalPanel mainPanel = new VerticalPanel();         HorizontalPanel details = new HorizontalPanel();                  Image thumbnailImage = new Image(thumbnail);         mainPanel.add(thumbnailImage);         mainPanel.add(details);         mainPanel.setBorderWidth(1);                  Button show = new Button(&quot;Show&quot;);         Button open = new Button(&quot;Open&quot;);         details.add(show);         details.add(open);                  final PopupPanel popup = new PopupPanel();            Image previewImage = new Image(preview);         VerticalPanel imagePanel = new VerticalPanel();         imagePanel.add(previewImage);                  previewImage.addClickListener(new ClickListener(){ public void onClick(Widget sender) { popup.hide(); }  });         popup.setWidget(imagePanel);                  show.addClickListener(new ClickListener(){ public void onClick(Widget sender) { popup.show(); } });                  open.addClickListener(new ClickListener(){ public void onClick(Widget sender) { Window.open(link, &quot;_blank&quot;,&quot;enabled&quot;);}});                  initWidget(mainPanel); //chiamata obbligatoria!     } }
  • Già stiamo migliorando...
  • ...ma questa è meglio...
  • ...c'è anche qualche info...
  • ...ma come abbiamo fatto?     public ImageSlide(String thumbnail, String preview, String title, final String link) {        ... creo vari panel ...                  Image thumbnailImage = new Image(thumbnail);         thumbnailImage.setStyleName(&quot;image-panel&quot;);         mainPanel.add(thumbnailImage);         mainPanel.setCellHorizontalAlignment(thumbnailImage, HasHorizontalAlignment.ALIGN_CENTER);         mainPanel.add(details);                  Button open = new Button(&quot;View on Flickr&quot;, new OpenLinkOnClick(link));         open.setWidth(&quot;100%&quot;);         Button close = new Button(&quot;Close me!&quot;, new ClosePopupPanelOnClick(popup));         close.setWidth(&quot;100%&quot;);                  Image previewImage = new Image(preview);         VerticalPanel imagePanel = new VerticalPanel();         imagePanel.add(previewImage);                  infoPanel.add(new Label(title, true));         infoPanel.add(open);         infoPanel.add(close);                  previewTab.add(imagePanel, &quot;Image&quot;);         previewTab.add(infoPanel, &quot;Get Info&quot;);         previewTab.selectTab(0);         previewTab.setAnimationEnabled(true);                  previewImage.addClickListener(new ClosePopupPanelOnClick(popup));             thumbnailImage.addClickListener(new DisplayPopupOnClick(popup));                  initWidget(mainPanel); //chiamata obbligatoria!     }
  • Ma soprattutto CSS E' stato modificato il file FlickrGWT.css   .image-panel {     background: url('img/bg.png') no-repeat top center;     padding: 0px 10px 10px 10px; } Ricordate : GWT in fondo crea semplici pagine HTML i cui stili possono essere impostati con semplici CSS
  • La versione finale!
      • Modifichiamo il file FlickrGWT.html creando un layout HTML
      • Specifichiamo l'id del div che conterrà la nostra applicazione: RootPanel.get(&quot;flickr-gallery&quot;).add(gallery);
      • Scriviamo un po' di css e html e...
  • Image Bundle? Problema Troppe request uccidono i nostri server Soluzione Una sola request per le immagini usate nel nostro applicativo
  • Image Bundle con GWT
      • L'unione di tutte le immagini in una sola è automatica
      • Basta definire una interfaccia interface ToolBarImage extends ImageBundle {          @Resource ( &quot;img/open.png&quot; )         AbstractImagePrototype open();         ....         @Resource ( &quot;img/save.png&quot; )         AbstractImagePrototype save();  }
      • L'utilizzo è ancora più semplice ToolBarImage bundle = (ToolBarImage)GWT.create(ToolBarImage. class ); Image save = bundle.save().createImage(); toolbar.add(save);
  • Plugin e widget per la view
  • Alcune librerie utili
      • Spring Security + GWT http://www.insideit.fr/post/2009/02/19/How-to-:-Spring-Security-ex-Acegi-and-GWT
      • Dependency injection
        • GIN - http://code.google.com/p/google-gin/
        • SUCO - http://code.google.com/p/suco/
        • RocketGWT - http://code.google.com/p/rocket-gwt/
        • SpringME - http://springframework.me
      • Altri Framework
        • GWT Toolbox - http://code.google.com/p/gwt-toolbox/
        • GWT Widget Library -http://gwt-widget.sourceforge.net/
        • GWITTIR - http://code.google.com/p/gwittir/
      • Hibernate + GWT
        • Gilead - http://noon.gilead.free.fr/gilead/
      • Sviluppo Server Side
        • Enunciate - http://enunciate.codehaus.org/
  • Usciamo dal browser con PRISM Mozilla Prism è un plugin per Firefox che permette la trasformazione di applicazioni web in applicazioni desktop
  • Usciamo dalla rete con Google Gears
      • Database SQL
      • Geo localizzazione
      • Interazione col desktop
      • Local server per file, immagini, javascript, css
  • Una combinazione vincente GWT + GEAR + PRISM = COOL APPLICATION
      • http://code.google.com/webtoolkit/
      • http://www.ociweb.com/mark/programming/GWT.html
      • http://code.google.com/p/gwt-google-apis/
      • http://gears.google.com/
      • http://www.gwtsite.com/
      • http://www.ongwt.com 
      • http://labs.mozilla.com/projects/prism/
    Link & Libri
      • Davide Cerbo [email_address] http://davide.cerbo.born-to-co.de
      • Stefano Linguerri stefano.linguerri @pronetics.it http://www.eljeko.net
    Contatti
  • Q&A