SlideShare une entreprise Scribd logo
1  sur  96
Google Web Toolkit
« Under the hood »
     Sébastien VUILLET
     Directeur technique
     Chez Silverpeas
Plateforme collaborative
  La réalisation d'un Intranet/Extranet
  La gestion documentaire (GED)
  La gestion d'une banque d'images
  La gestion documentaire de projets
  La gestion de connaissances
  Et plus encore ...




                                          www.silverpeas.com
                                           www.silverpeas.org
Version mobile




                 Power by




                   www.silverpeas.com
                    www.silverpeas.org
État des lieux
Le développement d'applications web c'est
 quoi ?
  Différents langages : HTML + CSS + JavaScript +
    Java
  Différents formats d'échanges : XML, Json ...
  Différents environnement d’exécution : Desktop,
    smatphone, tablette
  Différents moteurs d’exécution : IE, FF, ...
  Utilisation de langages interprétés
État des lieux
Au final développer une webapp ce n'est
 toujours pas facile !
GWT - Définition
Ensemble d'outils
Abstraction :
  du développement JavaScript
  de l'environnement d’exécution


« One to rule them all »
  Un langage : Java
GWT Masterpiece
Le compilateur
GWT - Compilateur
Étape Java AST -> Optimized Java AST :
  Pruning : suppression des classes / interfaces /
    méthodes / attributs non référencés.


  Finalizing : rend les méthodes, les classes et les
    variables final si c'est possible.


  Make Static : rend statiques les méthodes
   d'instances si possible (pas de surcharge, n'utilise
   pas de variables d'instance).
GWT - Compilateur
Étape Java AST -> Optimized Java AST :
  Type Tightening : optimisation des attributs et
    paramètres pour les rendre concrets (pour réduire
    les opérateurs cast et instanceof).


  Method Call Tightening : changement des appels
   de méthodes polymorphiques, en appel direct.


  Dead Code Elimination : suppression des portions
   de code qui n'est jamais appelé (condition jamais
GWT - Compilateur
Étape Java AST -> Optimized Java AST :
  Method Inlining : suppression des méthodes non
   référencés dans une classe extérieure et
   embarquement du code directement dans à
   l'endroit de l'appel (si la méthode n’excède pas
   deux lignes).


  Same Parameter Value Optimizer


  Enum Ordinalizer : remplace les références aux
