Faciliter le développement d applications Web horsligne en Java avec GWT 11h30 12h20 Salle E. Fitzgerald & L. Armstrong Palo IT - Arnaud Tournier Devoxx 2013
Speaker : Arnaud Tournier Développeur chez Palo IT, sponsor du Devoxx. 10 ans d expérience, C/C++ sous Windows. Puis depuis 5 ans : GWT et technologies Web. Formateur GWT Applis Offlines HTML5 avec GWT 2
Pourquoi les applications Web Hors-ligne? En terme de mobilité: Débits 3G parfois insuffisants (lecteur de blog offline) Mitiger l impact des déconnexions intempestives (emails) Déplacements hors zone de couverture (vente vrp, ) En ligne / Hors ligne, on veut la même expérience! L application la plus connectée est donc aussi hors-ligne! Applis Offlines HTML5 avec GWT 3
Le Web est la plateforme HTML5 ouvre de nouvelles possibilités d applicatifs réservés auparavant au monde du «natif». Concepts accessibles à une application HTML 5: Stockage de données, Stockage de l application pour exécution hors-ligne, Système de fichier, Worker thread, Web sockets, WebRTC, Web GL, Audio, Accès périphériques (webcam, microphone, gps, ), Une code web touche potentiellement énormément plus de clients qu une application native pour un même code (multiplateforme). Applis Offlines HTML5 avec GWT 4
Attention au coût de développement! La prise en charge de la tolérance aux pertes partielles ou totales de la connexion est couteuse au développement. Les problématiques à gérer peuvent être compliquées (synchronisation de données, gestion de conflits). Il faut essayer au maximum de cerner les besoins de l application pour minimiser l effort de développement. «Avec de grands pouvoirs vient une grande complexité» Applis Offlines HTML5 avec GWT 5
GWT : Notre de développement Google Web Toolkit va nous permettre de développer des applications complexes en Java et de faire levier sur la plateforme HTML5, Projet Open Source initialement créé en 2006 chez Google (un comité de pilotage intégrant les acteurs majeurs de GWT assure maintenant la gouvernance), Très vaste communauté, Téléchargé plus d un million de fois, Nous permet de partager du code entre client et serveur, La plupart des API HTML 5 sont prises en charge, Elemental pour prendre en compte les évolutions HTML 5, JSNI : Intéropérabilité avec le monde Javascript, Applis Offlines HTML5 avec GWT 6
La philosophie de GWT Développement dans un IDE évolué. Débogage dans l IDE. Refactoring Modèle de composants graphiques à la Swing, Le développeur ne doit pas être un gourou de JavaScript, HTML ou CSS, Gère les ressources de l application, Génère de façon quasi-transparente le code JavaScript à partir de Java, Multi-navigateurs, le développeur ne se soucie pas spécificités de chaque navigateur, Monde Java Monde GWT Bytecode JavaScript Virtual Machine Navigateur Applis Offlines HTML5 avec GWT 7
Principes de GWT Un seul code Java génère ensuite plusieurs scripts JavaScript optimisés pour chaque navigateur GWT gère les ressources (images, css, ) de l application Un seul code Java Intéropérabilité Javascript Au démarrage, le programme choisit le script à charger Applis Offlines HTML5 avec GWT 8
Sommaire HTML5 pour l Offline Cache d application Stockage de données local Problématiques Login SGBD local Synchronisation Démonstration Perspectives Applis Offlines HTML5 avec GWT 9
HTML 5 pour l Offline Présentation des APIs et intégration GWT
Le cache d application Permet de faire stocker au navigateur les ressources nécessaires au fonctionnement de votre page web lorsque la connexion est coupée Un fichier «manifest» avec la liste des ressources à mettre en cache Une api de gestion du cache et des événements associés Applis Offlines HTML5 avec GWT 11
Dynamique du Cache d Application Chargement initial DOWNLOADING.html Recharg ement.html NOUPDATE UPDATE READY.manifest CACHED Serveur NOUVEAU MANIFEST.manifest Applis Offlines HTML5 avec GWT 12
Cache d application - GWT GWT a déjà un mécanisme de gestion des ressources de l application, on n a plus qu à écrire un «linker» pour générer le fichier manifest : Genérateur de code Toutes les ressources de l application, y compris les images, css, etc sont intégrées automatiquement pour un fonctionnement hors ligne! Applis Offlines HTML5 avec GWT 13
Notre linker Application Cache // S exécute dans le contexte de la compilation @Shardable @LinkerOrder( Order.POST ) public class AppCacheLinker extends AbstractLinker { @Override public ArtifactSet link(linkercontext context, ) { for( Artifact artifact : artifacts ) { sb.append( artifact.getpartialpath() ); } } } emitstring( logger, sb.tostring(), "../" + context.getmodulename() + ".appcache" ); Applis Offlines HTML5 avec GWT 14
Cache d application GWT Intégration de l API du cache en GWT avec JSNI. Le navigateur vérifie la présence de nouveau contenu au chargement de l application. On peut demander la vérification avec la fonction update(). Quand on reçoit la mise à jour, on propose de recharger la page avec le nouveau contenu. En JavaScript, l object à utiliser est : window.applicationcache Applis Offlines HTML5 avec GWT 15
Cache d application Gestion des événements public final class AppCache extends JavaScriptObject { // call Javascript from Java public static final native AppCache get() /*-{ return $wnd.applicationcache; }-*/; } // launch an app cache update public final native void update() /*-{ this.update(); }-*/; public interface Callback { void handleevent( AppCacheEvent event ); } // register to App Cache events public final native void registerevents( Callback callback ) /*-{ this.addeventlistener('cached', function( s ) { // Call Java from Javascript callback.@package.appcache.callback::handleevent(lpackage/appcacheevent;) (@package.appcacheevent::cached); } ); }-*/; Applis Offlines HTML5 avec GWT 16 public enum AppCacheEvent { // Application en cache CACHED, } // Vérification en cours CHECKING, // Téléchargement en cours DOWNLOADING, // Une erreur s est produite ERROR, // Pas de mise à jour NOUPDATE, // Le fichier manifest n existe plus OBSOLETE, // Mise à jour en cours PROGRESS, // Mise à jour prête à être déployée UPDATEREADY;
Stockage de données local Conserver localement les données dans le champ de l utilisateur. Plusieurs normes existent mais peu sont implémentées sur tous les navigateurs : WebSQL, IndexedDB, LocalStorage, Seul Local Storage est cross-navigateur (ff, ie, chrome, safari, opera, ). C est un Map<String, String>. API est prise en charge par GWT «out of the box». Sérialisation et désérialisation des pojo dans l espace de stockage, en JSON car très rapide sur un navigateur. On peut s appuyer sur des bibliothèques existantes : Gson, gwt-json, Persistance au-delà des rechargements de la page! 5 Mega octets max! Applis Offlines HTML5 avec GWT 17
Sommaire HTML5 pour l Offline Cache d application Stockage de données local Problématiques Login SGBD local Synchronisation Démonstration Perspectives Applis Offlines HTML5 avec GWT 18
Problématiques Hors-ligne
Une liste de vœux On doit pouvoir se loguer en mode hors-ligne! Base de données locale pour continuer à fonctionner hors-ligne (dans l idéal un outil implémentant JPA). On voudrait que l utilisateur puisse manipuler les données en mode horsligne. On voudrait que l application se synchronise automatiquement, transparence pour l utilisateur. Applis Offlines HTML5 avec GWT 20
Authentification hors-ligne En mode connecté, le serveur fait l authentification. Ici, nous devons être capables d authentifier l utilisateur sans serveur. Attention! Stockage local non sécurisé! On va donc stocker le mot de passe chiffré en SHA-1 dans le navigateur. Avec GWT, on trouve une implémentation Java de SHA-1 et on l intègre dans son projet (merci ganymed-ssh-2!) : String shaencoded = sha.digest( String clearstring ); Applis Offlines HTML5 avec GWT 21
Un SGBD dans le navigateur? Interrogations complexes des données, on ne vas pas refaire la roue (complexité, performances, indexes, jointures, )! Les API HTML 5 base de données sont peu implémentées, à part Local Storage qui n est qu une table clé/valeur Jboss ERRAI est un projet très intéressant et ambitieux, qui vise à implémenter la norme JPA, mais il n est pas encore assez mature. SQL.js est l équivalent Javascript de SQLite réalisé avec le compilateur emscripten d Alon Zhakai, un traducteur C/C++ vers Javascript basé sur LLVM. Serait-ce une bonne idée? Applis Offlines HTML5 avec GWT 22
SQL.js avec GWT SQLite est le SGBD le plus déployé sur la planète (~500 millions) L API de sql.js : un object JavaScript window.sql open(data), execute(statement), exportdata(). Parle en JSON. Et la persistance de la base de données? Avec Local Storage! Code JSNI de liaison avec l api sql.js Code de liaison des résultats des requêtes vers des pojo pour plus de confort Cela donne Applis Offlines HTML5 avec GWT 23
SQL.js avec GWT Le script SQL.js crée une variable globale Javascript nommée «SQL» var result = window.sql.exec( «select»); // result contient les résultats en JSON public class SQLite extends JavaScriptObject { public static final native SQLite open( JsArrayInteger data ) /*-{ return $wnd.sql.open(data); }-*/; public final native JavaScriptObject execute( String statement ) /*-{ return this.exec(statement); }-*/; class DbHelper { SQLite db; public <T> List<T> query( String query ) { // parse query and generate select // execute query JavaScriptObject jso = db.execute( transformedquery ); JSON json = new JSONObject( jso ); public final native JsArrayInteger exportdata() /*-{ return this.exportdata(); }-*/; } } // generate List<T> from JSON return list; } public final native void close() /*-{ this.close(); }-*/; List<Article> articles = db.query( «select {Article:a} from Article a left join Marque m where m.id=42» ).getresultlist(); Applis Offlines HTML5 avec GWT 24
Des contrats de service homogènes public class RemoteBusinessLogic { private static ApplicationServiceAsync proxy = GWT.create(ApplicationService.class); } public List<Article> searcharticles( int id, AsyncCallback<List<Article>> callback ) { // simply delegate to remote service return proxy.searcharticles( ); } public class BusinessLogicFacade { public List<Article> searcharticles( int id, AsyncCallback<List<Article>> callback ) { return currentimplementation.searcharticles( ); } } public void switchimplementation( impl ) { currentimplementation = impl } Sur le serveur businesslogic = BusinessLogic( new JPADAO() ); // La servlet délègue au code métier return business.searcharticles( ); // le code métier appelle son DAO class BusinessLogic { DAO dao; } Serveur // qui utilise ici JPA return em.createquery( ).getresultlist(); public class SQLiteBusinessLogic { BusinessLogic businesslogic = new BusinessLogic( new SQLiteDAO() ); } public List<Article> searcharticles( int id, AsyncCallback<List<Article>> callback ) { // simply delegate to remote service callback.onsuccess( business.searcharticles( ) ); } // Le même code métier appelle cette fois le DAO SQLite return db.query( ); Applis Offlines HTML5 avec GWT 25 Client
Synchronisation des données Trois niveaux de difficulté selon les fonctionnalités offertes à l utilisateur Mode d accès local Lecture seule Lecture, Ajout Lecture, Ajout, Modification, Suppression Problèmes associés Synchronisation continue Envoi des ajouts au serveur Gestion des conflits Applis Offlines HTML5 avec GWT 26
Synchronisation descendante continue Accès Offline en LECTURE SEULE Alimenter en continu la base de données locale, On utilise les timestamp ou un compteur côté serveur, Le client demande les mises-à-jour qu il ne connaît pas, Pour les suppressions, un trigger alimente une table. Applis Offlines HTML5 avec GWT 27
Envoi des ajouts au serveur Accès Offline en LECTURE + AJOUT Nouveaux enregistrements. Gestion des identifiants. Les enregistrements locaux sont associés à des id négatifs. On les mets à jour à la synchronisation. Applis Offlines HTML5 avec GWT 28
Envoie des modifications au server Accès Offline en LECTURE ECRITURE Les pires scénarios sont imaginables! Problématiques semblables à celles des systèmes distribués. Gestion des conflits, plusieurs politiques possibles : Last writer wins, Source wins, Destination wins, Specified replica wins, Merge, automatic or manual? Log and deffer Horloges de Lamport pour la traçabilité de la causalité. Applis Offlines HTML5 avec GWT 29
Notre wish-list alors? Dans l idéal, ERRAI fonctionnerait à 100% et on n aurait qu un seul code d accès aux données. On n a pas vu la sécurité. En attendant : un mini-orm suffit. On constate une forte impédance entre le potentiel de la plateforme HTML5 et les outils dont on dispose. Nous avons donc atteint nos objectifs! Une application qui s exécute sans connexion et qui permet à l utilisateur de modifier ses données. Applis Offlines HTML5 avec GWT 30
Démonstration!
L architecture de la pile utilisée Interface graphique Façade Métier Services RPC Surveillance serveur Gestion AppCache Synchro Logique Métier Synchro DAO JPA DAO SQL.JS/GWT SGBD compatible JDBC SQLite/Local storage Serveur Client Applis Offlines HTML5 avec GWT 32
Passage vers le mode En ligne Interface graphique Façade Métier Services RPC Surveillance serveur Gestion AppCache Synchro Envoi des modifications Logique Métier locales au serveur Synchro DAO JPA DAO SQL.JS/GWT SGBD compatible JDBC SQLite/Local storage Serveur Client Applis Offlines HTML5 avec GWT 33
Mode En ligne Interface graphique Façade Métier Services RPC Surveillance serveur Gestion AppCache Synchro Logique Métier Synchro DAO JPA DAO SQL.JS/GWT SGBD compatible JDBC SQLite/Local storage Serveur Client Applis Offlines HTML5 avec GWT 34
Mode Hors-Ligne Interface graphique Façade Métier Synchro Services RPC Serveur inaccessible Logique Métier Surveillance serveur Gestion AppCache Synchro INDISPONIBLE DAO JPA SGBD compatible JDBC DAO SQL.JS/GWT SQLite/Local storage Serveur Client Applis Offlines HTML5 avec GWT 35
Passage vers le mode En ligne Interface graphique Façade Métier Réponse du serveur Services RPC Surveillance serveur Gestion AppCache Synchro Envoi des modifications Logique Métier locales Synchro DAO JPA DAO SQL.JS/GWT SGBD compatible JDBC SQLite/Local storage Serveur Client Applis Offlines HTML5 avec GWT 36
Mode En ligne Interface graphique Façade Métier Services RPC Surveillance serveur Gestion AppCache Synchro Logique Métier Synchro DAO JPA DAO SQL.JS/GWT SGBD compatible JDBC SQLite/Local storage Serveur Client Applis Offlines HTML5 avec GWT 37
C est parti! Applis Offlines HTML5 avec GWT 38
Merci, et bon Devoxx! Liens : HTML5Rocks GWT EMSCRIPTEN SQL.JS SQLITE JBOSS ERRAI CANIUSE.COM Venez nous retrouver sur le stand M2 de Palo IT! Applis Offlines HTML5 avec GWT 39