• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Presentation of GWT 2.4 (PowerPoint version)
 

Presentation of GWT 2.4 (PowerPoint version)

on

  • 3,708 views

My presentation of GWT 2.4 (in French).

My presentation of GWT 2.4 (in French).
Main topics : RPC, MVP, Activities and places, Dart, etc.
This is the PowerPoint version.

Statistics

Views

Total Views
3,708
Views on SlideShare
3,706
Embed Views
2

Actions

Likes
4
Downloads
0
Comments
1

2 Embeds 2

http://www.slashdocs.com 1
http://www.docshut.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

11 of 1 previous next

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

    Presentation of GWT 2.4 (PowerPoint version) Presentation of GWT 2.4 (PowerPoint version) Presentation Transcript

    • Présentation deGoogle Web Toolkit
    • Présentation de Google Web Toolkit• GWT (version 2.4)• Celinio Fernandes• juin 2012
    • Sommaire• Introduction • Design pattern• Historique MVP• Principe• Création d’un projet• Mode développement • Bonnes pratiques • L’EventBus• Les widgets• Widget composite • L’API Activities and• UiBinder Places • Le code splitting• Events et handlers• Les services distants RPC • Conclusion Celinio Fernandes
    • Introduction
    • Historique– Créé en 2006 par Bruce Johnson et Joel Webber– Rachat par Google de la startup créée par Bruce Johnson– Version 1.0 en 2006– Version 1.5 en 2008– Version 2.0 en 2009– Version 2.1 en 2010 (Activities and Places, Request Factory – une alternative à GWT RPC)– Version 2.2 en 2011 (update du widget CellTable)– Version 2.4 en septembre 2011– Version 2.5 prévue en 2012 (un SuperDevMode ?)– Release notes : https://developers.google.com/web-toolkit/release-notes Celinio Fernandes No. 5
    • Chronologie des frameworksSource : https://github.com/mraible/history-of-web-frameworks-timeline Celinio Fernandes
    • A quelle catégorie de frameworks appartient GWT ?• Catégorisation possible : – basés sur des requêtes : • Struts, Spring MVC, Wicket – basés sur des composants : • JSF, Tapestry, Vaadin – RIA : • Flex, JavaFX GWT un mix des deux dernières catégories ? • génère du code qui tourne côté client donc basé sur des composants ? • utilise des widgets donc RIA ? Celinio Fernandes No. 7
    • Principe• Un framework qui propose d’écrire une application en Java et de compiler ce code Java vers du HTML et du JavaScript nativement interprétable par les navigateurs web.Client Java JavaScript Compilateur GWT Services RPCServeur Services JavaPartie cliente : le code Java qui est au final compilé en JavaScript et qui est exécuté dans unbrowser.• N’utilisé, côté client, que des librairies de l’API Java qui peuvent êtrecompilées en JavaScript• Emulation partielle de JRE (java.lang.*, java.util.*, etc…) Celinio Fernandes No. 8
    • Plugin GWT pour Eclipse (1/3) • Renommé Google Plugin • Installation facile via l’URL • http://dl.google.com/eclipse/plugin/3.7 • (Eclipse 3.7 Indigo) • Permet de créer un projet GWT sous Eclipse • Permet de lancer une application en mode « developpement » Celinio Fernandes No. 9
    • Plugin GWT pour Eclipse (2/3)Application sample (1) Application sample (2) Celinio Fernandes
    • Plugin GWT pour Eclipse (3/3)Application sample (3) Application sample (4) Celinio Fernandes
    • Structure d’un projet / module GWT•Fichier de configuration du module :LabGWT.gwt.xml•Package client : code Java compilé enJavaScript (si spécifié par le tag <source> dufichier de configuration)•Package server : code Java non compilé enJavaScript•Package shared : code Java commun au clientet au serveur. Compilé en JavaScript (si spécifiépar le tag <source> du fichier de configuration)•Point d’entrée : LabGWT.javapublic void onModuleLoad() équivalent dumain() en C/C++/Java.•Page HTML d’accueil : LabGWT.html. Elle inclutle fichier JavaScript généré,<module>.nocache.js, dans un tag <script> :<script type="text/javascript" language="javascript"src="labgwt/labgwt.nocache.js"></script> Celinio Fernandes No. 12
    • Fichiers JavaScript générés• Les fichiers JavaScript générés sont présent dans le classpath.• Ils sont par défaut obfuscated. C’est un format compressé (pas de retour à la ligne, pas d’espace, noms des fonctions changés, etc) qui accélère les temps de chargement. Celinio Fernandes
    • Création d’un projet GWT avec Maven (1/2)Le plugin gwt-maven-plugin permet de générer un squelette de projet GWT Celinio Fernandes
    • Création d’un projet GWT avec Maven (2/2)• Problème : • Archétype :• Classes non trouvées. Faire un mvn install d’abord. • mvn archetype:generate Puis copier-coller des classes générées suivantes : • -DarchetypeRepository=repo1.maven.org • /target/generated- • -DarchetypeGroupId=org.codehaus.mojo sources/gwt/foo/client/GreetingServiceAsync.java • -DarchetypeArtifactId=gwt-maven-plugin • /target/generated- • -DarchetypeVersion=2.4.0 sources/gwt/foo/client/Messages.java• vers /src/main/java/foo/client • http://mojo.codehaus.org/gwt-maven- plugin/user-guide/archetype.html• Dépendances Maven : <dependency> <groupId>com.google.gwt</groupId> <artifactId>gwt-servlet</artifactId> <version>2.4</version> <scope>runtime</scope> </dependency> <dependency> <groupId>com.google.gwt</groupId> <artifactId>gwt-user</artifactId> <version>2.4</version> <scope>provided</scope> </dependency> Celinio Fernandes
    • Création d’un projet GWT avec Spring Roo (1/3)• Version standalone de Roo. Pas besoin de SpringSource Tool Suite (STS).• Un exemple standard, Expenses, intègre GWT :• Roo> script expenses.roo• Roo > exit Celinio Fernandes No. 16
    • Création d’un projet GWT avec Spring Roo (2/3) Celinio Fernandes No. 17
    • Création d’un projet GWT avec Spring Roo (3/3)• Projet importable dans Eclipse.• L’exemple Expenses utilise « Activities and Places ».• Autre commande Roo :• Roo > web gwt setup• Documentation officielle :• http://static.springsource.org/spring-roo/reference/html/base-gwt.html Celinio Fernandes
    • Mode développement (1/3)• Le mode developpement permet detester l’application dans le browser sansavoir besoin de compiler en JavaScript.• Apporte une plus grande productivité.Les modifications au niveau de l’UI sontvisibles immédiatement, après refresh.• Requiert l’installation du plugin GWTDeveloper pour le browser (Firefox,Internet Explorer, Chrome …).• URL se termine avecgwt.codesvr=127.0.0.1:9997. Parexemple :http://127.0.0.1:8888/LabGWT.html?gwt.codesvr=127.0.0.1:9997 Celinio Fernandes No. 19
    • Mode développement (2/3)• Mode développement ou hosted • Mode web ou production • Le code Java est traduit en• Utilisé dans la phase de JavaScript développement • Déploiement sur le serveur• Le code client n’est pas traduit en • Application plus rapide JavaScript• Possibilité de debugger• Les messages de log sont affichés dans une fenêtre de log• Utilise par défaut un serveur embarqué : Jetty• Evite la compilation de l’application et le déploiement sur le serveur Celinio Fernandes
    • Mode developpement (3/3)• Pour lancer le mode developpement avec le plugin Maven : <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>gwt-maven-plugin</artifactId> • goal gwt:run <version>2.4.0</version> <executions> • goal gwt:debug <execution> <goals> <goal>compile</goal> <goal>test</goal> <goal>i18n</goal> <goal>generateAsync</goal> </goals> </execution> </executions> <!-- Plugin configuration. There are many available options, see gwt-maven-plugin documentation at codehaus.org --> <configuration> <runTarget>labGWT2.html</runTarget> <hostedWebapp>${webappDirectory}</hostedWebapp> <i18nMessagesBundle>foo.client.Messages</i18nMessagesBundle> </configuration> </plugin> Celinio Fernandes No. 21
    • Les widgets
    • Les widgets (1/7)• Widget = composant graphique• Les composants graphiques générés sont du code HTML.• On peut utiliser l’arbre DOM directement, même s’il vaut mieux utiliser les widgets et leurs propriétés : Button button= new Button(); DOM.setStyleAttribute(button.element, " backgroundColor", "blue"); DOM.setStyleAttribute(button.element, " border", " 1px solid ");• Dans la hiérarchie des classes des Widgets, la classe mère est com.google.gwt.user.client.ui.UIObject.• http://google-web-toolkit.googlecode.com/svn/javadoc/2.4/com/google/gwt/user/client/ui/UIObject.html• Sous-classes directes de UIObject : • MenuItem • MenuItemSeparator • TreeItem • Widget Celinio Fernandes No. 23
    • Les widgets (2/7)• Sous-classes directes de com.google.gwt.user.client.ui.Widget : • AbstractNativeScrollbar : classe parente abstraite pour les scrollbars • CellWidget • Composite : pour créer des widgets personnalisés • FileUpload : widget qui wrap le tag HTML <input type="type"> • FocusWidget • Frame • Hidden • Hyperlink • Image • LabelBase • MenuBar • Panel : classe abstraite de base pour les panels (widgets qui contiennent d’autres widgets) • Tree : contient une hiérarchie de TreeItems Celinio Fernandes No. 24
    • Les widgets (3/7)• Quelques widgets de position (layout) : HorizontalPanel FlowPanel DisclosurePanel VerticalPanel TabLayoutPanel Celinio Fernandes No. 25
    • Les widgets (4/7)• Quelques widgets de saisie : CheckBox RadioButton DatePicker FileUpload Celinio Fernandes No. 26
    • Les widgets (5/7)• Autres widgets : CellTable CellTree Tree Celinio Fernandes No. 27
    • Les widgets (6/7)• Le showcase officiel : une gallerie de widgets avec code source disponible à l’URL http://gwt.google.com/samples/Sh owcase/Showcase.html• Disponible également dans le répertoire samples du SDK. Celinio Fernandes
    • Les widgets (7/7)• Possibilité de créer un widget personnalisé soit en : • sous-classant un widget existant public class DynamicSelectionCell extends SelectionCell { … } • héritant com.google.gwt.user.client.ui.Composite (recommandé) public class MultiSelect extends Composite { public Label lab = new Label(); public TextBox textBox = new TextBox(); public ListBox listBox = new ListBox(); ... public MultiSelect(String caption) { HorizontalPanel panel = new HorizontalPanel(); panel.add(lab); panel.add(listBox); … // All composites must call initWidget() in their constructors. initWidget(panel); } ... } Celinio Fernandes No. 29
    • L’interface UiBinder (1/5)– Façon déclarative de créer des layouts (vues, widgets …) • Un template avec l’extension ui.xml : RapportViewImpl.ui.xml • Code XML – Ne contient pas de logique – Décrit le layout • Une Owner classe de même nom : RapportViewImpl.java • Annotations : @UiField, @UiHandler, @UiTemplate (pour un nom de template différent et/ou avec plusieurs templates), etc… • Utilise UiBinder pour charger le layout • Relie les évènements au code Celinio Fernandes No. 30
    • L’interface UiBinder (2/5)• Owner classe :• public class RapportViewImpl extends Composite implements RapportView {• private static RapportViewImplUiBinder uiBinder = GWT.create(RapportViewImplUiBinder.class);• interface RapportViewImplUiBinder extends UiBinder<Widget, RapportViewImpl>• {• }• @UiField Label lab;• @UiField TabPanel TableauNotes;• @UiField DockPanel monDockPanel;• @UiField Label PremiereNote;• @UiField Label DeuxiemeNote;• @UiField Button boutonHello; …• @UiHandler("boutonHello")• void onBoutonHelloClick(ClickEvent event) {• presenter.goTo(new HelloPlace(nom));• }• …• } Celinio Fernandes No. 31
    • L’interface UiBinder (3/5)• Template XML:• <!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">• <ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"• xmlns:g="urn:import:com.google.gwt.user.client.ui">• ...• <g:HTMLPanel>• Hello,• <span class="{style.important}" ui:field="nameSpan" />• <g:DockPanel height="281px" width="448px" ui:field="monDockPanel">• <g:Dock direction="WEST">• <g:Label ui:field="lab" text="Rapport a faire" width="120px"></g:Label>• </g:Dock>• <g:Dock direction="SOUTH">• <g:TabPanel ui:field="TableauNotes"> … </g:TabPanel>• </g:Dock>• <g:Dock direction="WEST">• <g:Button ui:field="boutonHello" text="Retour à l&apos;accueil"/>• </g:Dock>• </g:DockPanel>• </g:HTMLPanel>• </ui:UiBinder> Celinio Fernandes No. 32
    • L’interface UiBinder (4/5)• Wizard de création sous Eclipse Celinio Fernandes No. 33
    • L’interface UiBinder (5/5)• GWT Designer pour le template Celinio Fernandes No. 34
    • Events ethandlers
    • Events et handlers (1/4)– Un évènement (event) peut être : • un clic de bouton (ClickEvent) • un changement dans une listbox (ChangeEvent) • une touche de clavier pressée (KeyDownEvent) • un passage de souris dans une zone (MouseOverEvent) • un défilement (ScrollEvent) • etc…– La classe de base est com.google.gwt.event.shared.GwtEvent Celinio Fernandes No. 36
    • Events et handlers (2/4)• Pour gérer ces évènements, on ajoute des handlers aux widgets. Avec plusieurs possibilités de faire: • en passant par une classe anonyme • en implémentant l’interface du Handler • etc …• Exemples d’interfaces d’handlers : ClickHandler, ChangeHandler, KeyDownHandler, MouseOverHandler, FocusHandler, ValueChangeHandler, SelectionHandler, OpenHandler …• L’interface de base est com.google.gwt.event.shared.EventHandler Celinio Fernandes No. 37
    • Events et handlers (3/4)• Classe Handler anonyme : public void anonClickHandlerExample() { Button b = new Button("Click Me"); b.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { // handle the click event } }); } Celinio Fernandess No. 38
    • Events et handlers (4/4)• Implémentation de l’interface du Handler : public class HandlerExample extends Composite implements ClickHandler { private FlowPanel fp = new FlowPanel(); private Button b1 = new Button("Button 1"); public HandlerExample() { initWidget(fp); fp.add(b1); b1.addClickHandler(this); } public void onClick(ClickEvent event) { Widget sender = (Widget) event.getSource(); … } } – Adéquat pour des handlers complexes (plusieurs boutons, design complexe ..) Celinio Fernandes No. 39
    • Les servicesdistants (RPC)
    • Les services RPC (1/6)• Les services RPC (Remote Procedure Call) permettent de faire des appels d’objets entre la partie cliente et la partie serveur.• GWT utilise des services RPC asynchrones pour rendre les applications Web plus interactives. Que veut dire asynchrone ? • Le programme n’attend pas la fin de l’exécution de la méthode pour passer la suite (principe même d’Ajax). Si un service est long, il ne faut pas attendre la réponse et il faut laisser la main au browser.• GWT prend en charge la sérialisation et la désérialisation des objets Java.• GWT utilise des interfaces pour créer un service RPC : • Une interface synchrone qui hérite de com.google.gwt.user.client.rpc.RemoteService, côté client • Une interface asynchrone, côté client • Une classe, côté serveur (= package serveur), qui implémente l’interface synchrone et les méthodes RPC qu’on veut mettre à disposition côté client • Pourquoi des services RPC dans GWT ? • Permettre l’exécution de méthodes côté serveur et qui ne sont pas exécutables côté client (compilation impossible en JavaScript, problème de sécurité …) Celinio Fernandes No. 41
    • Les services RPC (2/6)• Etapes1. Créer les classes et interfaces RPC côté client2. Créer l’implémentation côté serveur du service RPC. C’est une servlet qui implémente l’interface synchrone et qui étend RemoteServiceServlet.3. Faire l’appel du service RPC dans le code4. Ne pas oublier de modifier le fichier web.xml pour y déclarer la servlet et faire le mapping ! Celinio Fernandes No. 42
    • Les services RPC (3/6)• Diagramme de la plomberie RPC• Source : https://developers.google.com/web-toolkit/doc/latest/DevGuideServerCommunication#DevGuidePlumbingDiagram• Celinio Fernandes No. 43
    • Les services RPC (4/6) • L’interface synchrone (côté client) : @RemoteServiceRelativePath("manageVille") public interface ManageVilleService extends RemoteService { public long getCodePostalVille (String nom) throws VilleNonTrouveeExceptionDto; } • L’interface asynchrone (côté client) : public interface ManageVilleServiceAsync { void getCodePostalVille (String nom, AsyncCallback<long> callback); } • L’implémentation du service (côté serveur) : @RemoteServiceRelativePath("manageVille") public class ManageVilleDelegate extends SpringBeanInjectionRemoteServiceServlet implements ManageVilleService { @Autowired private ManageVille manageVilleApplication; public long getCodePostalVille (String nom) throws VilleNonTrouveeExceptionDto { // appels de services des autres couches / de modules non GWT … … }• Note : @RemoteServiceRelativePath associe le service à un chemin relatif Celinio Fernandes No. 44
    • Les services RPC (5/6)• Appel du service RPC depuis une activity (côte client), par exemple : public class VilleActivity extends AbstractActivity implements VilleView.Presenter { // RPC service proxy private final ManageVille ServiceAsync manageVilleServiceProxy; … manageVilleServiceProxy.getCodePostalVille(String nom, new AsyncCallback<long> () { public void onFailure(Throwable caught) { Window.alert("Problème !!"); } public void onSuccess(long codePostal){ view.setCodePostal(codePostal); } }); …. }• Création d’une classe AsyncCallback anonyme, en paramètre de la méthode asynchrone appelée. Lab GWT No. 45
    • Les services RPC (6/6)• Important : les objets transportés doivent être sérialisables. Les règles de sérialisation diffèrent un peu de celles de l’API Java standard.• https://developers.google.com/web-toolkit/doc/latest/DevGuideServerCommunication?hl=fr- FR#DevGuideSerializableTypes• Problème des entités :• Les entités JPA sont transformées au runtime par Hibernate, pour les rendre persistantes. Hibernate les instrumente en modifiant le bytecode, ce qui pose problème pour l’échange des données entre le client et le serveur à l’aide de la sérialisation. • Solution :• Utiliser le pattern DTO. Les objets de transfert (avec la même structure ou non que les objets persistés) ne sont pas instrumentés et peuvent être rendus sérialisables.• Et utiliser Dozer pour la transformation. Entité Dozer DTO Celinio Fernandes No. 46
    • Design pattern MVP• Model View Presenter
    • Le design pattern MVP (1/5)• Qui connait MVP ?• Permet d’éviter du code spaghetti MVP•• Modèle : les DTOs, les données qui sont affichées• Vue : l’interface graphique• Presenter : équivalent du contrôleur de MVC. Implémente l’accès à la logique métier et au modèle de données. Réagit aux évènements de l’utilisateur et qui sont transmis par la Vue. Celinio Fernandes No. 48
    • Le design pattern MVP (2/5)• Avantages : • Séparation claire entre la partie présentation et la logique métier • Plus grande maintenabilité puisqu’il n’y a presque pas de dépendance avec la logique métier (couplage faible). • Plus facile à tester. On peut mocker la Vue, le Presenter … (Mockito). Celinio Fernandes No. 49
    • Le design pattern MVP (3/5)• Un pattern conceptualisé par Martin Fowler :• http://martinfowler.com/eaaDev/ModelViewPresenter.html• Permet de séparer la logique métier de l’UI.• Deux variantes : Passive View et Supervising Controller• Source : http://msdn.microsoft.com/en-us/library/ff647543.aspx Celinio Fernandes No. 50
    • Le design pattern MVP (4/5)• Dans GWT, c’est plutôt la variante Passive View qui est appliquée.• Sens unidirectionnel (dans l’idéal, la Vue est totalement passive) Vue Presenter Modèle•• Le Presenter met à jour la Vue.• Sens bidirectionnel Vue Presenter Modèle• Le Presenter communique avec la Vue et la Vue communique avec le Presenter. Il existe un lien étroit.• Dans les deux sens, il n’y a pas de communication directe entre le Modèle et la Vue. Celinio Fernandes No. 51
    • Le design pattern MVP (5/5)• Différences avec MVC ? Vue Modèle Contrôleur• Le Contrôleur gère les actions de l’utilisateur.• La Vue peut accéder au Modèle directement. Vue Presenter Modèle• La Vue gère les actions de l’utilisateur (via le Presenter).• La Vue n’interagit pas avec le Modèle. Celinio Fernandes No. 52
    • Bonnespratiques
    • L’EventBus (1/5) • Le but du bus d’évènements est de permettre à des objets de « souscrire » à certains évènements du bus.• C’est un singleton. On peut créer plusieurs bus, par fonctionnalité.• Par exemple un bus pour traiter les évènements liés à la navigation seulement, un autre bus pour transmettre des messages …• Pour créer un bus, on peut étendre la classe com.google.gwt.event.shared.EventBus.SimpleEventBus• Permet un couplage lâche puisqu’il permet aux objets d’interagir sans avoir de dépendances directes les uns envers les autres.• Est utilisé par l’API Activities and Places.• Exemples d’utilisation : • Affichage d’une barre de notification lorsqu’un traitement démarre ou se termine. • Redirection vers un écran de login lors d’un timeout de session, après un appel à un service RPC Celinio Fernandes No. 54
    • L’EventBus (2/5)• Une instance unique d’un EventBus est transmise aux composants qui interagissent avec. Composant 1 Composant 2 Composant 3 Event Event Event + + + etc… Handler Handler Handler EventBus Composant 4 Composant 5 Composant 6 Celinio Fernandes No. 55
    • L’EventBus (3/5)• Création d’un évènement import com.google.gwt.event.shared.GwtEvent; public class MessageEvent extends GwtEvent<MessageEventHandler> { public static final Type<MessageEventHandler> TYPE = new Type<MessageEventHandler>(); private final String message; public MessageEvent(final String pMessage) { super(); message = pMessage; } @Override protected void dispatch(MessageEventHandler handler) { handler.onMessageRecu(this); } @Override public Type<MessageEventHandler> getAssociatedType() { return TYPE; } public String getMessage() { return message; } } Celinio Fernandes No. 56
    • L’EventBus (4/5)• Création d’un handler d’évènement import com.google.gwt.event.shared.EventHandler; import com.google.gwt.event.shared.GwtEvent.Type; import com.google.gwt.user.client.Window; public class MessageEventHandler implements EventHandler { public static final Type<MessageEventHandler> TYPE = new Type<MessageEventHandler>(); public MessageEventHandler() { } /** * Affichage dune alerte lors de la réception dun message * * @param messageEvent */ public void onMessageRecu(final MessageEvent messageEvent) { Window.alert(messageEvent.getMessage()); } } Celinio Fernandes No. 57
    • L’EventBus (5/5)• Classe com.google.gwt.event.shared.EventBus• 2 méthodes principales : • <H> HandlerRegistration addHandler(Event.Type<H> type, H handler) Ajoute un handler (à l’EventBus) pour recevoir des évènements de ce type de toutes les sources. private void ecouterEvents() { GWT.log("attachement des events"); this.eventBus.addHandler(MessageEvent.TYPE, new MessageEventHandler()); } • abstract void fireEvent(GwtEvent<?> event) Déclenche lévènement passé en paramètre, pour les handlers qui écoutent ce type dévènement private final MessageEvent messageEvent = new MessageEvent(« ATTENTION !!!"); … eventBus.fireEvent(messageEvent); Cet EventBus est par exemple passé en paramètre à la méthode start() d’une activity. Celinio Fernandes No. 58
    • Activities and Places (1/8)• Une API pour la navigation et pour la gestion de l’historique. Apparu dans la version 2.1.• Adéquat pour mettre en place une architecture basée sur le design pattern MVP.• Ne pas confondre « Activities and Places » avec MVP : on peut implémenter MVP sans « Activities and Places » et on peut utiliser « Activities and Places » sans MVP.• Explications officielles : http://code.google.com/webtoolkit/doc/latest/DevGuideMvpActivitiesAndPlaces.html• API complexe• Bonne façon de commencer :http://code.google.com/p/google-web-toolkit/downloads/detail?name=Tutorial-hellomvp-2.1.zip Celinio Fernandes No. 59
    • Activities and Places (2/8)–Les objets concernés • La vue : La partie graphique associée à une activité. • L’activité : c’est le presenter. L’interface du presenter est définie dans l’interface de la vue qui lui est associée. • La place : un objet Java qui représente un état bookmarkable de l’application. Utilisée pour l’historique. C’est l’endroit (la page) où l’on se trouve dans l’application. • Un PlaceHistoryMapper pour déclarer les places qu’on souhaite historiser (boutons Précédent et Suivant) dans l’application. Est lié à PlaceHistoryHandler qui permet le mapping bi- directionnel entre les places et l’URL (qui contient le token de la Place appelée). • Un PlaceController : gère le changement de places. • Un ActivityManager : détermine l’activité à lancer pour une place donnée. Il utilise un ActivityMapper. Un ActivityManager par zone est une bonne idée. • L’EventBus : est passé dans les activities et les vues. Il dispatche des évènements vers les parties intéressées. • Une ClientFactory : non requis mais bonne pratique. Utilisée pour l’injection d’objets tels que l’EventBus, le PlaceController, les vues … Celinio Fernandes No. 60
    • Activities and Places (3/8)– La vue public interface HelloView extends IsWidget { void setName(String helloName); void setPresenter(Presenter listener); public interface Presenter { void goTo(Place place); } } • Hérite de IsWidget • Généralement une vue est mappée à un presenter. Les vues complexes peuvent avoir plusieurs presenters. • setPresenter(…) permet une communication bi- directionnelle Celinio Fernandes No. 61
    • Activities and Places (4/8)– L’activity (presenter) public class HelloActivity extends AbstractActivity implements HelloView.Presenter { … public void goTo(Place place) { clientFactory.getPlaceController().goTo(place); } } • Elle étend AbstractActivity • Elle implémente l’interface déclarée dans la vue • Le PlaceController est injecté dans l’activité Celinio Fernandes No. 62
    • Activities and Places (5/8)– Méthodes du cycle de vie d’une activity • public void start(AcceptsOneWidget containerWidget, EventBus eventBus) – est appelée lors du retour de l’activity par l’ActivityMapper – seule méthode obligatoire si on étend AbstractActivity • public String mayStop() – est appelée avant que l’utilisateur quitte l’activity – retourne un message pour prévenir l’utilisateur, sinon rien • public void onCancel() • est appelée si l’utilisateur change d’activity avant le retour de la méthode start(…) • public void onStop() • est appelée lorsque l’activity se termine (quand on quitte la page ou qu’une autre activity la remplace) Celinio Fernandes No. 63
    • Activities and Places (6/8) – La place• public class GoodbyePlace extends Place { private String goodbyeName; public GoodbyePlacetoken) { this.goodbyeName = token; } public String getGoodbyeName() { return goodbyeName; } public static class Tokenizer implements PlaceTokenizer< GoodbyePlace > { @Override public String getToken(GoodbyePlace place) { return place.getGoodbyeName(); } @Override public GoodbyePlace getPlace(String token) { return new GoodbyePlace token); } } } • Une place hérite de com.google.gwt.place.shared.Place Celinio Fernandes No. 64
    • Activities and Places (7/8)– Par défaut l’URL est de la formehttp://127.0.0.1:8888/HelloMVP.html#{NomPlace}:T okenoù • {NomPlace} : par défaut le nom de la classe de la place. Peut être changé à l’aide de l’annotation @Prefix • Token : le token retourné par PlaceTokenizerhttp://127.0.0.1:8888/HelloMVP.html#GoodbyePlace:World! Celinio Fernandes No. 65
    • Activities and Places (8/8)– PlaceHistoryMapper @WithTokenizers( { HelloPlace.Tokenizer.class, GoodbyePlace.Tokenizer.class, RapportPlace.Tokenizer.class }) public interface AppPlaceHistoryMapper extends PlaceHistoryMapper { } • Non obligatoire. Si une place n’est pas déclarée, il n’y a pas d’historique pour cette place et le bouton « Précédent » du navigateur est désactivé. Celinio Fernandes No. 66
    • Optimisation avec le code splitting (1/2)– Chargement à la demande • Par défaut, tout le code JavaScript est compilé en un seul fichier qui est téléchargé au chargement de la page. Ce chargement initial peut être long. • Le code splitting consiste à splitter ce fichier JS en plusieurs fichiers JS qui seront téléchargés quand ceux-ci seront appelés. • On insère des « split points » dans le code. GWT.runAsync(new RunAsyncCallback() { @Override public void onFailure(Throwable caught) { //En cas déchec du téléchargement du nouveau code Window.alert("Echec du téléchargement du JavaScript"); } @Override public void onSuccess() { //Ce code est téléchargé au moment où il est appelé Window.alert("Chargement à la demande "); } }); Celinio Fernandes No. 67
    • Optimisation avec le code splitting (2/2)– Les fichiers JavaScript générés sont placés dans le répertoire defferedjs– Il convient de placer les split points à des endroits judicieux.– Avec Activities and Places, on peut par exemple faire du code splitting au niveau de l’ActivityManager en créant un wrapper autour de la classe AbstractActivity, avec l’interface AsyncProvider<T,F>. Ce wrapper renvoie une activité quand elle est appelée. Son code n’est donc pas chargé au démarrage de l’application. Celinio Fernandes No. 68
    • Autres bonnes pratiques (1/2)• Ne pas mélanger GWT avec d’autres frameworks, pour la partie présentation.• GWT ne doit pas être utilisé que pour créer des widgets mais aussi pour gérer la navigation, l’historique, l’internationalisation, la validation etc.• Créer des composants personnalisés réutilisables• Packager les ressources avec un client bundle Celinio Fernandes No. 69
    • Autres bonnes pratiques (2/2) • Créer des classes chargées de gérer les callbacks (allège le code, permet de réutiliser les callbacks …) des services RPC.• public class FindAllVillesCallBack implements AsyncCallback<List<VilleRechercheDto>> {• ...• public void onFailure(Throwable caught) {• eventBus.fireEvent(finishSearchVillesEvent);• if (caught instanceof AccesInterditExceptionDto) {• view.accesDenied();• }• else if (caught instanceof InvocationException) {• GWT.log("FindAllVillesCallBack : InvocationException *****" + caught.getMessage());• return;• }• else if (caught instanceof NotFoundExceptionDto) {• view.noData();• } else {• GWT.log("FindAllVillesCallBack: une erreur technique sest produite : " + caught);• }• }• public void onSuccess(List<VilleRechercheDto> result) {• GWT.log("FindAllVillesCallBack : onSuccess****************");• view.setData(result);• eventBus.fireEvent(finishSearchVillesEvent);• }• }• private final ManageVilleServiceAsync manageVilleServiceProxy;• manageVilleServiceProxy.findAllVilles(new FindAllDVillesCallBack(view, eventBus, finishSearchVillesEvent)); Celinio Fernandes No. 70
    • Non couvert• Request Factory : alternative à GWT RPC• Internationalisation• Ressources bundles / client bundle : mettre en cache des ressources (fichiers, images, CSS …)• JSNI (JavaScript Native Inteface) : support pour JavaScript natif (inclure du code JavaScript dans du code Java).• Tests : GWTTestCase• Deferred binding (liaison différée) : • pour l’insertion d’une classe à la compilation, pas au runtime. • pour créer plusieurs implémentations (une par browser) de la même fonctionnalité • GWT.create(Class) instancie une classe via le deferred binding• Speed Tracer : mesurer les performances• Gin : GWT Injection, framework IoC pour GWT, côté client• Guice : framework d’injection de dépendances• etc … Celinio Fernandes No. 71
    • Conclusion
    • Librairies tierces • SmartGWT : Remplace GWT-Ext. Type de licence : open source LGPL.C’est un wrapper de SmartClient (les composants encapsulent le code JavaScript SmartClient, en utilisant JSNI). http://gwt-ext.com/ http://www.smartclient.com/smartgwt/showcase/ • Sencha GXT (Ext GWT) : Sencha est le créateur du framework JavaScript Ext JS. Ce n’est pas un wrapper de Ext JS, les composants sont natifs c.a.d. écrits en Java. Types de licences : GPL et commercial. http://www.sencha.com/products/gxt/ https://developers.google.com/web-toolkit/tools/gwtdesigner/features/gwt/gxt • GWT-Ext : wrapper autour de Ext JS. N’est plus maintenu par Sencha. • etc … • Questions à se poser :1. Peut-on mélanger ces widgets avec les widgets de base de GWT ?2. Open source ou commerciale ?3. Performances ? Composants plus riches mais performances plus faibles par rapport à GWT de base ? • Etude comparative de quelques widgets entre Sencha GXT et GWT : http://gxtvsgwt.appspot.com/ Les widgets Sencha seraient 2 à 10 fois moins rapides que celles de GWT de base. Celinio Fernandes No. 73
    • Dart : la menace ?• Dart : créé en 2011 par Google. Certains développeurs GWT travaillent maintenant sur Dart.• Nouveau langage, avec une syntaxe proche d’un mélange entre C et Java. Produit du JavaScript.• Google IO 2012 (3 jours, fin juin) : • 2 sessions GWT seulement, pour l’instant (fin mai) : "Migrating Code from GWT to Dart" et "The History and Future of Google Web Toolkit" • Déjà au moins 4 sessions Dart de prévues https://developers.google.com/events/io/sessionsSource : http://www.dartlang.org/support/faq.html#future-for-GWT– Version 2.5 de GWT contiendrait une grosse surprise !  Celinio Fernandes No. 74
    • Pour aller plus loin– Livres • En anglais :GWT in Action, 2nd édition (prévue en août 2012) • En français :Programmation GWT 2 - Développer desapplications RIA et Ajax avec le Google Web Toolkitde Sami Jaber (1ère édition, janvier 2010).Deuxième édition prévue en juin 2012.– Lienshttps://developers.google.com/web-toolkit/doc/latest/DevGuidehttps://developers.google.com/web-toolkit/doc/latest/DevGuideMvpActivitiesAndPlaceshttp://groups.google.com/group/Google-Web-Toolkit Celinio Fernandes No. 75
    • Merci• Celinio Fernandes