GWT - Compilateur
Étape Java AST -> Optimized Java AST :
  Remove Empty Super Calls


  Set of Normalization Rules : transformation du
   code pour que la génération du JavaScript soit
   optimale (fusion des blocs catch, utilisation
   d'array). Remplacement des appels aux classes
   du JDK par de les classes de
   com.google.gwt.lang.
GWT - Compilateur
Étape Java AST -> Optimized Java AST :




  arbre « unifié », car il n'est lié à aucune permutation
GWT – Compilateur
Les permutations

                   Télécharge uniquement
                    la version nécessaire
                     au navigateur client


                          Un seul
                           code
                           Java




                   … puis le met en cache
                        indéfiniment
GWT - Compilateur
Possibilité de désactiver les optimisations :
  Paramètre : -draftCompile
Réglage du code généré :
  Paramètre : -style (OBF, PRETTY, DETAILED)
Amélioration des temps de compilation :
  Paramètre : -localWorkers
  Limiter les permutations : <set-property
    name="user.agent" value="gecko"/>
GWT - Compilateur
Code généré par défaut :

function qH(){return np}
function mH(){}
_=mH.prototype=new mu;_.gC=qH;_.tI=0;function
uH(){uH=ZH;sH={};tH=[];sH[LM]=[Is,Hs,Js];sH[JM]=[rt,qt,st];Xv(tH,yn,LM);Xv(tH,To,JM)}
var sH,tH;function AH(a){a.b=oH(new mH);return a}
function BH(a){var b,c,d,e,f,g,h,i,j,k;g=ox(new cx,MM);f=OA(new FA);j=XH(new
 VH,NM,OM);KA(f,j.b+sJ+j.c);pw(g.B,PM,true);Zw(gA(QM),f);Zw(gA(RM),g);f.B.focus()
;k=Jg(f.B,NJ).length;k>0&&JA(f,0,k);c=py(new my);Lf((tf(),c.b.B),SM);c.o=true;
b=ox(new cx,TM);b.B.id=UM;i=Py(new Ny);h=Ty(new My);d=UA(new RA);pw(d.B,VM,true);
VA(d,Uy(new My,WM));VA(d,i);VA(d,Uy(new My,XM));VA(d,h);d.b=(kz(),jz);VA(d,b);
Ax(c.j,d);Mx(c);vw(b,FH(new DH,c,g),(sh(),rh));e=KH(new IH,a,g,f,i,h,c,b);
vw(g,e,rh);vw(f,e,(hi(),gi))}
function CH(){return rp}
function xH(){}
GWT - Compilateur
Code généré en style pretty :
var $wnd = parent;
var $doc = $wnd.document;
var $moduleName, $moduleBase;
var $strongName = '21B409FCD39529C5A9DB925F7D8D9A95';
var $stats = $wnd.__gwtStatsEvent ? function(a) {return
  $wnd.__gwtStatsEvent(a);} : null;
$stats && $stats({moduleName:'gwtperf',subSystem:'startup',evtGroup:
'moduleStartup',millis:(new Date()).getTime(),type:'moduleEvalStart'});
var _;
function nullMethod(){
}


function equals(other){
  return this === (other == null?null:other);
}


function getClass_0(){
  return Ljava_lang_Object_2_classLit;
}


function hashCode_0(){
  return this.$H || (this.$H = ++sNextHashId);
}


function toString_0(){
  return (this.typeMarker$ == nullMethod || this.typeId$ ==
2?this.getClass$():Lcom_google_gwt_core_client_JavaScriptObject_2_classLit)
.typeName + '@' + toPowerOfTwoString(this.typeMarker$ == nullMethod || this.typeId$
== 2?this.hashCode$():this.$H || (this.$H = ++sNextHashId), 4);
}


function Object_0(){
}


_ = Object_0.prototype = {};
_.equals$ = equals;
_.getClass$ = getClass_0;
_.hashCode$ = hashCode_0;
_.toString$ = toString_0;
_.toString = function(){
  return this.toString$();
}
;
GWT - Compilateur
Obfuscation VS pretty :
GWT – build
GWT – Deferred binding
Le Deferred Binding consiste à effectuer l’insertion de la classe
  demandée à la compilation et non durant l’exécution du
  programme.
Deux implémentation de Deferred Binding
   Replacement : une classe est remplacée par une autre sous
     certaines conditions
   Generators : les classes qui héritent d’une classe particulière
     sont générées et remplacées sous certaines conditions
GWT – Deferred binding
Replacement :
  Configuration du module
GWT – Deferred binding
Generators :
  Classes invoquées par le compilateur GWT pour générer
     l’implémentation d’un classe java
  Pour la compilation en mode web, l’implémentation générée est
    directement traduite en Javascript
  Configuration du module :




  Créer un générateur
GWT – Linkers
Assurent le packaging
Exemples de linkers :
  IframeLinker (défaut) : génère une Iframe cachée
  XSLinker : produit des fichiers d'extension xs
   comme <module>-xs.nocache.js (cas des
   permutations hébergés sur un autre serveur que
   les pages hôtes).
  SingleScriptLinker : génère un seul fichier Java-
    Script pour un module. Il n'existe qu'une seule
    permutation.
GWT – Linkers
   Utilisation des linkers :
<module>
     (...)

      <define-linker name="sso"
      class="com.google.gwt.core.linker.SingleScriptLinker" />
      <define-linker name="std" class="com.google.gwt.core.linker.IFrameLinker" />
      <define-linker name="xs" class="com.google.gwt.core.linker.XSLinker" />

      <define-linker name="soycReport" class="com.google.gwt.core.linker.SoycReportLinker" />
      <define-linker name="symbolMaps" class="com.google.gwt.core.linker.SymbolMapsLinker" /
  >

      <add-linker name="std" />

     <add-linker name="soycReport" />
     <add-linker name="symbolMaps" />
</module>
GWT – Linkers
Créer un linker :
  Créer une classe dérivant de
    com.google.gwt.core.ext.Linker.
  Ajouter l'annotation @LinkOrder pour déterminer si le
    linker doit s'exécuter avant, après ou en
    remplacement du linker primaire. Le nombre de
    linkers n'est pas limité, seul le primaire est unique.
  Définir et ajouter le linker personnalisé dans le fichier
   de configuration du module (<module>.gwt.xml).
  Inclure dans le classpath du compilateur le nouveau
GWT – Linkers
    Exemple de linker :
@LinkerOrder(LinkerOrder.Order.POST)
public class MyLinker extends AbstractLinker {

         public String getDescription() {
               return "MyLinker";
         }

         public ArtifactSet link(TreeLogger logger, LinkerContext context,
                        ArtifactSet artifacts) throws UnableToCompleteException {
                String artifactList="";
                // Récupère la liste de tous les artéfacts
                ArtifactSet toReturn = new ArtifactSet(artifacts);
                for (Artifact artifact : toReturn) {
                        // Et trie seulement les fichiers générés
                        if (artifact instanceof EmittedArtifact) {
                                 EmittedArtifact fic = (EmittedArtifact) artifact;
                                 // Stocke dans une chaîne de caractères le nom du fichier généré
                                 artifactList = fic.getPartialPath() + "," + new
                                 Date(fic.getLastModified()).toString() + "n" + artifactList ;
                        }
                }
                // Ajoute à la liste précédente un nouveau fichier recensant
                // les artéfacts
                toReturn.add(emitString(logger, artifactList, "ListFiles.txt"));

               return toReturn;
         }
}
GWT – runtime
GWT – perfect caching
GWT – code splitting
Découpage en fragments JavaScript pour
 téléchargement à la demande
   GWT.runAsync(SomeClass.class, new RunAsyncCallback() {
     // ... callback class's body ...
   }


Séquence
   <extend-configuration-property name="compiler.splitpoint.initial.sequence"
    value="com.yourcompany.yourprogram.SomeClass"/>
   <extend-configuration-property name="compiler.splitpoint.initial.sequence"
    value="com.yourcompany.yourprogram.AnotherClassClass"/>
   <extend-configuration-property name="compiler.splitpoint.initial.sequence"
    value="com.yourcompany.yourprogram.YetAnotherClass"/>
GWT - Architecture
GWT - JRE Emulation
Types primitifs
Annotations
Exception
Assertion
Serialization
Packages :
  java.lang
  java.math
  java.io
GWT - JRE Emulation
Non supporté
  Multithreading (pour l'instant)
  Gestion de la concurrence (pour l'instant)
  Finalisation des objets
  Réflexion
GWT - JRE Emulation
Étendre la JRE Emulation :
   Ex : Timestamp
   <module>
    ...
    <!-- JRE Classes not Emulated by GWT -->
    <super-source path='jre'/>
   </module>


Serializer :
   Timestamp_CustomFieldSerializer
   public static void serialize(SerializationStreamWriter streamWriter, MyObject myObject)
        throws SerializationException {}

     public static void deserialize(SerializationStreamReader streamReader, MyObject myObject)
       throws SerializationException {}

     //This method is optional
     public static MyObject instantiate(SerializationStreamReader streamReader)
        throws SerializationException {}
GWT - tools
Environnement de développement
  Google plugin pour Eclipse, GWT Designer
Debug
  dans Eclipse avec dev mode et les plugins
    navigateurs
Optimisation
  SpeedTracer, Soyc
Build
  Maven plugin
Tests
  HtmlUnit, Selenium,...
GWT - synthèse
Pas un framework : beaucoup plus


         gwt-user.jar
                              Le Framework

     gwt-dev-[platform].jar




                              Les outils
GWT - performances
GWT - performances
Client Bundle
  CSS resources
  Image resources
  Data resources
  Text resources
GWT - performances
Client Bundle
  public interface MyResources extends ClientBundle {
   public static final MyResources INSTANCE = GWT.create(MyResources.class);

      @Source("my.css")
      public CssResource css();

      @Source("config.xml")
      public TextResource initialConfiguration();

      @Source("manual.pdf")
      public DataResource ownersManual();

      @Source("default.txt")
      public TextResource defaultText();
  }


I18N compatible
GWT - performances
Client Bundle : image resources
  interface Resources extends ClientBundle {
    @Source("logo.png")
    ImageResource logo();

      @Source("arrow.png")
      @ImageOptions(flipRtl = true)
      ImageResource pointer();
  }

  Resources resources = GWT.create(Resources.class);
  Image img = new Image(resources.logo());
GWT - performances
Client Bundle : image resources
GWT - performances
Chargement des images sans Client Bundle
GWT - performances
Client Bundle : CSS ressources
  interface MyResources extends CssResource {
    String myStyleName();
  }


  Fonctionnalités
     Constantes
        @def small 1px;
        @def black #000;
        border: small solid black;
     Substitution au runtime
        @eval userBackground com.module.UserPreferences.getUserBackground();
        div {
          background: userBackground;
        }
GWT - performances
Client Bundle : CSS ressources
  interface MyResources extends CssResource {
    String myStyleName();
  }


  Fonctionnalités
     Constantes
        @def small 1px;
        @def black #000;
        border: small solid black;
     Substitution au runtime
        @eval userBackground com.module.UserPreferences.getUserBackground();
        div {
          background: userBackground;
        }
GWT - performances
Client Bundle : CSS ressources
  Fonctionnalités
    Value function
       .myDiv {
         offset-left: value('imageResource.getWidth', 'px');
       }
    Literal function
       div-with-literal {
         top: literal("expression(document.compatMode=="CSS1Compat" ?
                       documentElement.scrollTop : document.body.scrollTop  2)");
       }
GWT - performances
Client Bundle : CSS ressources
  Fonctionnalités
                    /* Runtime evaluation in a static context */
    Conditions      @if (com.module.Foo.staticBooleanFunction()) {
                      ... css rules ...
                    }

                    /* Compile-time evaluation */
                    @if <deferred-binding-property> <space-separated list of values> {
                      ... css rules ...
                    }
                    @if user.agent safari gecko1_8 { ... }
                    @if locale en { ... }

                    /* Negation is supported */
                    @if !user.agent ie6 opera {
                    }

                    /* Chaining is also supported */
                    @if (true) {
                    } @elif (false) {
                    } @else { }
GWT - performances
Client Bundle : CSS ressources
  Fonctionnalités
    Images sprites
       public interface DocumentsResources extends ClientBundle {
        @Source("documents.css")
        DocumentsCSS css();

           @Source("instances.png")
           ImageResource instances();
       }
       public interface DocumentsCSS extends CssResource {
         String instances();
       }
       @sprite .instances {
             gwt-image: "instances";
             border: none;
       }
GWT – Bilan de l'approche
Perfect caching


Client Bundle


Data : URLs & MHTML packaging


Developer guided code splitting
GWT - Développements
JSNI <=> JNI
  Ouverture et intégration



Fonctionnalités
  Invoquer du JavaScript natif depuis du code Java
  public static native void alert(String msg) /*-{
    $wnd.alert(msg);
  }-*/;
GWT - Développements
JSNI
 Invoquez une méthode Java depuis du code
   javaScript externe

  //La fonction Java qu'on peut appeler depuis javaScript
  public static int maFonctionJava(int param) { ... }

  public static native void exportationMaFonction() /*-{

  //On assigne notre méthode
  // à la variable globale maFonctionJava de notre objet window
  $wnd.maFonctionJava = $entry(@com.silverpeas.jsni.client::maFonctionJava(I));

  }-*/
GWT - Développements
Communication avec le serveur
  Plusieurs approches :
    RequestBuilder + JSONParser (resty-gwt)
    RequestBuilder + XMLParser
    GWT-RPC
    RequestFactory (depuis GWT 2.1)
GWT - Développements
Communication avec le serveur
  GWT-RPC
  @RemoteServiceRelativePath("Contact")
  public interface ServiceContact extends RemoteService {
         List<DetailUserDTO> getAllContact() throws ContactException;
  }



  public class ServiceContactImpl extends AbstractAuthenticateService
  implements ServiceContact {

      public List<DetailUserDTO> getAllContact() throws ContactException {
           ...
      }
  }
GWT - Développements
  Communication avec le serveur
      GWT-RPC
      public interface ServiceContactAsync {
        void getAllContact(AsyncCallback<List<DetailUserDTO>> callback);
      }


   web.xml
<servlet>
      <servlet-name>serviceContactImpl</servlet-name>
      <servlet-class>com.silverpeas.mobile.server.services.ServiceContactImpl</servlet-
  class>
 </servlet>
 <servlet-mapping>
      <servlet-name>serviceContactImpl</servlet-name>
      <url-pattern>/spmobil/Contact</url-pattern>
 </servlet-mapping>
GWT - Développements
Communication avec le serveur
  GWT-RPC : appel

 ServiceContactAsync serviceContact =
    (ServiceContactAsync) GWT.create(ServiceContact.class);

 serviceContact.getAllContact(new AsyncCallback<List<DetailUserDTO>>() {
     @Override
     public void onFailure(Throwable caught) {
             ...
     }

     @Override
     public void onSuccess(List<DetailUserDTO> result) {
             ...
     }
   });
GWT - Développements
Communication avec le serveur
  GWT-RPC : architecture
GWT - Développements
Communication avec le serveur
  GWT-RPC : Simple et puissant
    Envoie / réception de POJO

    Support du polymorphisme

    Transfert optimisés
    (plus léger que JSON)

    Sécurité (pas de risque de
    JavaScript hijacking/JSON attack)
GWT - Développements
Communication avec le serveur
  RequestFactory
    Pour les services orientés données
    Niveau d’abstraction plus important que GWT-RPC
    Plus rapide que GWT-RPC
       Basé sur JSON : pas de sérialisation/déserialisation
       Envoi uniquement du différentiel de données
    Réponse aux problèmes Entity / DTO
GWT - Développements
Communication avec le serveur
  RequestFactory : Entity proxies

  @Entity
  public class Employee {        @ProxyFor(Employee.class)
                                 public interface EmployeeProxy
      @Size(min = 3, max = 30)          extends EntityProxy {
      private String userName;
                                     Long getId();
      @Id
      private Long id;               String getUserName();

      @Version                       void setUserName(String userName);
      private Integer version;
                                     ...
      ...                        }
  }
GWT - Développements
Communication avec le serveur
   RequestFactory : Value proxies



                             public interface AddressProxy extends ValueProxy
 public class Address {
                                {
   private String street1;
                               public String getStreet1();
   private String street2;
                               public String getStreet2();
   private String city;
                               public String getCity();
   private String st;
                               public String getSt();
   private String zip;
                               public String getZip();
   ...
                               ...
 }
                             }
GWT - Développements
Communication avec le serveur
  RequestFactory
  public interface ExpensesRequestFactory extends RequestFactory {

      EmployeeRequest employeeRequest();
      ...
  }

  @Service(Employee.class)
  public interface EmployeeRequest extends RequestContext {

      Request<Long> countEmployees();
      Request<List<EmployeeProxy>> findAllEmployees();
      Request<EmployeeProxy> findEmployee(Long id);
      InstanceRequest<EmployeeProxy, Void> persist();
      InstanceRequest<EmployeeProxy, Void> remove();

  }
GWT - Développements
Communication avec le serveur
  RequestFactory
  final EventBus eventBus = new SimpleEventBus();
  requestFactory = GWT.create(ExpensesRequestFactory.class);
  requestFactory.initialize(eventBus);
  requestFactory.employeeRequest().findEmployee(employeeId).fire(
       new Receiver<EmployeeProxy>() {
         @Override
         public void onSuccess(EmployeeProxy employee) {
         ...
         }
       });
  EmployeeRequest request = requestFactory.employeeRequest();
  EmployeeProxy newEmployee =
      request.create(EmployeeProxy.class);
  newEmployee.setDisplayName(...);
  newEmployee.setDepartment(...);
  ...
  Request<Void> createReq = request.persist().using(newEmployee);
GWT - Développements
Communication avec le serveur
  RequestFactory : entity validation
     JSR 303 support
     Envoi de violation de contraintes au client
     Appel de la méthode onViolation() du Receiver
GWT - Développements
Des logs dans le browser
  GWT logging




    # Dans le fichier .gwt.xml
    <inherits name="com.google.gwt.logging.Logging"/>



    Logger logger = Logger.getLogger("monLogger");
    logger.log(Level.SEVERE, "impossible de contacter le serveur");
GWT - Développements
Des logs dans le browser
  GWT logging : loggers
  private static Logger childLogger =
    Logger.getLogger("ParentLogger.Child");
  private static Logger parentLogger = Logger.getLogger("ParentLogger");
  private static Logger rootLogger = Logger.getLogger("");


  Configuration
  <set-property name="gwt.logging.logLevel" value="SEVERE"/>
  <set-property name="gwt.logging.enabled" value="FALSE"/>
  <set-property name="gwt.logging.consoleHandler" value="DISABLED"/>
GWT - Développements
Des logs dans le browser
  GWT logging : handlers
    SystemLogHandler : stdout (seulement en DevMode)
    DevelopmentModeLogHandler : sur appel de la méthode
      GWT.log (seulement en DevMode)
    ConsoleLogHandler : javascript console
    FirebugLogHandler : firebug
    PopupLogHandler : popup
    SimpleRemoteLogHandler : envoi au serveur (via GWT-
      RPC)
GWT - Développements
Et la GUI ?
GWT - Développements
Approche de développement par composants
  En java : « comme Swing »
  Widgets et placement par Panels et Layouts


Avantages :
  abstraction de l'html / javascript
    (DOM/event/memory)
  programmation événementielle
  refactoring
Inconvénients :
GWT - Développements
Les widgets
  Intégrés : com.google.gwt.user.client.ui
GWT - Développements
Les widgets
  Bibliothèques additionnelles
    gwt-mosaic
    Sencha GXT
    Smartgwt (wrapper)
    Gwtmobile
    Gwt-links
    Gwt-cal
    GwtGL
GWT - Développements
 Les widgets
     Construire ses propres widgets
Trois possibilités pour créer ses propres composants :

Créer un widget avec des widgets existants
Héritage de com.google.gwt.user.client.ui.Composite


Créer un widget nouveau sans composition
Héritage de com.google.gwt.user.client.ui.Widget


Créér un widget qui « wrap » du code JavaScript en utilisation using JSNI
GWT - Développements
Les widgets : construire ses propres widgets
  public class OptionalTextBox extends Composite implements ClickHandler {

      private TextBox textBox = new TextBox();
      private CheckBox checkBox = new CheckBox();

      public OptionalTextBox(String caption) {
       VerticalPanel panel = new VerticalPanel();
       panel.add(checkBox);
       panel.add(textBox);

          checkBox.setText(caption);
          checkBox.setChecked(true);
          checkBox.addClickHandler(this);
      }

      public void onClick(ClickEvent event) {
        Object sender = event.getSource();
        if (sender == checkBox) {
          textBox.setEnabled(checkBox.isChecked());
        }
      }
  }
GWT - Développements
Les widgets : construire ses propres widgets
  public class OptionalTextBox extends Composite implements ClickHandler {

      private TextBox textBox = new TextBox();
      private CheckBox checkBox = new CheckBox();

      public OptionalTextBox(String caption) {
       VerticalPanel panel = new VerticalPanel();
       panel.add(checkBox);
       panel.add(textBox);

          checkBox.setText(caption);
          checkBox.setChecked(true);
          checkBox.addClickHandler(this);
      }

      public void onClick(ClickEvent event) {
        Object sender = event.getSource();
        if (sender == checkBox) {
          textBox.setEnabled(checkBox.isChecked());
        }
      }
  }
GWT - Développements
Ui-binder (depuis GWT 2.0) : declarative UI
  Description des vues en XML
  Binding XML (*.ui.xml) / Java (*.java)


  <ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
    xmlns:g='urn:import:com.google.gwt.user.client.ui'>

   <g:HTMLPanel>
    Gagnant, <g:ListBox ui:field='listBox' visibleItemCount='1'/>.
   </g:HTMLPanel>

  </ui:UiBinder>
GWT - Développements
Ui-binder (depuis GWT 2.0) : declarative UI
  public class HelloWidgetWorld extends Composite {

      interface MyUiBinder extends UiBinder<Widget, HelloWidgetWorld> {}
      private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);

      @UiField ListBox listBox;

      public HelloWidgetWorld(String... names) {
        // sets listBox
        initWidget(uiBinder.createAndBindUi(this));
        for (String name : names) {
          listBox.addItem(name);
        }
      }
  }
GWT - Développements
Ui-binder (depuis GWT 2.0) : declarative UI
  Annotations
    @UiField
    @UiHandler
    @UiFactory
    @UiConstructor
    @UiTemplate("mobile.ui.xml")


  Ressources externes
    <ui:with field='res' type='com.silverpeas.ged.Resources'/>
    @UiField(provided = true)
GWT - Développements
Editors (depuis GWT 2.1)
  <inherits name="com.google.gwt.editor.Editor" />




  POJO
  Editor (généralement un widget)
  Driver
      SimpleBeanEditorDriver
      RequestFactoryEditorDriver
  Adapter
GWT - Développements
Editors
 public class PersonEditor extends Composite implements Editor<Person> {

     interface Binder extends UiBinder<Widget, PersonEditor> {}

     private static final Binder BINDER = GWT.create(Binder.class);

     @UiField TextBox firstName;
     @UiField TextBox lastName;
     @UiField AddressEditor address;

     public PersonEditor() {
       initWidget(BINDER.createAndBindUi(this));
     }
 }

Annotations @path et @ignored
GWT - Développements
Editors
 public class PersonView extends Composite {

  interface Binder extends UiBinder<Widget, PersonView> {}

  interface EditorDriver extends SimpleBeanEditorDriver<Person, PersonEditor> {}

  private final Binder BINDER = GWT.Create(Binder.class);

  private final PersonServiceAsync RPC = GWT.create(PersonService.class);

  private final EditorDriver editorDriver = GWT.create(EditorDriver.class);

  @UiField PersonEditor editor;
  @UiField Button save;
  @UiField Button cancel;

  public PersonView() {
    initWidget(BINDER.createAndBindUi(this));
  }
GWT - Développements
Editors
 public void edit(String id) {
    RPC.getPerson(id, new AsyncCallback<Person>() {
      @Override
      public void onSuccess(Person person) {
        editorDriver.edit(person);
      }
      @Override
      public void onFailure(Throwable e) {
        ...
      }
    });
  }
GWT - Développements
Editors
     @UiHandler("save")
     void onSaveClick(ClickEvent event) {
       If (! editorDriver.hasErrors()) {
         Person person = editorDriver.flush();
         RPC.savePerson(this.value, new AsyncCallback<Void>() {
           @Override
           public void onSuccess(Person person) {
              ...
           }
           @Override
           public void onFailure(Throwable e) {
             ...
           }
         });
       } else {
         List<EditorError> errors = editorDriver.getErrors() ;
         ...
       }
     }
 }
GWT - Développements
HTML5 (depuis GWT 2.3)
  Intégration progressive
    Événements multi-touch
    Drag & drop
    LocalStorage & SessionStorage
    Canvas
    Audio (expérimentale)
    Vidéo (expérimentale)
GWT - Développements
Patterns
  MVC : implémentation PureMVC
GWT - Développements
Patterns
  EventBus
    SimpleEventBus
    ResettableEventBus
    CountingEventBus
GWT - Développements
Patterns
  EventBus : handler

  public interface DocumentsControllerEventHandler extends EventHandler {
   void loadSettings(DocumentsLoadSettingsEvent event);

      void saveSettings(DocumentsSaveSettingsEvent event);

      void loadTopics(DocumentsLoadTopicsEvent event);

      void loadPublications(DocumentsLoadPublicationsEvent event);

      void loadPublication(DocumentsLoadPublicationEvent event);
  }
GWT - Développements
Patterns
  EventBus : event
  public abstract class AbstractDocumentsControllerEvent extends
    GwtEvent<DocumentsControllerEventHandler> {

      public static Type<DocumentsControllerEventHandler> TYPE =
        new Type<DocumentsControllerEventHandler>();

      public AbstractDocumentsControllerEvent() {
      }

      @Override
      public GwtEvent.Type<DocumentsControllerEventHandler> getAssociatedType() {
        return TYPE;
      }
  }
GWT - Développements
Patterns
  EventBus : event
  public class DocumentsSaveSettingsEvent extends AbstractDocumentsControllerEvent {
   private ApplicationInstanceDTO instance;
   private TopicDTO topic;

      public DocumentsSaveSettingsEvent(ApplicationInstanceDTO instance, TopicDTO topic) {
        super();
        this.instance = instance;
        this.topic = topic;
      }

      @Override
      protected void dispatch(DocumentsControllerEventHandler handler) {
        handler.saveSettings(this);
      }
      public ApplicationInstanceDTO getInstance() {
        return instance;
      }
      public TopicDTO getTopic() {
        return topic;
      }
  }
GWT - Développements
Patterns
  EventBus
       Abonnement
  EventBus.getInstance().addHandler(AbstractDocumentsControllerEvent.TYPE, this);


       Désabonnement
   EventBus.getInstance().removeHandler(AbstractDocumentsControllerEvent.TYPE,
                                        this);

       Lancement
 EventBus.getInstance().fireEvent(
          new DocumentsSaveSettingsEvent(currentInstance, currentTopic));
GWT - Développements
Patterns
  MVP :
  intégré depuis GWT 2.1
GWT - Développements
    Patterns
        MVP : navigation
public class AppActivityMapper implements ActivityMapper {
  private ClientFactory clientFactory;

    public AppActivityMapper(ClientFactory clientFactory) {
      super();
      this.clientFactory = clientFactory;
    }

    @Override
    public Activity getActivity(Place place) {
       if (place instanceof HelloPlace)
           return new HelloActivity((HelloPlace) place, clientFactory);
       else if (place instanceof GoodbyePlace)
           return new GoodbyeActivity((GoodbyePlace) place,
    clientFactory);
       return null;
    }
}
GWT - Développements
Des APIs pour aller plus loin
  Internationalisation
  Sécurité
  Accessibilité
  Tests
  ...
GWT - Développements
Des bibliothèques pour aller plus loin
  Gin : injection client-side
  Gwt-ent : AOP, Reflexion, ...
  Gwt-dnd
  Gwt-comet
  Crypto-gwt
  Gwt-voices
  Gquery
Uses cases
Application web single page
  Caractéristiques :
     Non server-centric
     Webapp légère :
         un conteneur de servlets suffit
         pas de compilation des pages par le serveur d'applications
Application ou site web multi page
  Caractéristiques :
     Server-centric : jsp, jsf, php, html
     Frameworks additionnels : vaadin
Application dans le cloud
Qui utilise GWT ?
Que s'est il passé depuis 2006 ?
Novembre 2011 :
   Abandon de flex par adobe
   Abandon de Silverlight par Microsoft
HTML5 plébiscité par le ténors du web
Que s'est il passé depuis 2006 ?
Adoption massive des smartphones




Explosion des applications mobiles natives
La suite : GWT 2.5
Amélioration du noyau :
 Optimisation du compilateur :
  30 % de réduction du code non
  compressé et 15 % avec
  compression gzip
 Support de SourceMap et
  Source-Level : java debugging
  dans Chrome (Firefox à venir)
Futur...
Merci de votre attention

Contenu connexe

Tendances

Cours yeoman backbone box2d
Cours yeoman backbone box2dCours yeoman backbone box2d
Cours yeoman backbone box2dhugomallet
 
Angular + JHipster @ Paris JUG
Angular + JHipster @ Paris JUGAngular + JHipster @ Paris JUG
Angular + JHipster @ Paris JUGWilliam Marques
 
Oxalide Workshop #4 - Docker, des tours dans le petit bassin
Oxalide Workshop #4 - Docker, des tours dans le petit bassinOxalide Workshop #4 - Docker, des tours dans le petit bassin
Oxalide Workshop #4 - Docker, des tours dans le petit bassinLudovic Piot
 
A la découverte de docker
A la découverte de dockerA la découverte de docker
A la découverte de dockerjean pasqualini
 
Julien Maitrehenry - Docker, ça mange quoi au printemps
Julien Maitrehenry - Docker, ça mange quoi au printempsJulien Maitrehenry - Docker, ça mange quoi au printemps
Julien Maitrehenry - Docker, ça mange quoi au printempsWeb à Québec
 
GWT Principes & Techniques
GWT Principes & TechniquesGWT Principes & Techniques
GWT Principes & TechniquesRachid NID SAID
 
Meetup Drupal Lyon 2016 - Environnements de dév Drupal automatisés LXC et Ans...
Meetup Drupal Lyon 2016 - Environnements de dév Drupal automatisés LXC et Ans...Meetup Drupal Lyon 2016 - Environnements de dév Drupal automatisés LXC et Ans...
Meetup Drupal Lyon 2016 - Environnements de dév Drupal automatisés LXC et Ans...Aurelien Navarre
 
Docker nice meetup #1 construire, déployer et exécuter vos applications, ...
Docker nice meetup #1   construire, déployer et exécuter vos applications, ...Docker nice meetup #1   construire, déployer et exécuter vos applications, ...
Docker nice meetup #1 construire, déployer et exécuter vos applications, ...adri1s
 
jQuery - GTI780 & MTI780 - ETS - A08
jQuery - GTI780 & MTI780 - ETS - A08jQuery - GTI780 & MTI780 - ETS - A08
jQuery - GTI780 & MTI780 - ETS - A08Claude Coulombe
 
Déploiements avec Docker
Déploiements avec DockerDéploiements avec Docker
Déploiements avec DockerLuis Lopez
 
Docker Tours Meetup #1 - Introduction à Docker
Docker Tours Meetup #1 - Introduction à DockerDocker Tours Meetup #1 - Introduction à Docker
Docker Tours Meetup #1 - Introduction à DockerThibaut Marmin
 
NightClazz Docker Découverte
NightClazz Docker Découverte NightClazz Docker Découverte
NightClazz Docker Découverte Zenika
 
Spring 3 en production
Spring 3 en productionSpring 3 en production
Spring 3 en productionJulien Dubois
 
Introduction à Docker et utilisation en production /Digital apéro Besançon [1...
Introduction à Docker et utilisation en production /Digital apéro Besançon [1...Introduction à Docker et utilisation en production /Digital apéro Besançon [1...
Introduction à Docker et utilisation en production /Digital apéro Besançon [1...Silicon Comté
 
jQuery GTI780 & MTI780 ETS A09
jQuery   GTI780 & MTI780   ETS   A09jQuery   GTI780 & MTI780   ETS   A09
jQuery GTI780 & MTI780 ETS A09Claude Coulombe
 
Présentation jQuery pour débutant
Présentation jQuery pour débutantPrésentation jQuery pour débutant
Présentation jQuery pour débutantStanislas Chollet
 

Tendances (20)

Cours yeoman backbone box2d
Cours yeoman backbone box2dCours yeoman backbone box2d
Cours yeoman backbone box2d
 
Angular + JHipster @ Paris JUG
Angular + JHipster @ Paris JUGAngular + JHipster @ Paris JUG
Angular + JHipster @ Paris JUG
 
Oxalide Workshop #4 - Docker, des tours dans le petit bassin
Oxalide Workshop #4 - Docker, des tours dans le petit bassinOxalide Workshop #4 - Docker, des tours dans le petit bassin
Oxalide Workshop #4 - Docker, des tours dans le petit bassin
 
A la découverte de docker
A la découverte de dockerA la découverte de docker
A la découverte de docker
 
Julien Maitrehenry - Docker, ça mange quoi au printemps
Julien Maitrehenry - Docker, ça mange quoi au printempsJulien Maitrehenry - Docker, ça mange quoi au printemps
Julien Maitrehenry - Docker, ça mange quoi au printemps
 
Apprenez le jQuery
Apprenez le jQueryApprenez le jQuery
Apprenez le jQuery
 
GWT Principes & Techniques
GWT Principes & TechniquesGWT Principes & Techniques
GWT Principes & Techniques
 
Meetup Drupal Lyon 2016 - Environnements de dév Drupal automatisés LXC et Ans...
Meetup Drupal Lyon 2016 - Environnements de dév Drupal automatisés LXC et Ans...Meetup Drupal Lyon 2016 - Environnements de dév Drupal automatisés LXC et Ans...
Meetup Drupal Lyon 2016 - Environnements de dév Drupal automatisés LXC et Ans...
 
Docker nice meetup #1 construire, déployer et exécuter vos applications, ...
Docker nice meetup #1   construire, déployer et exécuter vos applications, ...Docker nice meetup #1   construire, déployer et exécuter vos applications, ...
Docker nice meetup #1 construire, déployer et exécuter vos applications, ...
 
jQuery - GTI780 & MTI780 - ETS - A08
jQuery - GTI780 & MTI780 - ETS - A08jQuery - GTI780 & MTI780 - ETS - A08
jQuery - GTI780 & MTI780 - ETS - A08
 
Déploiements avec Docker
Déploiements avec DockerDéploiements avec Docker
Déploiements avec Docker
 
Docker Tours Meetup #1 - Introduction à Docker
Docker Tours Meetup #1 - Introduction à DockerDocker Tours Meetup #1 - Introduction à Docker
Docker Tours Meetup #1 - Introduction à Docker
 
NightClazz Docker Découverte
NightClazz Docker Découverte NightClazz Docker Découverte
NightClazz Docker Découverte
 
Devoxx fr
Devoxx frDevoxx fr
Devoxx fr
 
Présentation Docker
Présentation DockerPrésentation Docker
Présentation Docker
 
Spring 3 en production
Spring 3 en productionSpring 3 en production
Spring 3 en production
 
Introduction à Docker et utilisation en production /Digital apéro Besançon [1...
Introduction à Docker et utilisation en production /Digital apéro Besançon [1...Introduction à Docker et utilisation en production /Digital apéro Besançon [1...
Introduction à Docker et utilisation en production /Digital apéro Besançon [1...
 
jQuery GTI780 & MTI780 ETS A09
jQuery   GTI780 & MTI780   ETS   A09jQuery   GTI780 & MTI780   ETS   A09
jQuery GTI780 & MTI780 ETS A09
 
Présentation jQuery pour débutant
Présentation jQuery pour débutantPrésentation jQuery pour débutant
Présentation jQuery pour débutant
 
JQuery
JQueryJQuery
JQuery
 

Similaire à GWT : under the hood

Présentation Javascript à l'ESI (Alger)
Présentation Javascript à l'ESI (Alger)Présentation Javascript à l'ESI (Alger)
Présentation Javascript à l'ESI (Alger)Dr Samir A. ROUABHI
 
Cours du soir_gwt
Cours du soir_gwtCours du soir_gwt
Cours du soir_gwtSaid Talibi
 
Gwt fast overview_v1
Gwt fast overview_v1Gwt fast overview_v1
Gwt fast overview_v1David Herviou
 
Marzouk une introduction à jdbc
Marzouk une introduction à jdbcMarzouk une introduction à jdbc
Marzouk une introduction à jdbcabderrahim marzouk
 
Présentation de Django @ Orange Labs (FR)
Présentation de Django @ Orange Labs (FR)Présentation de Django @ Orange Labs (FR)
Présentation de Django @ Orange Labs (FR)Martin Latrille
 
Node.js, le pavé dans la mare
Node.js, le pavé dans la mareNode.js, le pavé dans la mare
Node.js, le pavé dans la mareValtech
 
ENIB cours CAI Web - Séance 3 - JSP/Servlet - Cours
ENIB cours CAI Web - Séance 3 - JSP/Servlet - CoursENIB cours CAI Web - Séance 3 - JSP/Servlet - Cours
ENIB cours CAI Web - Séance 3 - JSP/Servlet - CoursHoracio Gonzalez
 
Activity
ActivityActivity
Activitydido
 
Symfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 PerformantSymfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 PerformantHugo Hamon
 
GWT Approfondissement - GTI780 & MTI780 - ETS - A08
GWT Approfondissement - GTI780 & MTI780 - ETS - A08GWT Approfondissement - GTI780 & MTI780 - ETS - A08
GWT Approfondissement - GTI780 & MTI780 - ETS - A08Claude Coulombe
 
Automatisez vos tâches répétitives avec Grunt (Blend 2013)
Automatisez vos tâches répétitives avec Grunt (Blend 2013)Automatisez vos tâches répétitives avec Grunt (Blend 2013)
Automatisez vos tâches répétitives avec Grunt (Blend 2013)Corinne Schillinger
 
Gwt jetty et sources de données
Gwt   jetty et sources de donnéesGwt   jetty et sources de données
Gwt jetty et sources de donnéesFranck SIMON
 
Aperçu de RequireJS
Aperçu de RequireJSAperçu de RequireJS
Aperçu de RequireJSVISEO
 
react-slides.ppx (2) (1).pptx react presentation basic
react-slides.ppx (2) (1).pptx react presentation basicreact-slides.ppx (2) (1).pptx react presentation basic
react-slides.ppx (2) (1).pptx react presentation basiczineblahib2
 
Présentation Ansible Ikoula
Présentation Ansible IkoulaPrésentation Ansible Ikoula
Présentation Ansible IkoulaIkoula
 
Usages autour d’Ansible chez ikoula
Usages autour d’Ansible chez ikoulaUsages autour d’Ansible chez ikoula
Usages autour d’Ansible chez ikoulaNicolas Trauwaen
 

Similaire à GWT : under the hood (20)

Vert.x 3
Vert.x 3Vert.x 3
Vert.x 3
 
Présentation Javascript à l'ESI (Alger)
Présentation Javascript à l'ESI (Alger)Présentation Javascript à l'ESI (Alger)
Présentation Javascript à l'ESI (Alger)
 
Cours du soir_gwt
Cours du soir_gwtCours du soir_gwt
Cours du soir_gwt
 
Gwt fast overview_v1
Gwt fast overview_v1Gwt fast overview_v1
Gwt fast overview_v1
 
Marzouk une introduction à jdbc
Marzouk une introduction à jdbcMarzouk une introduction à jdbc
Marzouk une introduction à jdbc
 
Présentation de Django @ Orange Labs (FR)
Présentation de Django @ Orange Labs (FR)Présentation de Django @ Orange Labs (FR)
Présentation de Django @ Orange Labs (FR)
 
Présentation nouveauté java7
Présentation nouveauté java7Présentation nouveauté java7
Présentation nouveauté java7
 
Node.js, le pavé dans la mare
Node.js, le pavé dans la mareNode.js, le pavé dans la mare
Node.js, le pavé dans la mare
 
ENIB cours CAI Web - Séance 3 - JSP/Servlet - Cours
ENIB cours CAI Web - Séance 3 - JSP/Servlet - CoursENIB cours CAI Web - Séance 3 - JSP/Servlet - Cours
ENIB cours CAI Web - Séance 3 - JSP/Servlet - Cours
 
Activity
ActivityActivity
Activity
 
Symfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 PerformantSymfony2 - Un Framework PHP 5 Performant
Symfony2 - Un Framework PHP 5 Performant
 
GWT Approfondissement - GTI780 & MTI780 - ETS - A08
GWT Approfondissement - GTI780 & MTI780 - ETS - A08GWT Approfondissement - GTI780 & MTI780 - ETS - A08
GWT Approfondissement - GTI780 & MTI780 - ETS - A08
 
Automatisez vos tâches répétitives avec Grunt (Blend 2013)
Automatisez vos tâches répétitives avec Grunt (Blend 2013)Automatisez vos tâches répétitives avec Grunt (Blend 2013)
Automatisez vos tâches répétitives avec Grunt (Blend 2013)
 
Gwt jetty et sources de données
Gwt   jetty et sources de donnéesGwt   jetty et sources de données
Gwt jetty et sources de données
 
iTunes Stats
iTunes StatsiTunes Stats
iTunes Stats
 
Apache ANT
Apache ANTApache ANT
Apache ANT
 
Aperçu de RequireJS
Aperçu de RequireJSAperçu de RequireJS
Aperçu de RequireJS
 
react-slides.ppx (2) (1).pptx react presentation basic
react-slides.ppx (2) (1).pptx react presentation basicreact-slides.ppx (2) (1).pptx react presentation basic
react-slides.ppx (2) (1).pptx react presentation basic
 
Présentation Ansible Ikoula
Présentation Ansible IkoulaPrésentation Ansible Ikoula
Présentation Ansible Ikoula
 
Usages autour d’Ansible chez ikoula
Usages autour d’Ansible chez ikoulaUsages autour d’Ansible chez ikoula
Usages autour d’Ansible chez ikoula
 

GWT : under the hood

  • 1. Google Web Toolkit « Under the hood » Sébastien VUILLET Directeur technique Chez Silverpeas
  • 2. Plateforme collaborative La réalisation d'un Intranet/Extranet La gestion documentaire (GED) La gestion d'une banque d'images La gestion documentaire de projets La gestion de connaissances Et plus encore ... www.silverpeas.com www.silverpeas.org
  • 3. Version mobile Power by www.silverpeas.com www.silverpeas.org
  • 4. État des lieux Le développement d'applications web c'est quoi ? Différents langages : HTML + CSS + JavaScript + Java Différents formats d'échanges : XML, Json ... Différents environnement d’exécution : Desktop, smatphone, tablette Différents moteurs d’exécution : IE, FF, ... Utilisation de langages interprétés
  • 5. État des lieux Au final développer une webapp ce n'est toujours pas facile !
  • 6. GWT - Définition Ensemble d'outils Abstraction : du développement JavaScript de l'environnement d’exécution « One to rule them all » Un langage : Java
  • 8. GWT - Compilateur Étape Java AST -> Optimized Java AST : Pruning : suppression des classes / interfaces / méthodes / attributs non référencés. Finalizing : rend les méthodes, les classes et les variables final si c'est possible. Make Static : rend statiques les méthodes d'instances si possible (pas de surcharge, n'utilise pas de variables d'instance).
  • 9. GWT - Compilateur Étape Java AST -> Optimized Java AST : Type Tightening : optimisation des attributs et paramètres pour les rendre concrets (pour réduire les opérateurs cast et instanceof). Method Call Tightening : changement des appels de méthodes polymorphiques, en appel direct. Dead Code Elimination : suppression des portions de code qui n'est jamais appelé (condition jamais
  • 10. GWT - Compilateur Étape Java AST -> Optimized Java AST : Method Inlining : suppression des méthodes non référencés dans une classe extérieure et embarquement du code directement dans à l'endroit de l'appel (si la méthode n’excède pas deux lignes). Same Parameter Value Optimizer Enum Ordinalizer : remplace les références aux
  • 11. GWT - Compilateur Étape Java AST -> Optimized Java AST : Remove Empty Super Calls Set of Normalization Rules : transformation du code pour que la génération du JavaScript soit optimale (fusion des blocs catch, utilisation d'array). Remplacement des appels aux classes du JDK par de les classes de com.google.gwt.lang.
  • 12. GWT - Compilateur Étape Java AST -> Optimized Java AST : arbre « unifié », car il n'est lié à aucune permutation
  • 13. GWT – Compilateur Les permutations Télécharge uniquement la version nécessaire au navigateur client Un seul code Java … puis le met en cache indéfiniment
  • 14. GWT - Compilateur Possibilité de désactiver les optimisations : Paramètre : -draftCompile Réglage du code généré : Paramètre : -style (OBF, PRETTY, DETAILED) Amélioration des temps de compilation : Paramètre : -localWorkers Limiter les permutations : <set-property name="user.agent" value="gecko"/>
  • 15. GWT - Compilateur Code généré par défaut : function qH(){return np} function mH(){} _=mH.prototype=new mu;_.gC=qH;_.tI=0;function uH(){uH=ZH;sH={};tH=[];sH[LM]=[Is,Hs,Js];sH[JM]=[rt,qt,st];Xv(tH,yn,LM);Xv(tH,To,JM)} var sH,tH;function AH(a){a.b=oH(new mH);return a} function BH(a){var b,c,d,e,f,g,h,i,j,k;g=ox(new cx,MM);f=OA(new FA);j=XH(new VH,NM,OM);KA(f,j.b+sJ+j.c);pw(g.B,PM,true);Zw(gA(QM),f);Zw(gA(RM),g);f.B.focus() ;k=Jg(f.B,NJ).length;k>0&&JA(f,0,k);c=py(new my);Lf((tf(),c.b.B),SM);c.o=true; b=ox(new cx,TM);b.B.id=UM;i=Py(new Ny);h=Ty(new My);d=UA(new RA);pw(d.B,VM,true); VA(d,Uy(new My,WM));VA(d,i);VA(d,Uy(new My,XM));VA(d,h);d.b=(kz(),jz);VA(d,b); Ax(c.j,d);Mx(c);vw(b,FH(new DH,c,g),(sh(),rh));e=KH(new IH,a,g,f,i,h,c,b); vw(g,e,rh);vw(f,e,(hi(),gi))} function CH(){return rp} function xH(){}
  • 16. GWT - Compilateur Code généré en style pretty : var $wnd = parent; var $doc = $wnd.document; var $moduleName, $moduleBase; var $strongName = '21B409FCD39529C5A9DB925F7D8D9A95'; var $stats = $wnd.__gwtStatsEvent ? function(a) {return $wnd.__gwtStatsEvent(a);} : null; $stats && $stats({moduleName:'gwtperf',subSystem:'startup',evtGroup: 'moduleStartup',millis:(new Date()).getTime(),type:'moduleEvalStart'}); var _; function nullMethod(){ } function equals(other){ return this === (other == null?null:other); } function getClass_0(){ return Ljava_lang_Object_2_classLit; } function hashCode_0(){ return this.$H || (this.$H = ++sNextHashId); } function toString_0(){ return (this.typeMarker$ == nullMethod || this.typeId$ == 2?this.getClass$():Lcom_google_gwt_core_client_JavaScriptObject_2_classLit) .typeName + '@' + toPowerOfTwoString(this.typeMarker$ == nullMethod || this.typeId$ == 2?this.hashCode$():this.$H || (this.$H = ++sNextHashId), 4); } function Object_0(){ } _ = Object_0.prototype = {}; _.equals$ = equals; _.getClass$ = getClass_0; _.hashCode$ = hashCode_0; _.toString$ = toString_0; _.toString = function(){ return this.toString$(); } ;
  • 19. GWT – Deferred binding Le Deferred Binding consiste à effectuer l’insertion de la classe demandée à la compilation et non durant l’exécution du programme. Deux implémentation de Deferred Binding Replacement : une classe est remplacée par une autre sous certaines conditions Generators : les classes qui héritent d’une classe particulière sont générées et remplacées sous certaines conditions
  • 20. GWT – Deferred binding Replacement : Configuration du module
  • 21. GWT – Deferred binding Generators : Classes invoquées par le compilateur GWT pour générer l’implémentation d’un classe java Pour la compilation en mode web, l’implémentation générée est directement traduite en Javascript Configuration du module : Créer un générateur
  • 22. GWT – Linkers Assurent le packaging Exemples de linkers : IframeLinker (défaut) : génère une Iframe cachée XSLinker : produit des fichiers d'extension xs comme <module>-xs.nocache.js (cas des permutations hébergés sur un autre serveur que les pages hôtes). SingleScriptLinker : génère un seul fichier Java- Script pour un module. Il n'existe qu'une seule permutation.
  • 23. GWT – Linkers Utilisation des linkers : <module> (...) <define-linker name="sso" class="com.google.gwt.core.linker.SingleScriptLinker" /> <define-linker name="std" class="com.google.gwt.core.linker.IFrameLinker" /> <define-linker name="xs" class="com.google.gwt.core.linker.XSLinker" /> <define-linker name="soycReport" class="com.google.gwt.core.linker.SoycReportLinker" /> <define-linker name="symbolMaps" class="com.google.gwt.core.linker.SymbolMapsLinker" / > <add-linker name="std" /> <add-linker name="soycReport" /> <add-linker name="symbolMaps" /> </module>
  • 24. GWT – Linkers Créer un linker : Créer une classe dérivant de com.google.gwt.core.ext.Linker. Ajouter l'annotation @LinkOrder pour déterminer si le linker doit s'exécuter avant, après ou en remplacement du linker primaire. Le nombre de linkers n'est pas limité, seul le primaire est unique. Définir et ajouter le linker personnalisé dans le fichier de configuration du module (<module>.gwt.xml). Inclure dans le classpath du compilateur le nouveau
  • 25. GWT – Linkers Exemple de linker : @LinkerOrder(LinkerOrder.Order.POST) public class MyLinker extends AbstractLinker { public String getDescription() { return "MyLinker"; } public ArtifactSet link(TreeLogger logger, LinkerContext context, ArtifactSet artifacts) throws UnableToCompleteException { String artifactList=""; // Récupère la liste de tous les artéfacts ArtifactSet toReturn = new ArtifactSet(artifacts); for (Artifact artifact : toReturn) { // Et trie seulement les fichiers générés if (artifact instanceof EmittedArtifact) { EmittedArtifact fic = (EmittedArtifact) artifact; // Stocke dans une chaîne de caractères le nom du fichier généré artifactList = fic.getPartialPath() + "," + new Date(fic.getLastModified()).toString() + "n" + artifactList ; } } // Ajoute à la liste précédente un nouveau fichier recensant // les artéfacts toReturn.add(emitString(logger, artifactList, "ListFiles.txt")); return toReturn; } }
  • 27. GWT – perfect caching
  • 28. GWT – code splitting Découpage en fragments JavaScript pour téléchargement à la demande GWT.runAsync(SomeClass.class, new RunAsyncCallback() { // ... callback class's body ... } Séquence <extend-configuration-property name="compiler.splitpoint.initial.sequence" value="com.yourcompany.yourprogram.SomeClass"/> <extend-configuration-property name="compiler.splitpoint.initial.sequence" value="com.yourcompany.yourprogram.AnotherClassClass"/> <extend-configuration-property name="compiler.splitpoint.initial.sequence" value="com.yourcompany.yourprogram.YetAnotherClass"/>
  • 30. GWT - JRE Emulation Types primitifs Annotations Exception Assertion Serialization Packages : java.lang java.math java.io
  • 31. GWT - JRE Emulation Non supporté Multithreading (pour l'instant) Gestion de la concurrence (pour l'instant) Finalisation des objets Réflexion
  • 32. GWT - JRE Emulation Étendre la JRE Emulation : Ex : Timestamp <module> ... <!-- JRE Classes not Emulated by GWT --> <super-source path='jre'/> </module> Serializer : Timestamp_CustomFieldSerializer public static void serialize(SerializationStreamWriter streamWriter, MyObject myObject) throws SerializationException {} public static void deserialize(SerializationStreamReader streamReader, MyObject myObject) throws SerializationException {} //This method is optional public static MyObject instantiate(SerializationStreamReader streamReader) throws SerializationException {}
  • 33. GWT - tools Environnement de développement Google plugin pour Eclipse, GWT Designer Debug dans Eclipse avec dev mode et les plugins navigateurs Optimisation SpeedTracer, Soyc Build Maven plugin Tests HtmlUnit, Selenium,...
  • 34. GWT - synthèse Pas un framework : beaucoup plus gwt-user.jar Le Framework gwt-dev-[platform].jar Les outils
  • 36. GWT - performances Client Bundle CSS resources Image resources Data resources Text resources
  • 37. GWT - performances Client Bundle public interface MyResources extends ClientBundle { public static final MyResources INSTANCE = GWT.create(MyResources.class); @Source("my.css") public CssResource css(); @Source("config.xml") public TextResource initialConfiguration(); @Source("manual.pdf") public DataResource ownersManual(); @Source("default.txt") public TextResource defaultText(); } I18N compatible
  • 38. GWT - performances Client Bundle : image resources interface Resources extends ClientBundle { @Source("logo.png") ImageResource logo(); @Source("arrow.png") @ImageOptions(flipRtl = true) ImageResource pointer(); } Resources resources = GWT.create(Resources.class); Image img = new Image(resources.logo());
  • 39. GWT - performances Client Bundle : image resources
  • 40. GWT - performances Chargement des images sans Client Bundle
  • 41. GWT - performances Client Bundle : CSS ressources interface MyResources extends CssResource { String myStyleName(); } Fonctionnalités Constantes @def small 1px; @def black #000; border: small solid black; Substitution au runtime @eval userBackground com.module.UserPreferences.getUserBackground(); div { background: userBackground; }
  • 42. GWT - performances Client Bundle : CSS ressources interface MyResources extends CssResource { String myStyleName(); } Fonctionnalités Constantes @def small 1px; @def black #000; border: small solid black; Substitution au runtime @eval userBackground com.module.UserPreferences.getUserBackground(); div { background: userBackground; }
  • 43. GWT - performances Client Bundle : CSS ressources Fonctionnalités Value function .myDiv { offset-left: value('imageResource.getWidth', 'px'); } Literal function div-with-literal { top: literal("expression(document.compatMode=="CSS1Compat" ? documentElement.scrollTop : document.body.scrollTop 2)"); }
  • 44. GWT - performances Client Bundle : CSS ressources Fonctionnalités /* Runtime evaluation in a static context */ Conditions @if (com.module.Foo.staticBooleanFunction()) { ... css rules ... } /* Compile-time evaluation */ @if <deferred-binding-property> <space-separated list of values> { ... css rules ... } @if user.agent safari gecko1_8 { ... } @if locale en { ... } /* Negation is supported */ @if !user.agent ie6 opera { } /* Chaining is also supported */ @if (true) { } @elif (false) { } @else { }
  • 45. GWT - performances Client Bundle : CSS ressources Fonctionnalités Images sprites public interface DocumentsResources extends ClientBundle { @Source("documents.css") DocumentsCSS css(); @Source("instances.png") ImageResource instances(); } public interface DocumentsCSS extends CssResource { String instances(); } @sprite .instances { gwt-image: "instances"; border: none; }
  • 46. GWT – Bilan de l'approche Perfect caching Client Bundle Data : URLs & MHTML packaging Developer guided code splitting
  • 47. GWT - Développements JSNI <=> JNI Ouverture et intégration Fonctionnalités Invoquer du JavaScript natif depuis du code Java public static native void alert(String msg) /*-{ $wnd.alert(msg); }-*/;
  • 48. GWT - Développements JSNI Invoquez une méthode Java depuis du code javaScript externe //La fonction Java qu'on peut appeler depuis javaScript public static int maFonctionJava(int param) { ... } public static native void exportationMaFonction() /*-{ //On assigne notre méthode // à la variable globale maFonctionJava de notre objet window $wnd.maFonctionJava = $entry(@com.silverpeas.jsni.client::maFonctionJava(I)); }-*/
  • 49. GWT - Développements Communication avec le serveur Plusieurs approches : RequestBuilder + JSONParser (resty-gwt) RequestBuilder + XMLParser GWT-RPC RequestFactory (depuis GWT 2.1)
  • 50. GWT - Développements Communication avec le serveur GWT-RPC @RemoteServiceRelativePath("Contact") public interface ServiceContact extends RemoteService { List<DetailUserDTO> getAllContact() throws ContactException; } public class ServiceContactImpl extends AbstractAuthenticateService implements ServiceContact { public List<DetailUserDTO> getAllContact() throws ContactException { ... } }
  • 51. GWT - Développements Communication avec le serveur GWT-RPC public interface ServiceContactAsync { void getAllContact(AsyncCallback<List<DetailUserDTO>> callback); } web.xml <servlet> <servlet-name>serviceContactImpl</servlet-name> <servlet-class>com.silverpeas.mobile.server.services.ServiceContactImpl</servlet- class> </servlet> <servlet-mapping> <servlet-name>serviceContactImpl</servlet-name> <url-pattern>/spmobil/Contact</url-pattern> </servlet-mapping>
  • 52. GWT - Développements Communication avec le serveur GWT-RPC : appel ServiceContactAsync serviceContact = (ServiceContactAsync) GWT.create(ServiceContact.class); serviceContact.getAllContact(new AsyncCallback<List<DetailUserDTO>>() { @Override public void onFailure(Throwable caught) { ... } @Override public void onSuccess(List<DetailUserDTO> result) { ... } });
  • 53. GWT - Développements Communication avec le serveur GWT-RPC : architecture
  • 54. GWT - Développements Communication avec le serveur GWT-RPC : Simple et puissant Envoie / réception de POJO Support du polymorphisme Transfert optimisés (plus léger que JSON) Sécurité (pas de risque de JavaScript hijacking/JSON attack)
  • 55. GWT - Développements Communication avec le serveur RequestFactory Pour les services orientés données Niveau d’abstraction plus important que GWT-RPC Plus rapide que GWT-RPC Basé sur JSON : pas de sérialisation/déserialisation Envoi uniquement du différentiel de données Réponse aux problèmes Entity / DTO
  • 56. GWT - Développements Communication avec le serveur RequestFactory : Entity proxies @Entity public class Employee { @ProxyFor(Employee.class) public interface EmployeeProxy @Size(min = 3, max = 30) extends EntityProxy { private String userName; Long getId(); @Id private Long id; String getUserName(); @Version void setUserName(String userName); private Integer version; ... ... } }
  • 57. GWT - Développements Communication avec le serveur RequestFactory : Value proxies public interface AddressProxy extends ValueProxy public class Address { { private String street1; public String getStreet1(); private String street2; public String getStreet2(); private String city; public String getCity(); private String st; public String getSt(); private String zip; public String getZip(); ... ... } }
  • 58. GWT - Développements Communication avec le serveur RequestFactory public interface ExpensesRequestFactory extends RequestFactory { EmployeeRequest employeeRequest(); ... } @Service(Employee.class) public interface EmployeeRequest extends RequestContext { Request<Long> countEmployees(); Request<List<EmployeeProxy>> findAllEmployees(); Request<EmployeeProxy> findEmployee(Long id); InstanceRequest<EmployeeProxy, Void> persist(); InstanceRequest<EmployeeProxy, Void> remove(); }
  • 59. GWT - Développements Communication avec le serveur RequestFactory final EventBus eventBus = new SimpleEventBus(); requestFactory = GWT.create(ExpensesRequestFactory.class); requestFactory.initialize(eventBus); requestFactory.employeeRequest().findEmployee(employeeId).fire( new Receiver<EmployeeProxy>() { @Override public void onSuccess(EmployeeProxy employee) { ... } }); EmployeeRequest request = requestFactory.employeeRequest(); EmployeeProxy newEmployee = request.create(EmployeeProxy.class); newEmployee.setDisplayName(...); newEmployee.setDepartment(...); ... Request<Void> createReq = request.persist().using(newEmployee);
  • 60. GWT - Développements Communication avec le serveur RequestFactory : entity validation JSR 303 support Envoi de violation de contraintes au client Appel de la méthode onViolation() du Receiver
  • 61. GWT - Développements Des logs dans le browser GWT logging # Dans le fichier .gwt.xml <inherits name="com.google.gwt.logging.Logging"/> Logger logger = Logger.getLogger("monLogger"); logger.log(Level.SEVERE, "impossible de contacter le serveur");
  • 62. GWT - Développements Des logs dans le browser GWT logging : loggers private static Logger childLogger = Logger.getLogger("ParentLogger.Child"); private static Logger parentLogger = Logger.getLogger("ParentLogger"); private static Logger rootLogger = Logger.getLogger(""); Configuration <set-property name="gwt.logging.logLevel" value="SEVERE"/> <set-property name="gwt.logging.enabled" value="FALSE"/> <set-property name="gwt.logging.consoleHandler" value="DISABLED"/>
  • 63. GWT - Développements Des logs dans le browser GWT logging : handlers SystemLogHandler : stdout (seulement en DevMode) DevelopmentModeLogHandler : sur appel de la méthode GWT.log (seulement en DevMode) ConsoleLogHandler : javascript console FirebugLogHandler : firebug PopupLogHandler : popup SimpleRemoteLogHandler : envoi au serveur (via GWT- RPC)
  • 65. GWT - Développements Approche de développement par composants En java : « comme Swing » Widgets et placement par Panels et Layouts Avantages : abstraction de l'html / javascript (DOM/event/memory) programmation événementielle refactoring Inconvénients :
  • 66. GWT - Développements Les widgets Intégrés : com.google.gwt.user.client.ui
  • 67. GWT - Développements Les widgets Bibliothèques additionnelles gwt-mosaic Sencha GXT Smartgwt (wrapper) Gwtmobile Gwt-links Gwt-cal GwtGL
  • 68. GWT - Développements Les widgets Construire ses propres widgets Trois possibilités pour créer ses propres composants : Créer un widget avec des widgets existants Héritage de com.google.gwt.user.client.ui.Composite Créer un widget nouveau sans composition Héritage de com.google.gwt.user.client.ui.Widget Créér un widget qui « wrap » du code JavaScript en utilisation using JSNI
  • 69. GWT - Développements Les widgets : construire ses propres widgets public class OptionalTextBox extends Composite implements ClickHandler { private TextBox textBox = new TextBox(); private CheckBox checkBox = new CheckBox(); public OptionalTextBox(String caption) { VerticalPanel panel = new VerticalPanel(); panel.add(checkBox); panel.add(textBox); checkBox.setText(caption); checkBox.setChecked(true); checkBox.addClickHandler(this); } public void onClick(ClickEvent event) { Object sender = event.getSource(); if (sender == checkBox) { textBox.setEnabled(checkBox.isChecked()); } } }
  • 70. GWT - Développements Les widgets : construire ses propres widgets public class OptionalTextBox extends Composite implements ClickHandler { private TextBox textBox = new TextBox(); private CheckBox checkBox = new CheckBox(); public OptionalTextBox(String caption) { VerticalPanel panel = new VerticalPanel(); panel.add(checkBox); panel.add(textBox); checkBox.setText(caption); checkBox.setChecked(true); checkBox.addClickHandler(this); } public void onClick(ClickEvent event) { Object sender = event.getSource(); if (sender == checkBox) { textBox.setEnabled(checkBox.isChecked()); } } }
  • 71. GWT - Développements Ui-binder (depuis GWT 2.0) : declarative UI Description des vues en XML Binding XML (*.ui.xml) / Java (*.java) <ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'> <g:HTMLPanel> Gagnant, <g:ListBox ui:field='listBox' visibleItemCount='1'/>. </g:HTMLPanel> </ui:UiBinder>
  • 72. GWT - Développements Ui-binder (depuis GWT 2.0) : declarative UI public class HelloWidgetWorld extends Composite { interface MyUiBinder extends UiBinder<Widget, HelloWidgetWorld> {} private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class); @UiField ListBox listBox; public HelloWidgetWorld(String... names) { // sets listBox initWidget(uiBinder.createAndBindUi(this)); for (String name : names) { listBox.addItem(name); } } }
  • 73. GWT - Développements Ui-binder (depuis GWT 2.0) : declarative UI Annotations @UiField @UiHandler @UiFactory @UiConstructor @UiTemplate("mobile.ui.xml") Ressources externes <ui:with field='res' type='com.silverpeas.ged.Resources'/> @UiField(provided = true)
  • 74. GWT - Développements Editors (depuis GWT 2.1) <inherits name="com.google.gwt.editor.Editor" /> POJO Editor (généralement un widget) Driver SimpleBeanEditorDriver RequestFactoryEditorDriver Adapter
  • 75. GWT - Développements Editors public class PersonEditor extends Composite implements Editor<Person> { interface Binder extends UiBinder<Widget, PersonEditor> {} private static final Binder BINDER = GWT.create(Binder.class); @UiField TextBox firstName; @UiField TextBox lastName; @UiField AddressEditor address; public PersonEditor() { initWidget(BINDER.createAndBindUi(this)); } } Annotations @path et @ignored
  • 76. GWT - Développements Editors public class PersonView extends Composite { interface Binder extends UiBinder<Widget, PersonView> {} interface EditorDriver extends SimpleBeanEditorDriver<Person, PersonEditor> {} private final Binder BINDER = GWT.Create(Binder.class); private final PersonServiceAsync RPC = GWT.create(PersonService.class); private final EditorDriver editorDriver = GWT.create(EditorDriver.class); @UiField PersonEditor editor; @UiField Button save; @UiField Button cancel; public PersonView() { initWidget(BINDER.createAndBindUi(this)); }
  • 77. GWT - Développements Editors public void edit(String id) { RPC.getPerson(id, new AsyncCallback<Person>() { @Override public void onSuccess(Person person) { editorDriver.edit(person); } @Override public void onFailure(Throwable e) { ... } }); }
  • 78. GWT - Développements Editors @UiHandler("save") void onSaveClick(ClickEvent event) { If (! editorDriver.hasErrors()) { Person person = editorDriver.flush(); RPC.savePerson(this.value, new AsyncCallback<Void>() { @Override public void onSuccess(Person person) { ... } @Override public void onFailure(Throwable e) { ... } }); } else { List<EditorError> errors = editorDriver.getErrors() ; ... } } }
  • 79. GWT - Développements HTML5 (depuis GWT 2.3) Intégration progressive Événements multi-touch Drag & drop LocalStorage & SessionStorage Canvas Audio (expérimentale) Vidéo (expérimentale)
  • 80. GWT - Développements Patterns MVC : implémentation PureMVC
  • 81. GWT - Développements Patterns EventBus SimpleEventBus ResettableEventBus CountingEventBus
  • 82. GWT - Développements Patterns EventBus : handler public interface DocumentsControllerEventHandler extends EventHandler { void loadSettings(DocumentsLoadSettingsEvent event); void saveSettings(DocumentsSaveSettingsEvent event); void loadTopics(DocumentsLoadTopicsEvent event); void loadPublications(DocumentsLoadPublicationsEvent event); void loadPublication(DocumentsLoadPublicationEvent event); }
  • 83. GWT - Développements Patterns EventBus : event public abstract class AbstractDocumentsControllerEvent extends GwtEvent<DocumentsControllerEventHandler> { public static Type<DocumentsControllerEventHandler> TYPE = new Type<DocumentsControllerEventHandler>(); public AbstractDocumentsControllerEvent() { } @Override public GwtEvent.Type<DocumentsControllerEventHandler> getAssociatedType() { return TYPE; } }
  • 84. GWT - Développements Patterns EventBus : event public class DocumentsSaveSettingsEvent extends AbstractDocumentsControllerEvent { private ApplicationInstanceDTO instance; private TopicDTO topic; public DocumentsSaveSettingsEvent(ApplicationInstanceDTO instance, TopicDTO topic) { super(); this.instance = instance; this.topic = topic; } @Override protected void dispatch(DocumentsControllerEventHandler handler) { handler.saveSettings(this); } public ApplicationInstanceDTO getInstance() { return instance; } public TopicDTO getTopic() { return topic; } }
  • 85. GWT - Développements Patterns EventBus Abonnement EventBus.getInstance().addHandler(AbstractDocumentsControllerEvent.TYPE, this); Désabonnement EventBus.getInstance().removeHandler(AbstractDocumentsControllerEvent.TYPE, this); Lancement EventBus.getInstance().fireEvent( new DocumentsSaveSettingsEvent(currentInstance, currentTopic));
  • 86. GWT - Développements Patterns MVP : intégré depuis GWT 2.1
  • 87. GWT - Développements Patterns MVP : navigation public class AppActivityMapper implements ActivityMapper { private ClientFactory clientFactory; public AppActivityMapper(ClientFactory clientFactory) { super(); this.clientFactory = clientFactory; } @Override public Activity getActivity(Place place) { if (place instanceof HelloPlace) return new HelloActivity((HelloPlace) place, clientFactory); else if (place instanceof GoodbyePlace) return new GoodbyeActivity((GoodbyePlace) place, clientFactory); return null; } }
  • 88. GWT - Développements Des APIs pour aller plus loin Internationalisation Sécurité Accessibilité Tests ...
  • 89. GWT - Développements Des bibliothèques pour aller plus loin Gin : injection client-side Gwt-ent : AOP, Reflexion, ... Gwt-dnd Gwt-comet Crypto-gwt Gwt-voices Gquery
  • 90. Uses cases Application web single page Caractéristiques : Non server-centric Webapp légère : un conteneur de servlets suffit pas de compilation des pages par le serveur d'applications Application ou site web multi page Caractéristiques : Server-centric : jsp, jsf, php, html Frameworks additionnels : vaadin Application dans le cloud
  • 92. Que s'est il passé depuis 2006 ? Novembre 2011 : Abandon de flex par adobe Abandon de Silverlight par Microsoft HTML5 plébiscité par le ténors du web
  • 93. Que s'est il passé depuis 2006 ? Adoption massive des smartphones Explosion des applications mobiles natives
  • 94. La suite : GWT 2.5 Amélioration du noyau : Optimisation du compilateur : 30 % de réduction du code non compressé et 15 % avec compression gzip Support de SourceMap et Source-Level : java debugging dans Chrome (Firefox à venir)
  • 96. Merci de votre attention

Notes de l'éditeur

  1. Le modèle de développement d&apos;applications à énormément évolué depuis une décennie. Les technologies web se sont imposées et ont évoluées. Les applications web offrent de plus en plus de services, elles sont de plus en plus ergonomiques et performantes. Mais qu&apos;en est-il du quotidien du développeur ? Les outils de développement ont-ils évolués ? Il y a 6 ans l&apos;ovni GWT faisait son apparition, avec pour objectif de facilité le développement d&apos;applications web sophistiqués La vision révolutionnaire de ses deux concepteurs a mit du temps a être accepté. De nos jours comment a évolué GWT ? Qui l&apos;utilise ? La vision de Bruce Johnson et de Joel Webber a-t-elle supporté l&apos;épreuve du temps ? Cette présentation tentera de répondre à ces questions, en présentant ce que GWT a dans le ventre.