Projet de fin d'études Clients RIA pour le framework Telosys Étude de faisabilité Introduction ● ● ● ● Projet de fin d'études Entreprise Sogeti Framework open source Telosys Étude de nouvelles technologies RIA Plan ● ● ● ● ● ● ● Contexte Organisation Méthodologie Flex JavaFx OpenLaszlo Conclusion Contexte ● Web ● Besoin de dynamisme ● Interfaces de plus en plus riches AJAX ● AJAX (Asynchronous JavaScript And XML) – Dialogue asynchrone entre client et serveur – Évite le chargement complet de la page à chaque requête – Utilise XMLHttpRequest pour échanger et manipuler des données AJAX AJAX Telosys ● Framework open source ● Facilite la création d'applications internet ● Repose sur les concepts AJAX ● Principaux avantages – Open source – Développé en Java EE – Applications via des clients variés Telosys ● Notion d'écran – Page Web – Données – Actions ● ● ● Gestion de l'écran (Open, Close...) Gestion des données (Load, Save...) Basé sur les concepts AJAX Telosys Telosys ● Bookstore : requête <request screen-name="EMPLOYEE" screen-id="0" action="load" elements="employee"> <params> <param code="A001"/> </params> </request> Telosys ● Bookstore : réponse <response screen-name="EMPLOYEE" screen-id="0" action="load"> <return code="0" message="OK"> <found/> </return> <data> <employee firstname="JEAN" surname="DUPONT" shopcode="AAA" code="A001" manager="1"/> </data> </response> Telosys Telosys ● Taglibs JSP <%@ taglib uri="/telosys" prefix="t" %> <t:screenbody data="employee"> ... <t:field id="code" data="code"/> <t:field id="firstname" data="firstname"/> ... <t:button txt="Open" onclick="actionOpen();"/> ... </t:screenbody> Objectifs Client HTML AJAX Serveur Java Script Telosys Objectifs Client HTML AJAX Serveur Java Script Telosys OpenLaszlo ? ? Flex JavaFx ? Possible ? Objectifs ● Appréhender ces technologies ● Étudier les interactions possibles ● Réaliser des prototypes d'écran Plan ● ● ● ● ● ● ● Contexte Organisation Méthodologie Flex JavaFx OpenLaszlo Conclusion Environnement de travail ● Matériel – Serveur Telosys ● ● ● ● Serveur Tomcat + SGBD MySQL Application Bookstore Accessible via internet Communication – – – Réunions avec l’entreprise : 2 fois par mois Suivi de projet : Wiki en anglais E-mails et messagerie instantanée Répartition du travail ● ● ● ● Flex : Mickaël JavaFx : Benjamin, François OpenLaszlo : Jean-François, Thomas Chef de projet : Benjamin Plan ● ● ● ● ● ● ● Contexte Organisation Méthodologie Flex JavaFx OpenLaszlo Conclusion Méthodologie ● ● ● ● ● Prise en main des technologies (écrans, communication AJAX, ...) Étude des communications avec Telosys Proposition d’une architecture Développement des écrans (requêtes HTTP et interprétation des réponses) Proposition de librairies facilitant la conception Plan ● ● ● ● ● ● ● Contexte Organisation Méthodologie Flex JavaFx OpenLaszlo Conclusion Flex ● Généralités ● Flex builder ● MXML ● ActionScript ● Requêteur Telosys ● Application Telosys ● Serveur Telosys ● Serveur Flex Généralités ● Plateforme pour la création de RIA en Flash – Multiplateforme : 97 % des utilisateurs équipés – Version 2 (ou 3 bêta), licence open source MPL – SDK gratuit, IDE payant – 2 langages (comparables à HTML + JavaScript) ● ● – MXML pour les IHMs ActionScript pour le comportement Rendu et comportement homogène Flex builder ● ● IDE basé sur Eclipse (payant) – Éditeur WYSIWYG – Auto-complétion – Compilation automatique – Débogueur Nouveauté de la version 3 : les outils – Refactoring – Profiling MXML ● Langage de descriptions des IHMs – Dialecte XML – Nombreux composants graphiques natifs – Utilisation possible de feuilles de style CSS – Tout composant MXML est un object ActionScript ● ● Grande connectivité avec ActionScript Composants aisément manipulables ActionScript ● Langage dynamique côté client – ● Basé sur ECMAScript : JavaScript fortement typé Atouts – Langage objet – Accesseurs et modifieurs natifs – Librairie E4X (ECMAScript for XML) : XML natif – Binding facilité entre modèle et vue – Mécanisme de gestion des exceptions ActionScript ● Défauts – Pas de classes ou de méthodes abstraites – Pas de généricité – Pas de surcharge des méthodes – Pas de constructeur privé ou protégé – Mécanisme de gestion des exceptions basique – Subit les limitations du lecteur Flash Requêteur Telosys : aperçu Requêteur Telosys : requêtes ● Requêtes HTTP asynchrones : HTTPService – Principaux attributs ● – Principales méthodes ● ● ● – url, contentType, method, resultFormat, request addEventListener(ResultEvent.RESULT, success) addEventListener(FaultEvent.FAULT, failure) send() Problème : documentation incomplète ● text/xml géré, mais non officiellement Requêteur Telosys : réponses ● Réponse HTTP – Succès ● ● – Échec ● ● – function success (event: ResultEvent): void event.result = corps de la réponse HTTP function failure (event: FaultEvent): void event.fault.faultDetail = détail de l’erreur 2 en 1 ● ● function response(event: Event): void Test du type de l’évènement, puis cast Application Telosys : Aperçu Application Telosys : Paramétrage IFormat Settings contentType resultFormat parseRequest() parseReponse() SERVER_URL XMLFormat FORMAT Logger LOGGER logs lastRequest lastResponse APP_NAME Application Telosys : Modèle - vue IModel screenID screenName handleResponse() Foo view Construction Graphical components Binding Actions FooModel Application Telosys : Binding ● ● ● Mot-clé : [Bindable] – Par défaut sur les composants graphiques MXML – Indispensable sur les variables ActionScript Unidirectionnel (géré nativement) – [Bindable] public var value: Number; – <mx:Text id="foo" text="{myObject.value}"/> Bidirectionnel (non géré nativement) – A nécessité l’écriture d’une méthode : – Bind.bind(foo, "text", myObject, "value"); Application Telosys : Initialisation IModel 1 Requester 2 3 Session XXX 6 Telosys server 5 parseId(<ID>XXX</ID>) IFormat <ID>XXX</ID> 4 id.jsp Application Telosys : Requête Foo view 1 IModel xxxAction() FooModel Telosys server 2 xxxRequest(Array<Key, Value>) Requester 3 parseRequest(Request) 4 <…>…</…> IFormat <…>…</…> 5 /action Application Telosys : Réponse IModel 4 FooModel Telosys server handleResponse(Response) Requester Response 3 <…>…</…> 1 2 parseResponse(<…>…</…>) IFormat /action Serveur Telosys ● ● ● Sécurité – Autoriser l’accès depuis une application Flash – Fichier crossdomain.xml Identifiant de session – Entêtes des réponses HTTP coupées par Flash – Page JSP fournissant un identifiant dans le corps Contenu initial des écrans – Pages JSP fournissant les données ou services REST Serveur Flex ● ● 2 possibilités – Module sur serveur Apache HTTP – Projet web sur serveur d'application Java EE Fonctionnalités offertes par le serveur Java EE – Compilation à la volée – Génération de code MXML via des pages JSP – Mise en cache Plan ● ● ● ● ● ● ● Contexte Organisation Méthodologie Flex JavaFx OpenLaszlo Conclusion JavaFx ● JavaFx – – – ● Principes Mécanismes intéressants Limites Telosys et JavaFx – – Architecture générale Un exemple : screen employee Principes ● ● ● ● Langage de script basé sur Java Compilé / interprété à l’exécution Permet de rapidement réaliser une IHM Repose sur Swing Principes ● Exemple : package test; import javafx.ui.*; var f = Frame { content : TextField { value : } visible : true } "text" Principes ● Exécution du script test/test.fx package test; import javafx.ui.*; Classe Java var f = Frame { … } package test; import net.java.javafx.FXShell; public class Main { public static void main(String[] args) throws Exception { FXShell.main(new String []{"test/Test"}); } } Script JavaFx Mécanismes intéressants ● Binding – – Pour « lier » des variables entre elles, et les garder synchronisées S’applique à une instance class X { attribute a : Integer; attribute b : Integer; attribute c : Integer; } var x1 = X { a : 1 b : 2 c : 3 }; var x2 = X { a : x1.a b : bind x1.b c : bind x1.c + 5 }; Contraintes imposées : x1.b = k <=> x2.b = k x1.c = k => x2.c = k +5 Mécanismes intéressants ● Triggering – – Pour déclencher une suite d’opérations lors de la modification d’une variable S’applique à une classe class X { attribute num; } trigger on X.num [oldValue] = newValue { System.out.println ("{oldValue} => {newValue}"); } Mécanismes intéressants ● Lien avec Java – JavaFx vers Java ● ● Instanciation d’objets Java Appel à des méthodes Java import java.lang.System; import myPackage.MyClass; System.out.println ("bonjour"); var x = new MyClass (); x.test (...); Mécanismes intéressants ● Lien avec Java – Java vers JavaFx ● Librairie d’introspection net.java.javafx package test; import net.java.javafx.type.Value; public class MyClass { public void test (Value fxObject) { // Récupération de l’attribut "x" Integer x = fxObject.getAttribute(fxObject.getAttribute("x")).getInt(); System.out.println("fxObject.x =" + x); // Affiche "fxObject.x = 10" // Valuation de l’attribut "x" fxObject.setAttribute("x", 20); } } Limites ● Intégration à une applet – – ● ● Lourdeur des librairies (près de 3Mo) Nécessité de signer le .jar Les scripts sont recompilés à chaque exécution du programme Problèmes de concurrence non gérés par le « binding » Telosys ??? <request screen-name=‘EMPLOYEE’ action=‘load’ …> <response <param ... /> </request> screen-name=‘EMPLOYEE’ action=‘load’ …> <employee code=‘A001’ firstname=‘JEAN’ … /> </response> Frame { … TextField { value : ... } … } Telosys model = Model { code : ‘A001’ firstname : ‘JEAN’ lastname : ‘DUPONT’ … } <request screen-name=‘EMPLOYEE’ action=‘load’ …> <response <param ... /> </request> screen-name=‘EMPLOYEE’ action=‘load’ …> <employee code=‘A001’ firstname=‘JEAN’ … /> </response> JavaFx Binding Frame { … TextField { value : bind model.code } … } Telosys Requester <request screen-name=‘EMPLOYEE’ action=‘load’ …> <response <param ... /> </request> screen-name=‘EMPLOYEE’ action=‘load’ …> <employee code=‘A001’ firstname=‘JEAN’ … /> </response> model = Model { code : ‘A001’ firstname : ‘JEAN’ lastname : ‘DUPONT’ … } JavaFx Binding Frame { … TextField { value : bind model.code } … } Telosys et JavaFx • L’objet Requester – Classe Java (pour plus de souplesse) – Utilise l’objet XmlHttpRequest (librairie org.jdesktop) – Possède une méthode « map » • Permet de faire le mapping entre le XML et l’objet modèle • Par exemple : map (model, ‘code’, ‘code’) indique que l’attribut « model.code » correspond à l’attribut XML ‘code’ – Effectue les actions open, close, etc. et value l’objet modèle en conséquence Telosys ● Pas suffisant Requester model = Model { manager : ... } JavaFx Binding map (model, 'manager', 'manager'); String <response …> <employee manager='0'… /> </response> Frame { … Boolean CheckBox { selected : bind model.manager } … } Telosys ● Pas suffisant : Requester model = Model { manager : ... ??? } JavaFx Binding map (model, 'manager', 'manager'); String <response …> <employee manager='0'… /> </response> Frame { … Boolean CheckBox { selected : bind model.manager } … } Telosys ● Première solution : Requester model = Model { manager : ... Boolean } JavaFx Binding map (model, 'manager', 'manager', Boolean); String <response …> <employee manager='0'… /> </response> Frame { … Boolean CheckBox { selected : bind model.manager } … } Telosys ● Deuxième solution : Requester model = Model { manager : ... String } JavaFx Binding map (model, 'manager', 'manager'); String <response …> <employee manager='0'… /> </response> Frame { … CheckBox { Boolean selected : bind model.manager == '0' } … } Telosys ● Troisième solution – Réalisation de classes JavaFx dédiées à ce genre de conversion – Utilisation du mécanisme de triggering // class definition class BooleanMapper { attribute booleanValue : Boolean; attribute stringValue : String; } // Binding between attributes trigger on BooleanMapper.booleanValue = newValue { if (newValue) { stringValue = "1"; } else { stringValue = "0"; } } trigger on BooleanMapper.stringValue = newValue { booleanValue = not (newValue=="0"); } Telosys ● Troisième solution model = Model { manager : BooleanMapper { stringValue : ... Requester } } ... booleanValue : ... JavaFx Binding map (model.manager, 'stringValue', 'manager'); <response …> <employee manager='0'… /> </response> Frame { … CheckBox { selected : bind manager.booleanValue } … } Telosys ● Troisième solution model = Model { manager : BooleanMapper { String stringValue : ... Requester } } ... booleanValue : ... Boolean JavaFx Binding map (model.manager, 'stringValue', 'manager'); String <response …> <employee manager='0'… /> </response> Frame { … CheckBox { Boolean selected : bind manager.booleanValue } … } L'écran Employee Employee code firstname lastname shop manager L'écran Employee 1) Déclaration du modèle (et instanciation) class Model { attribute code: String; attribute firstName: String; attribute lastName: String; … } var model = Model { code:"A001" firstName: "" lastName: "" … }; L'écran Employee 2) Réalisation de la frame var frameEmployee = Frame { title : "Employee Page" content : FlowPanel { content : [ TextField { value: bind model.code }, TextField { value: bind model.firstname }, TextField { value: bind model.lastname } … Button { action : operation () { ... } } … ] } ... }; L'écran Employee 3) Instanciation du Requester et mapping var employeeRequester = new Requester ( "http://…/TelosysBookStore/action", "EMPLOYEE", "employee"); employeeRequester.map (model, "code", "code"); employeeRequester.map (model, "firstName", "firstname"); employeeRequester.map (model, "lastName", "surname"); … L'écran Employee Requester <request action=‘load’… > … </request> load 1 2 Load Save … Telosys 3 <response action=‘load’… > <data> … </data> </request> 4 binding 5 Valuation des attributs Model { code : ‘A001’ firstName : ‘JEAN’ lastname : ‘DUPONT’ … } Perspectives ● Un simple mapping entre attributs XML et attributs du modèle n’est pas suffisant <response ... > <data> <employee code='A001'.../> <employee code='A002'.../> <employee code='A003'.../> </data> </request> ● Il faut mapper chaque balise avec une classe JavaFx – mécanisme de sérialisation / désérialisation – Possible grâce à la librairie « net.java.javafx » Plan ● ● ● ● ● ● ● Contexte Organisation Méthodologie Flex JavaFx OpenLaszlo Conclusion OpenLaszlo ● ● ● ● ● Généralités Les fonctionnalités Outils de développement La communication distante La liaison des données ● Autres points ● BookStore ● ● Initialisation des écrans Architecture Généralités ● ● Framework permettant de créer des clients lourds pour le Web Les langages – XML – JavaScript XML JavaScript Servlet OpenLaszlo Flash DHTML OpenLaszlo ● Animations prédéfinies ● Mise en page (layout) ● La liaison des données (binding) ● ● Communication avec un serveur distant (XHR,SOAP...) Outils de création d'interfaces Outils de développement ● Spket – Outil léger basé sur Eclipse (auto-complétion) – Plugin ou .jar indépendant Outils de développement ● Plugin OpenLaszlo pour Eclipse – Déploiement – Auto-complétion – Vue OpenLaszlo – WYSIWYG – Projet abandonné en cours de développement La communication ● L'objet XMLHttpRequest – ● Impossible de remplir la requête L'objet DataSet – Stockage des données (XML) – Chargement de données ● ● Statique dans le code Remplissage – ● Méthode doRequest() – ● setQueryString({lzpostbody : request.serialize()}); Fonctionnement asynchrone DataPointer et l'évènement onData La liaison des données ● Entre DataSet et composant graphique ● Côté composant graphique – Du DataSet au composant ● – Attribut datapath (hérité de Node) Du composant au DataSet ● ● Handler sur l'évènement onValue Méthode updateData() Autres points ● Le débogueur – ● Importer du JavaScript – ● Messages de log : Debug.write(); <include href=”Requester.js”/> Les problèmes – Méthodes – Attributs BookStore ● Architecture existante – Requester – Interface et données Initialisation des écrans ● Identifiant de session – DataSet ● ● Ajout d'une JSP sur le serveur Données non disponibles par requêtes – Ex: liste des shops ● ● Statique Ajout d'une JSP sur le serveur Architecture ● Modèles de requêtes – DataSet – Parties statiques des requêtes ● Ex : <dataset name="loadRequest"> <request screen-name="EMPLOYEE"screen-id="0" action="load" elements="employee"> <params> <param code=""/> </params> </request> </dataset> Architecture ● Requester – Une méthode par requête – Prends le DataModel en paramètre ● DataModel ● Vue / Interface – Binding avec le DataModel Architecture ● Request Models Communication Requester 3 : Récupération de la requête 2 : Appel de la méthode 4 : Mise à jour Data Model Interface 1 : Binding 5 : Binding Plan ● ● ● ● ● ● ● Contexte Organisation Méthodologie Flex JavaFx OpenLaszlo Conclusion Conclusion ● ● ● ● ● Clients fonctionnels Architectures divergentes Travail restant – Quelques évolutions nécessaires sur Telosys – Architectures à refondre – Outillage pour le développement de RIA Projet bien calibré (temps, ressources) Étude de faisabilité réussie