Your SlideShare is downloading. ×
GWT : under the hood
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Saving this for later?

Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime - even offline.

Text the download link to your phone

Standard text messaging rates apply

GWT : under the hood

4,615
views

Published on

Published in: Technology

0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,615
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
0
Comments
0
Likes
3
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • Le modèle de développement d'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'en est-il du quotidien du développeur ? Les outils de développement ont-ils évolués ? Il y a 6 ans l'ovni GWT faisait son apparition, avec pour objectif de facilité le développement d'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'utilise ? La vision de Bruce Johnson et de Joel Webber a-t-elle supporté l'épreuve du temps ? Cette présentation tentera de répondre à ces questions, en présentant ce que GWT a dans le ventre.
  • Transcript

    • 1. Google Web Toolkit« Under the hood » Sébastien VUILLET Directeur technique Chez Silverpeas
    • 2. Plateforme collaborative La réalisation dun Intranet/Extranet La gestion documentaire (GED) La gestion dune banque dimages 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 lieuxLe développement dapplications web cest 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 lieuxAu final développer une webapp ce nest toujours pas facile !
    • 6. GWT - DéfinitionEnsemble doutilsAbstraction : du développement JavaScript de lenvironnement d’exécution« One to rule them all » Un langage : Java
    • 7. GWT MasterpieceLe compilateur
    • 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 cest possible. Make Static : rend statiques les méthodes dinstances si possible (pas de surcharge, nutilise pas de variables dinstance).
    • 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 nest 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 à lendroit de lappel (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 darray). 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 nest lié à aucune permutation
    • 13. GWT – CompilateurLes 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 - CompilateurPossibilité de désactiver les optimisations : Paramètre : -draftCompileRé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 - CompilateurCode généré par défaut :function qH(){return np}function mH(){}_=mH.prototype=new mu;_.gC=qH;_.tI=0;functionuH(){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 - CompilateurCode 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$();};
    • 17. GWT - CompilateurObfuscation VS pretty :
    • 18. GWT – build
    • 19. GWT – Deferred bindingLe 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 bindingReplacement : Configuration du module
    • 21. GWT – Deferred bindingGenerators : 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 – LinkersAssurent le packagingExemples de linkers : IframeLinker (défaut) : génère une Iframe cachée XSLinker : produit des fichiers dextension 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 nexiste quune 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 – LinkersCréer un linker : Créer une classe dérivant de com.google.gwt.core.ext.Linker. Ajouter lannotation @LinkOrder pour déterminer si le linker doit sexécuter avant, après ou en remplacement du linker primaire. Le nombre de linkers nest 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; }}
    • 26. GWT – runtime
    • 27. GWT – perfect caching
    • 28. GWT – code splittingDécoupage en fragments JavaScript pour téléchargement à la demande GWT.runAsync(SomeClass.class, new RunAsyncCallback() { // ... callback classs 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"/>
    • 29. GWT - Architecture
    • 30. GWT - JRE EmulationTypes primitifsAnnotationsExceptionAssertionSerializationPackages : java.lang java.math java.io
    • 31. GWT - JRE EmulationNon supporté Multithreading (pour linstant) Gestion de la concurrence (pour linstant) 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 - toolsEnvironnement de développement Google plugin pour Eclipse, GWT DesignerDebug dans Eclipse avec dev mode et les plugins navigateursOptimisation SpeedTracer, SoycBuild Maven pluginTests HtmlUnit, Selenium,...
    • 34. GWT - synthèsePas un framework : beaucoup plus gwt-user.jar Le Framework gwt-dev-[platform].jar Les outils
    • 35. GWT - performances
    • 36. GWT - performancesClient Bundle CSS resources Image resources Data resources Text resources
    • 37. GWT - performancesClient 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 - performancesClient 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 - performancesClient Bundle : image resources
    • 40. GWT - performancesChargement des images sans Client Bundle
    • 41. GWT - performancesClient 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 - performancesClient 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 - performancesClient 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 - performancesClient 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 - performancesClient 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 lapprochePerfect cachingClient BundleData : URLs & MHTML packagingDeveloper guided code splitting
    • 47. GWT - DéveloppementsJSNI <=> JNI Ouverture et intégrationFonctionnalités Invoquer du JavaScript natif depuis du code Java public static native void alert(String msg) /*-{ $wnd.alert(msg); }-*/;
    • 48. GWT - DéveloppementsJSNI Invoquez une méthode Java depuis du code javaScript externe //La fonction Java quon 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éveloppementsCommunication avec le serveur Plusieurs approches : RequestBuilder + JSONParser (resty-gwt) RequestBuilder + XMLParser GWT-RPC RequestFactory (depuis GWT 2.1)
    • 50. GWT - DéveloppementsCommunication 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éveloppementsCommunication 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éveloppementsCommunication avec le serveur GWT-RPC : architecture
    • 54. GWT - DéveloppementsCommunication 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éveloppementsCommunication 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éveloppementsCommunication 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éveloppementsCommunication 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éveloppementsCommunication 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éveloppementsCommunication 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éveloppementsCommunication 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éveloppementsDes 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éveloppementsDes 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éveloppementsDes 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)
    • 64. GWT - DéveloppementsEt la GUI ?
    • 65. GWT - DéveloppementsApproche de développement par composants En java : « comme Swing » Widgets et placement par Panels et LayoutsAvantages : abstraction de lhtml / javascript (DOM/event/memory) programmation événementielle refactoringInconvénients :
    • 66. GWT - DéveloppementsLes widgets Intégrés : com.google.gwt.user.client.ui
    • 67. GWT - DéveloppementsLes 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 widgetsTrois possibilités pour créer ses propres composants :Créer un widget avec des widgets existantsHéritage de com.google.gwt.user.client.ui.CompositeCréer un widget nouveau sans compositionHéritage de com.google.gwt.user.client.ui.WidgetCréér un widget qui « wrap » du code JavaScript en utilisation using JSNI
    • 69. GWT - DéveloppementsLes 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éveloppementsLes 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éveloppementsUi-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éveloppementsUi-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éveloppementsUi-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éveloppementsEditors (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éveloppementsEditors 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éveloppementsEditors 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éveloppementsEditors 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éveloppementsEditors @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éveloppementsHTML5 (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éveloppementsPatterns MVC : implémentation PureMVC
    • 81. GWT - DéveloppementsPatterns EventBus SimpleEventBus ResettableEventBus CountingEventBus
    • 82. GWT - DéveloppementsPatterns 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éveloppementsPatterns 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éveloppementsPatterns 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éveloppementsPatterns 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éveloppementsPatterns MVP : intégré depuis GWT 2.1
    • 87. GWT - Développements Patterns MVP : navigationpublic 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éveloppementsDes APIs pour aller plus loin Internationalisation Sécurité Accessibilité Tests ...
    • 89. GWT - DéveloppementsDes 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 casesApplication 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 dapplicationsApplication ou site web multi page Caractéristiques : Server-centric : jsp, jsf, php, html Frameworks additionnels : vaadinApplication dans le cloud
    • 91. Qui utilise GWT ?
    • 92. Que sest il passé depuis 2006 ?Novembre 2011 : Abandon de flex par adobe Abandon de Silverlight par MicrosoftHTML5 plébiscité par le ténors du web
    • 93. Que sest il passé depuis 2006 ?Adoption massive des smartphonesExplosion des applications mobiles natives
    • 94. La suite : GWT 2.5Amé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)
    • 95. Futur...
    • 96. Merci de votre attention