Retrouvez cet article dans : Linux Magazine 91
AJAX (Asynchronous JAvascript and Xml) est un terme inventé par Jesse James Garret [1] en février 2005 [2] pour désigner une technologie ancienne de 1999. Il s’agit d’utiliser du code Javascript sur le client pour invoquer le serveur en tâche de fond et obtenir des données au format XML afin de modifier le Dynamic HTML et rafraîchir une partie de la page.
Cela consiste à exploiter l’objet XMLHttpRequest, présent dans les navigateurs récents. Ce composant permet de jouer le rôle d’un client HTTP, d’envoyer une requête et d’attendre la réponse pour pouvoir la manipuler.
AJAX permet d’optimiser le trafic en ne ramenant que les données nécessaires au rafraîchissement d’une page et non une page entière. De vingt à quatre-vingt pourcents d’une page sert à la présentation. AJAX permet d’optimiser les affichages de type " liste/détail ", de trier les données sur le client, d’aider l’utilisateur lors des saisies, d’enrichir les arbres ou d’alimenter les onglets… AJAX permet également d’offrir une approche " une seule page pour l’application ". Pour, par exemple, proposer un tableur ou un traitement de texte dans une page WEB.
Sous le terme AJAX, on intègre également d’autres utilisations du Javascript. Il s’agit d’améliorer l’ergonomie de l’application en ajoutant des composants graphiques complémentaires (aide à la saisie, saisie de date, arbre, onglet, menus, piles, accordéon, curseur, barre de progression, etc.)
Si toutes les données sont disponibles, les technologies Dynamic HTML (DHTML) et CSS permettent une mise jour dynamique de la structure de la page. Il est possible de proposer une ergonomie proche de celle d’une application cliente classique. Des parties de pages sont cachées ou affichées à la demande ; des fenêtres apparaissent ou disparaissent sur évènements ; des zones sont complétées dynamiquement à l’insu de l’utilisateur, des arbres s’enrichissent au fur et à mesure, etc. Si les données ne sont pas disponibles, une requête AJAX asynchrone y remédiera.
Cette technologie a pour but d’améliorer l’efficacité des internautes et l’attractivité des sites. En réduisant de quelques secondes les manipulations des utilisateurs, un centre d’appel améliore sa rentabilité. En attirant de nouveaux internautes, un site améliore son ROI.
Les applications traditionnelles offrent une très grande richesse de l’interface. Des logiciels comme Open Office proposent des fonctionnalités que l’on ne retrouve pas sur les sites internet. À l’opposé, les applications HTML offrent une très grande facilité d’accès. AJAX est une technologie permettant de rapprocher ces deux objectifs (figure 1).

Figure 1 : Positionnement d’AJAX
De plus en plus de sites proposent des ergonomies enrichies. Citons : www.netvibes.com, www.gmail.com, local.google.com, www.kiko.com, www.zimbra.com, etc. L’objectif est de s’affranchir de l’ordinateur. Tous les fichiers et les applications seront disponibles sur une ou plusieurs machines du réseau. À partir de n’importe quel poste, muni d’un simple navigateur, il sera possible de retrouver son environnement, d’éditer ses fichiers textes, ses feuilles de calculs, consulter ses mails, etc.
AJAX permet d’invoquer dynamiquement le serveur, afin d’enrichir la page en manipulant le Dynamic HTML. La page est mise à jour par zone. Une application web traditionnelle est décomposée en plusieurs pages. Une application AJAX demande une première page, puis des données au fur et à mesure des besoins (figure 2).

Figure 2 : Les requêtes HTML et AJAX
Avant, le navigateur présente un contenu ; le serveur héberge une application et les requêtes au serveur sont explicites. Avec AJAX, le navigateur héberge une application ; le serveur fournit des données et la plupart des requêtes au serveur sont implicites.
1. Comment cela fonctionne-t-il ?
Le rôle du serveur consiste à maintenir l’ensemble des objets de l’application et à envoyer quelques extraits au client. Dans la figure 3, le serveur transforme une partie des objets métier qu’il possède (les objets en marron) et les envoie au client sous un format compatible avec le HTTP. Le client transforme le flux en objets Javascript et manipule la page. Le client prend en charge quelques objets et s’occupe de les présenter. Il apporte alors des modifications à certains objets et les propage au serveur. Celui-ci peut alors décider ou non de sauver les modifications.
Nous revenons à une architecture de type client/serveur.
Il est préférable d’avoir dans le client un moteur générique de transformation du modèle vers du DHTML. Cela permet de généraliser le lien entre le modèle de donnée présent dans le client et la présentation. Beaucoup de frameworks AJAX travaillent sur cette approche. Ils utilisent des règles de transformations ou des annotations du XHTML. Certains proposent une connexion automatique entre les éléments de présentation et les objets présents sur le serveur.

Figure 3 : Export d’objets
Pour la communication entre le client et le serveur, il y a cinq étapes :
1. Création de paramètre de la requête pour le serveur.
2. Invocation de requêtes HTTP via l’objet XMLHttpRequest.
3. Attente de la réponse du serveur.
4. Analyse et transformation du résultat.
5. Modification dynamique de la page.
Reprenons les différentes étapes pour voir les stratégies possibles d’implémentations.
Pour la création de paramètre de la requête, il y a plusieurs approches :
- Création d’une URL de type GET. Les paramètres sont présents dans l’URL, séparés par un &.
- Récupération du formulaire HTTP. La requête HTTP est du type POST.
- Sérialisation d’objet Javascript. Il existe de nombreux formats (JSON, XML, CSV, etc.).
- Création d’une requête SOAP.
Ensuite, il faut invoquer le serveur. L’objet XMLHttpRequest est présent dans les navigateurs récents. Cela représente 92% des navigateurs en juillet 2006 d’après l’analyse effectuée par www.thecounter.com [3]. L’invocation est asynchrone. Il faut enregistrer un traitement qui sera invoqué lorsque la réponse est disponible.
Il reste à attendre que la requête soit terminée. Cela peut arriver immédiatement, mais parfois, lorsque le réseau n’est pas rapide ou que l’internaute utilise un modem, la réponse peut arriver plusieurs secondes après l’émission. Les réponses peuvent même ne jamais arriver ou arriver dans un ordre différent. Il faut alors traiter l’erreur.
Le serveur qui reçoit la requête est libre de retourner une réponse dans le format qu’il souhaite. Il peut retourner des extraits de pages HTML, des scripts JSON (JavaScript Object Notation, un code Javascript permettant lors de son exécution de construire une structure complexe d’objets), des flux XML (Content-Type : text/xml), des flux SOAP pour les services Web, du code Javascript ou un format propriétaire.
Comment le serveur peut-il générer ces différents formats ? Le tableau 1 propose différentes pistes.

Il faut ensuite transformer la réponse pour modifier la présentation. Si le serveur retourne des extraits de pages XHTML, il suffit d’inclure la réponse directement dans un tag <div/> via l’attribut innerHTML. Si le serveur retourne un flux JSON, il faut exécuter celui-ci avec la fonction eval() pour obtenir des grappes d’objets Javascript (attention à la sécurité), puis utiliser ces données pour manipuler le Dynamic HTML avec un script spécifique. Les méthodes createElement(), createTextNode() et appendChild() sont alors sollicitées.
Si le serveur retourne un flux XML, la première approche consiste à analyser les données pour manipuler le Dynamic HTML. La deuxième approche, plus simple, consiste à invoquer une transformation XSLT sur le client avec les données, pour générer un extrait XHTML et inclure le résultat dans un tag <div/> via l’attribut innerHTML.
L’approche Javascript permet d’animer la page, mais présente l’inconvénient d’être difficilement portable. Il faut tester, re-tester le code avec différents navigateurs et différentes versions du même navigateur.
L’approche XSLT utilise le moteur XSLT présent dans les navigateurs. Elle permet de générer des portions de pages à partir de données au format XML. La transformation génère du XHTML à insérer dans la page. Cette approche permet de facilement trier ou filtrer les données en mémoire. Par exemple, le clic sur la tête d’une colonne permet de modifier le critère de tri du filtre XSLT. Les données sont, à nouveau, transformées en XHTML, mais avec un ordre différent. Le résultat remplace le tableau avec les nouvelles données. C’est le moteur XSLT du navigateur qui s’est chargé de pratiquement tout. Il est facile d’utiliser XPath pour naviguer dans des structures complexes et de sélectionner les données à manipuler. Comme le moteur XSLT est compilé, il est beaucoup plus rapide qu’un équivalent en Javascript.
Les scripts XSLT peuvent être réutilisés dans plusieurs pages. Ils peuvent faire partie de la charte graphique du site, au même titre que la feuille de style. Ainsi, tous les tableaux, par exemple, auront le même look et le même comportement.
Si le serveur retourne une réponse SOAP, il est préférable d’avoir préalablement généré un proxy [6] Javascript d’invocation du service Web. Ainsi, l’invocation d’une fonction Javascript permet de formater la question et d’analyser la réponse. Des outils [7] se proposent de générer cela à partir de la description du service WEB en WSDL. La difficulté avec cette approche est que la réponse arrive de façon asynchrone. Le code peut alors analyser les objets Javascript et manipuler le Dynamic HTML.
Si le serveur retourne directement un script Javascript, il suffit d’invoquer eval() avec le résultat. Il faut faire très attention au risque de sécurité que cela peut engendrer.
Certains frameworks permettent d’apporter des modifications à la présentation à partir de critères de sélection type XPath ou CSS [8]. Ainsi, une règle peut demander que tous les tags de type <p/> doivent avoir leurs styles passés de " caché " à " visible " et inversement.
Marier l’invocation asynchrone du serveur et la génération dynamique de la page permet d’offrir une navigation visuelle (tooltips, fenêtre flottante), une saisie interactive (auto-complétion, vérification dynamique, drag-and-drop) ou des animations (effet visuel). Les données non disponibles pour manipuler le Dynamic HTML sont demandées au serveur lorsque cela est nécessaire (approche paresseuse). Le modèle objet dans la mémoire du navigateur peut alors s’enrichir dynamiquement par l’ajout de branches à un arbre par exemple.
On rencontre de plus en plus d’aide à la saisie lorsque le nombre de valeur possible est important, mais limité. Par exemple, la liste des communes françaises est connue. Après quelques caractères, une requête part vers le serveur pour lui demander de sélectionner les candidats compatibles avec la saisie. Une liste déroulante est alors alimentée avec les dix candidats les plus courants et une suite à la saisie est proposées. La première valeur est ajoutée à la saisie. L’ajout est pré-sélectionné afin que la saisie d’un nouveau caractère efface la proposition (figure 4). L’appui d’un nouveau caractère améliore la sélection en interrogeant à nouveau le serveur ou en filtrant la sélection précédente. Lorsqu’il ne reste qu’un choix, un bip retentit au premier caractère invalide. Cela est également utilisé pour les moteurs de recherche.

Figure 4 : Aide à la saisie
Un autre exemple consiste à alimenter des listes de sélections au fur et à mesure des choix de l’utilisateur. Une première liste propose les départements. Lorsque l’utilisateur a fait son choix, une requête AJAX permet d’obtenir tous les codes postaux du département. Lorsque l’utilisateur choisit un code postal, toutes les communes correspondantes sont proposées (figure 5). Sans AJAX, la page propose généralement un bouton permettant de faire une validation partielle du formulaire. Cela génère une nouvelle page complète, dont une liste de saisie complémentaire est alors initialisée. AJAX permet d’économiser ces échanges coûteux, tout en proposant une ergonomie plus cohérente.

Figure 5 : Listes déroulantes liées
Plus fort encore, des sites proposent de réorganiser les éléments d’un portail par drag-and-drop (figure 6).

Figure 6 : Drag-and-drop
1.1 Optimisation du réseau ?
Si l’application AJAX est bien construite, elle permet de réduire fortement la bande passante (figure 7).

Figure 7 : Comparaison du trafic réseau
AJAX peut réduire le volume des informations échangées, mais peut aussi écrouler le serveur. En effet, si trop de requêtes arrivent sur le serveur, celui-ci peut être saturé. Pour pallier cet inconvénient, il peut être judicieux d’organiser les soumissions vers le serveur. Il n’est pas nécessaire de générer une requête AJAX pour chaque caractère ou à chaque modification d’un champ. Il est préférable d’agréger plusieurs requêtes clientes dans une seule requête HTTP. Les requêtes sont postées dans la boîte aux lettres. Celle-ci est relevée périodiquement pour être envoyée au serveur. Chaque requête peut être identifiée par un ID, afin de pouvoir être écrasée si nécessaire, avant la levé du facteur.
Dans l’exemple présenté figure 8, un utilisateur sélectionne un premier champ, tape sur la touche ‘A’, la touche ‘B’, puis sélectionne un deuxième champ et saisit ‘999’. Enfin, l’utilisateur corrige sa saisie pour la remplacer par ‘0’. Des validations sur le serveur sont souhaitées pour l’application. Dans le premier scénario, sans optimisation, pratiquement chaque événement génère une requête AJAX. Dans le deuxième scénario, les requêtes sont accumulées avant d’être envoyées au serveur. Avec cette nouvelle approche, il peut y avoir un délai supplémentaire avant que le serveur ne détecte une anomalie, mais le nombre de requêtes est réduit. Certaines requêtes ont même disparues. Par exemple, la saisie de la valeur ‘999’ n’est pas signalée au serveur, car elle est immédiatement modifiée par la valeur ‘0’. La méthode abort() permet également d’interrompre une requête AJAX dont ont sait, un peu tard, que le résultat ne sera pas utilisé.

Figure 8 : Agrégation des requêtes
Avec une aide à la saisie, il y a un fort risque de saturer le serveur. Il faut impérativement faire une maquette et la tester en charge ! Ce n’est pas facile à cause des interactions utilisateurs complexes des applications AJAX. Les tests unitaires automatiques sont plus difficiles à réaliser avec une application AJAX qu’avec une application classique. Une capture du flux réseau pour pouvoir le rejouer permet d’identifier les problèmes d’infrastructures.
Le gain attendu en performance, en ne rafraîchissant pas toute la page, peut être annulé par une aide à la saisie. Le serveur et toute la chaîne de traitement doivent être adaptés pour pouvoir accepter de nombreuses petites requêtes.
1.2 Push : état du serveur
Pendant que l’utilisateur manipule son écran, des modifications peuvent intervenir sur le serveur. Pour connaître les modifications d’états du serveur, il y a deux approches :
- Interroger le serveur périodiquement [9] (Arrivée d’un nouveau mail ?).
- Désynchroniser l’invocation du serveur pour que celui-ci puisse prévenir le client immédiatement.
La deuxième approche est plus complexe, mais elle permet une réaction immédiate du client et réduit théoriquement le trafic réseau. Une requête est envoyée au serveur (figure 9). Celui-ci ne répond pas. Il laisse la requête en attente de réponse. Lorsque le serveur désire informer le client d’un événement, il répond enfin à la requête. Le client traite cela comme un événement du serveur et relance immédiatement une nouvelle requête en attente de l’événement suivant.

Figure 9 : Attente passive
Attention, cela risque de saturer le pool de connexion sur le serveur. En effet, les serveurs savent traiter un nombre limité de requêtes. En gardant des requêtes ouvertes, de nouvelles connexions risquent d’être refusées. Certains serveurs d’applications proposent des mécanismes spécifiques, afin de permettre une désynchronisation entre l’analyse de la requête et l’émission de la réponse. BEA, par exemple, propose une servlet spécifique AsyncServlet, permettant de ne pas exploser le serveur d’application.
En théorie, cela fonctionne. Mais, à cause des proxies et pare-feu, il est probable qu’une connexion, restée ouverte, soit automatiquement fermée après trente secondes. Cela oblige le client à rouvrir une connexion. Nous retombons alors dans la situation d’un pool dont la période est de trente secondes. Si la modification d’état du serveur doit être signalée le plus rapidement possible, situation d’un " chat " par exemple, il est judicieux d’utiliser cette technologie.
L’impact est parfois plus gênant si un proxy d’entreprise agrège les requêtes de différents clients dans la même connexion vers le serveur. Cette approche, autorisée par les proxies HTTP, permet de réduire le nombre de connexions vers le serveur cible. Le protocole HTTP 1.1 permet de cumuler les requêtes dans la même connexion. Les réponses doivent arriver dans l’ordre des requêtes. Cela entraîne qu’une requête n’est exécutée qu’après la précédente, car les réponses doivent arriver dans l’ordre. L’approche de Push consistant à garder la connexion ouverte, toutes les transactions suivantes sont bloquées. Il faut donc utiliser le protocole version 1.0 ou paramétrer le proxy HTTP pour qu’il n’agrège pas les requêtes d’utilisateurs différents.
1.3 Les données du client
Un état au moins partiel du serveur peut être gardé par le client (figure 3). Si les données ont évolué entre-temps, les techniques classiques de blocage optimiste peuvent être mises en place. C’est-à -dire que le client manipule des copies des données présentes sur le serveur. Entre-temps, elles peuvent évoluer sur le serveur, le client n’en est pas informé. Cette situation étant considérée comme rare, il n’est pas nécessaire de mettre en place des mécanismes complexes de blocage. À la place, un timestamp ou un numéro de version permet de détecter si un objet a évolué. Lorsque le client renvoie ses versions des objets, le serveur peut vérifier si elles sont toujours compatibles avec les versions courantes dans la base de donnée. Dans les cas limites, le client est prévenu tardivement que les données qu’il a utilisées n’étaient pas valides, que son cache n’est pas à jour par rapport aux valeurs présentes sur le serveur. Un traitement d’erreur spécifique est alors exécuté. L’utilisateur est informé du problème et doit prendre une décision : écraser les données dans la base de données ou rafraîchir les données sur le client et recommencer à y apporter les modifications. Cette situation étant rare, cette stratégie de blocage est qualifiée d’optimiste.
Où placer les données du client ? Elles peuvent être présentes dans la page si l’application propose l’approche " Une seule page pour l’application ". Si l’utilisateur peut naviguer entre plusieurs pages, les données sont perdues d’une page à une autre. Pour une durée de vie plus importante, il faut s’appuyer sur les caches HTTP, des IFrames, les cookies du navigateur (4 Ko x 20 cookies = 80 ko) ou les cookies " Flash " qui acceptent une taille plus importante. Avec des privilèges, il est possible d’utiliser le disque dur de l’utilisateur (via un ActiveX ou une applet Java signée).
Attention, aucune donnée présente chez le client n’est digne de confiance. En effet, celui-ci peut les manipuler avant de les envoyer vers le serveur. De même, un virus ou une attaque de type Cross Site Scripting (injection de Javascript dans une page) peut révéler à un pirate des informations confidentielles. Il faut se prémunir contre cela en cryptant éventuellement les données persistantes chez le client et en auditant le site pour éviter les injections de script.
1.4 Gestion de la navigation
Pour ne pas perdre les utilisateurs avec une nouvelle ergonomie, il ne faut pas modifier leurs habitudes. Les internautes utilisent les boutons " suivant ", " précédant ", " rafraîchir " et souhaitent pouvoir placer des signets. Si la page est très mobile, ces boutons risquent de ne pas correspondre aux désirs des utilisateurs. Les signets peuvent mener au début de l’application, et non à l’étape que souhaitait mémoriser l’internaute.
Pour résoudre cela, il faut utiliser les marqueurs intra page des URL, à l’aide du caractère dièse. Chaque étape de la page peut être synthétisée par une URL différente, sans rafraîchissement de la page. L’instruction window.location.replace(newHash) permet de faire évoluer l’URL de la page. Par exemple, l’URL peut devenir quelque chose comme ceci : http://monsite.org/ajaxapp#wizard:step2. L’utilisateur peut alors mémoriser un signet pour l’étape deux du Wizard. Lors de l’initialisation de la page, l’URL est analysée. Cela permet à l’application de restituer la page à l’étape correspondante.
Si les modifications ne sont pas facilement synthétisées par une simple valeur, le contexte de la page peut être sérialisé et encodé en Base64 (encodage binaire vers ASCII, utilisant 64 symboles). Le résultat de ce calcul est ajouté à l’URL. Lors de l’initialisation de la page, il est alors possible de restituer le contexte de la page et d’ajuster l’affichage en conséquence. Cette approche consiste à avoir une sorte de session sur le client, session mémorisée dans l’URL ! Des frameworks proposent des services [10] de manipulation d’URL pour les applications AJAX.
1.5 Gestion des erreurs
À l’usage, la gestion des erreurs est complexe. Les requêtes étant asynchrones, les erreurs sont découvertes tardivement. Entre-temps, l’utilisateur est déjà en train de saisir un autre champ. Il faut impérativement mettre en place un mécanisme de notification de l’utilisateur ne perturbant pas sa saisie. Par exemple, l’ajout d’un message d’erreur à côté du champ ; le changement de couleur du champ ou du libellé ; l’ajout d’icône d’état de tous les traitements asynchrones. Il peut être nécessaire de classifier les erreurs pour adapter la notification de l’utilisateur suivant l’urgence. Sinon, l’utilisateur risque de recevoir une alerte concernant un champ saisi, il y a quelque temps. L’utilisateur est mentalement parti vers d’autres problèmes. L’alerte va lui faire interrompre la saisie en cours, générant plus tard une autre alerte, etc.
Une approche pour faire cela consiste à utiliser le marqueur <label/> qui permet d’associer un texte à un champ, et permet aux outils de synthèse vocale d’informer les malvoyants du libellé de la saisie.
 <label for="nom">Nom</label> <input size="20" type="text" name="nom" />
Un framework peut alors retrouver automatiquement le libellé et lui modifier son style CSS.
Les traitements AJAX étant essentiellement asynchrones, cette particularité doit être prise en compte lors de la conception des pages. Il est possible de rendre synchrone les invocations du serveur, mais cela s’effectue avec une attente active et risque fortement de figer le navigateur.
2. Pour quelles applications ?
Alan Cooper propose de classer les applications en deux familles [11] : les applications souveraines et les applications transitoires. Les applications souveraines sont utilisées quotidiennement pour de longues périodes. Elles prennent toute l’attention de l’utilisateur. Elles sont conçues pour une utilisation optimum, au prix d’une formation.
Les applications transitoires sont utilisées occasionnellement pour de courtes périodes. L’utilisateur interrompt son activité principale avant de la reprendre. Elles sont conçues pour une accessibilité immédiate, sans formation.
Suivant la famille de l’application, les améliorations de l’ergonomie seront différentes. AJAX offrant beaucoup plus de liberté sur l’ergonomie, de nouveaux horizons s’ouvrent pour les ergonomes. Les principes d’ergonomies nouveaux (drag-and-drop, contrôles en tâche de fond, etc.) peuvent dérouter les utilisateurs. Avant AJAX, les ergonomies possibles pour proposer un processus étaient évidentes, imposées par les contraintes du HTML. Dorénavant, AJAX permet plus d’ouverture et d’interaction avec les utilisateurs. Les internautes ont pris des habitudes leur permettant d’être immédiatement efficaces sur n’importe quel site Internet. Apporter des innovations bousculant leurs habitudes risque d’être contre productif.
Pour les applications transitoires, AJAX doit être utilisé avec parcimonie, afin d’aider l’utilisateur sans trop le bousculer. L’aider et le conseiller lors de la saisie d’un critère de recherche est une bonne chose. Les listes déroulantes liées permettent d’éviter les soumissions partielles d’un formulaire et améliore discrètement l’ergonomie, tout en restant dans les usages du net.
Par contre, l’utilisation du drag-and-drop n’est pas évidente pour un internaute arrivant pour la première fois sur un site. De même, sauver les modifications de l’utilisateur dès qu’il coche une case à cocher n’est pas conforme aux usages. L’utilisateur va chercher en vain le bouton de soumission. Cacher ou présenter des zones sur une page ou proposer des onglets ne perturbe pas l’utilisateur.
Que les informations complémentaires soient chargées en tâche de fond et non lors de la récupération de la page ne concerne pas l’internaute ! Il s’agit de problèmes techniques, résolus par AJAX, à l’insu de l’utilisateur. Il faut éviter d’aller trop loin et de devoir former l’utilisateur à l’utilisation du site. Il ne faut pas oublier que le concurrent est à un clic de là  ! Ces technologies doivent être utilisées après une bonne analyse du public visé et de l’investissement qui lui est demandé. Les applications transitoires peuvent gagner en attractivité et en facilité d’utilisation.
Pour les applications souveraines, utilisées quotidiennement, les possibilités d’amélioration de l’ergonomie sont plus importantes. Cela permet d’améliorer l’efficacité des utilisateurs. Des tests [12] en laboratoire ont montré un gain de 30% pour la saisie et l’édition d’informations comptables.
AJAX peut également être utilisé pour enrichir les portails. Une page d’un portail est décomposée en plusieurs éléments graphiques, souvent autonomes les uns les autres. AJAX offre la possibilité de faire évoluer chaque portlet sans devoir imposer un rechargement de toute la page. La personnalisation du portail peut également bénéficier des techniques de drag-and-drop. Les portlets peuvent être réorganisés physiquement sur la page, sans devoir proposer une ergonomie complexe (figure 6). Il existe des Best Practices " JSR168 & AJAX [13] ". Le JSR286 (Portlet 2.0) y réfléchit également.
Les projets AJAX entraînent une réelle réflexion sur l’ergonomie. Il est facile de louper la cible, en proposant une ergonomie élégante et animée, mais moins efficace qu’une application WEB classique.
3. Les pièges
AJAX présente un certain nombre de pièges qu’il est bon de connaître avant de se précipiter à concevoir une nouvelle application. Il faut déjà savoir qu’une application AJAX peut réduire l’accès à l’application à une partie de la population. Par exemple, les utilisateurs handicapés [14] ne peuvent plus y accéder avec leurs extensions habituelles (synthétiseur vocaux, MozBraille [15], etc.). Il existe des règles d’accessibilité [16] imposées par les administrations. Les applications AJAX sont incompatibles avec les règles d’accès aux contenus Web [17]. Le W3C propose une feuille de route [18] pour offrir des interfaces riches à cette population.
Les navigateurs anciens, ou dont les règles de sécurité interdisent l’utilisation de Javascript, ne peuvent plus utiliser l’application. Il faut prévoir une solution en mode " dégradé ". Gmail, par exemple, propose deux versions de l’application. L’une utilise AJAX, l’autre n’utilise ni AJAX ni le Javascript.
Si AJAX est utilisé pour améliorer l’ergonomie, il est relativement facile d’avoir une stratégie de repli plus classique. Par exemple, le champ de saisie d’un moteur de recherche ne bénéficie plus alors des suggestions ; les listes déroulantes liées rechargent toute la page dès la perte du focus au lieu de se contenter d’obtenir les quelques informations manquantes ; des boutons ou des formulaires compensent l’absence de drag-and-drop d’un portail. Pour les applications transitoires, AJAX doit être utilisé comme un complément à une application Web classique, et non comme un élément majeur de l’ergonomie.
Les pages AJAX doivent pouvoir être indexées par les moteurs de recherches, sous peine de disparaître du net. Si l’application ne propose pas une ergonomie du type " application dans une seule page ", les moteurs continueront à pouvoir référencer les pages. Sinon, il faut proposer des pages particulières pour les robots. Lors de la détection du robot de Google ou d’autres, des pages non-AJAX sont retournées, avec les données importantes.
Les développeurs doivent être vigilants sur la taille du code Javascript nécessaire à l’application. Même compactés [19], les Javascripts AJAX nécessaires peuvent être très volumineux (>100 ko). Il faut compenser cela avec des paramètres de cache de la requête HTTP, et une réutilisation sur de nombreuses pages. Ils doivent également faire attention à la quantité de mémoire nécessaire sur le client. Dès la conception, il faut chercher à économiser les ressources. Tous les internautes n’ont pas la chance d’avoir un terminal généreusement pourvu. Des frameworks éviteront de consommer quatre-vingt pourcents du temps de développement à régler les problèmes de portabilité.
Les requêtes AJAX ne maintiennent pas toujours en vie la session [20] de l’utilisateur. Afin de ne pas la perdre lors de l’utilisation d’une application AJAX, il faut générer une requête périodiquement (entraînant un trafic supplémentaire) ou que l’application AJAX demande l’état de la session avant de laisser l’utilisateur continuer à manipuler les données. La durée de vie de la session d’une application AJAX peut également être adaptée au contexte. Ces problèmes disparaissent si l’intégration d’AJAX est superficielle, et que les pages HTML sont toujours utilisées, mais enrichies.
Internet Explorer ne possède pas de ramasse-miettes efficace pour le code Javascript [21]. Cela ne posait pas de problème pour les applications changeant régulièrement de page, car IE fait alors le ménage. Les applications AJAX sont différentes. Une page peut être utilisée pendant longtemps, générant des fuites mémoires très difficiles à localiser.
Les impressions et l’utilisation " off-line " ne sont pas traitées par AJAX. Il est également difficile de proposer une approche multi-canal type PDA, WebTV, etc. L’expérience sur de nombreux sites a permis d’identifier quelques cent cinquante-trois règles de bonnes pratiques pour les services en lignes [22]. Les applications AJAX en violent plusieurs.
Au niveau sécurité, des difficultés nouvelles peuvent arriver. Les navigateurs interdisent au client de communiquer avec un serveur différent de celui ayant livré le script. Internet Explorer affiche alors une fenêtre demandant l’autorisation à l’utilisateur. Celle-ci n’est affichée qu’une seule fois. Avec Mozilla Firefox, une fenêtre est affichée pour chaque requête. Cela peut être levé en signant les scripts. Pour contourner cette difficulté, il faut proposer un reverse proxy [23] sur le serveur, pour pouvoir invoquer d’autres sites. Cela peut présenter un risque de vulnérabilité et intéressera sûrement les pirates en mal d’anonymat.
Un reverse proxy de service Web (figure 10) peut ajouter les paramètres d’identifications à la requête, à partir des informations de la session d’utilisateur. Cela permet de propager l’identité de l’utilisateur à l’aide du serveur, sans présenter de vulnérabilité sur le client. Un ESB (Entreprise Service Bus) peut jouer ce rôle d’enrichissement du service Web.

Figure 10 : Reverse proxy
Les applications AJAX peuvent également présenter des risques de sécurité. Par exemple, les cookies mémorisant l’état du client sont visibles et manipulables. Le serveur expose des services métier. Ceux-ci doivent être codés en intégrant le risque d’être invoqué en dehors de l’application. Les échanges avec le serveur doivent être sécurisés, cryptés et authentifiés, les paramètres vérifiés.
Les frameworks AJAX peuvent présenter des risques de déni de service ou des vulnérabilités pour le serveur. Si le source n’est pas public, l’audit n’est pas toujours possible. Par exemple, un audit rapide du framework de Google (GWT [24]) montre qu’il est possible de consommer toute la mémoire du serveur en envoyant un flux bien choisi. L’algorithme de dé-sérialisation ne possède pas de limite pour la taille des tableaux en mémoire. En envoyant un flux indiquant un tableau d’octets d’un million d’éléments, le serveur va allouer l’espace nécessaire avant de lire chaque octet.w
Un code AJAX mal contrôlé peut envoyer à son propre serveur des requêtes à l’infini, créant ainsi une auto-attaque par saturation. Il existe des virus AJAX [25] et des outils [26] d’analyse de code AJAX.
Plus de 150 frameworks sont recensés sur Ajaxpatterns.org. C’est un monde très instable, car les pré-requis techniques sont simples. Il suffit de savoir utiliser l’objet XMLHttpRequest. Certains frameworks se détachent et sont soutenus par des entreprises renommées. Des produits commerciaux proposent des approches originales et riches.
Les approches sont très différentes. Certains ne s’occupent que du tiers client, d’autres facilitent la communication entre le client et le serveur, suppriment l’adhérence à Javascript ou enrichissent des frameworks existants. Certains sont orientés " une seule page par application " ou proposent d’enrichir le XHTML de comportements dynamiques. L’intégration d’AJAX s’effectue alors sans aucun Javascript.
A mon avis, l’approche la plus prometteuse consiste à enrichir les frameworks serveur, orientés " composant ". C’est le cas de JSF et de .Net. Ces frameworks proposent de réutiliser et d’assembler des composants d’ergonomies. Sun vient de publier un tutoriel [27] pour l’intégration d’AJAX dans JSF.
Ces frameworks gardent une connaissance fine de la structure de la page. Si un événement client peut avoir un impact sur un composant coté serveur, une requête est envoyée et l’information est propagée au composant. La page est alors entièrement recalculée avant d’être retournée au client.
En greffant des composants AJAX, la communication entre le composant présent dans le client et son alter ego sur le serveur s’effectue en direct. Il n’est plus nécessaire de recalculer toute la page. De plus, les composants peuvent théoriquement proposer deux versions : une classique sans utilisation d’AJAX et une version utilisant AJAX. Ainsi, il n’est plus nécessaire de rédiger deux fois la même application. Si le navigateur refuse les fonctionnalités AJAX, l’application s’adapte. Pour la saisie d’une ville par exemple, le composant peut proposer une aide à la saisie ou un bouton de validation partielle du formulaire ; les listes déroulantes liées peuvent être traduites comme un événement JSF ou .NET classique, ou transformées en événement AJAX.
Coté client, je préconise d’utiliser des frameworks proposant un moteur générique de transformation des données pour les insérer dans la présentation. Certains utilisent des annotations du XHTML, d’autres des feuilles de styles, etc. Ces approches permettent de s’affranchir des problèmes de Javascript.
Il y a une évolution dans le rôle du navigateur et du serveur. Avant, le navigateur présente un contenu ; le serveur héberge une application ; les requêtes au serveur sont explicites. Après, le navigateur héberge une application ; le serveur fournit des données ; la plupart des requêtes au serveur sont implicites.
4. Conseils
Un seul objectif : générer de la valeur en améliorant la productivité et/ou l’attractivité. Il faut utiliser AJAX à bon escient :
- Sur les champs de moteur de recherche.
- Sur les pages mettant en place un processus à plusieurs étapes.
- Pour manipuler de longues listes de données.
- Pour réduire le risque d’une mauvaise saisie de l’utilisateur ou pour effectuer des vérifications de surface. Attention à ne pas effectuer cela sur chaque champ.
- N’utiliser les fonctions Drag-and-drop que si cela apporte un véritable avantage ergonomique. Les réserver de préférence aux applications souveraines.
Limiter AJAX au nécessaire. S’il s’agit d’améliorer la productivité, on se concentrera sur les écrans ou fonctions les plus utilisées. Il faut éviter de casser les conventions (retour, signet, indexation par les moteurs de recherches, etc.) et indiquer les changements [28] sur la page ; expliquez à l’utilisateur par un message temporaire pourquoi il attend.
Proposez un framework de notification non intrusif sur l’interaction de l’utilisateur. Si une information est à communiquer au client, lui indiquer directement dans la page et non par une boîte d’alerte.
Pour ne pas s’exclure d’une partie du public, il faut proposer des alternatives à l’utilisation d’AJAX.
Pour coder l’application, ne réinventez pas la roue : utilisez des frameworks après les avoir sélectionnés sur la pérennité des stratégies mises en place. Les choix seront différents s’il s’agit d’intégrer AJAX à des applications existantes ou pour de nouvelles applications. Commencez par normaliser vos pages en XHTML. Ce format rigoureux facilite ensuite les manipulations.
Coté serveur, il faut répondre aux requêtes le plus vite possible. Utilisez des caches puissants pour éviter d’interroger trop souvent la base de donnée. Paramétrez les requêtes HTTP pour exploiter toutes les possibilités de caches du protocole (En-tête ETAG [29] ). Pensez au maintien en vie de la session de l’utilisateur.
Coté client, utilisez un cache Javascript sur le navigateur pour réduire le nombre de requêtes vers le serveur (agrégation de requêtes, etc.). Utilisez les Design Patterns [30] de développement en Javascript. N’oubliez pas de tester l’application sur tous les navigateurs et toutes les plateformes. Vérifiez son comportement sur un LAN et un WAN.
Conclusion
Il est raisonnable d’utiliser cette technologie en tant que complément à une application WEB classique. Offrir des aides à l’utilisateur, des suggestions de réponses, le remplissage dynamique des listes déroulantes ne perturbe pas les applications classiques. Il s’agit d’offrir des composants ergonomiques avancés. Avec cette approche, il est facile de proposer des solutions alternatives plus classiques, pour permettre à tous les internautes d’utiliser l’application. Cette approche évite de devoir gérer la durée de vie de la session, la gestion de la persistance des objets métier sur le client, une gestion complexe de l’historique ou de la navigation, d’exposer trop ouvertement les objets métier présents sur le serveur, etc. Dans le cas d’une nouvelle application, il est préférable d’utiliser un framework à base de composants (JSF ou .NET) pour limiter la complexité du client, et garder la maîtrise de l’utilisateur sur le serveur. Sinon, différents frameworks ou composants client permettent d’enrichir une application existante.
Concevoir une application du type " une seule page pour l’application " est plus ambitieux et plus risqué. Pour certaines applications souveraines, exigeant une grande richesse ergonomique, cela permet de revamper une application existante ou d’offrir de nouvelles applications, en bénéficiant de la standardisation des postes des utilisateurs et des facilités de déploiements qu’offrent les navigateurs. Mais il faut alors s’interroger si une approche RDA (Rich Desktop Application) n’est pas préférable. Il est vrai que le déploiement est un peu plus complexe qu’avec un navigateur et que les applications exigent plus de ressource sur le poste du client. Les technologies Java Web Start [31] de Sun ou No-Touch Deployment [32] de Microsoft offrent des approches séduisantes. Une application RDA sera plus à même de gérer les impressions, les interactions avec les autres applications ou les périphériques du poste de l’utilisateur (Office, carte à puce, lecteur de code barre, etc.)
Open Ajax Aliance [33] est une initiative qui se propose d’unifier les efforts sur AJAX. Il est trop tôt pour savoir s’il en sortira quelque chose.
Le phénomène Web 2.0 (usages et combinaison des technologies Web telle AJAX) est un axe de recherche fort pour les équipes Innovation d’Atos Origin. L’objectif est d’accompagner nos clients afin de tirer profit de l’usage de ces nouvelles technologies, ainsi que pour la création de nouveaux services. Nous pensons qu’AJAX peut apporter de réelles opportunités d’attractivité et d’efficacité pour les utilisateurs. Les projets réussis utilisent AJAX raisonnablement et offrent des solutions alternatives pour les internautes ne pouvant bénéficier de cette évolution technologique. L’utilisation d’un framework est indispensable.
Références
- [1] http://en.wikipedia.org/wiki/Jesse_James_Garrett
- [2] http://www.adaptivepath.com/publications/essays/archives/000385.php
- [3] http://www.thecounter.com/stats/2006/July/browser.php
- [4] http://www.json.org/java/
- [5] http://ws.apache.org/axis/
- [6] http://www-128.ibm.com/developerworks/web/library/ws-wsajax/?ca=dgr-lnxw071SOAP-Ajax
- [7] http://www.codeproject.com/soap/JavaScriptProxy_01.asp
- [8] http://www.openrico.org/
- [9] https://bpcatalog.dev.java.net/nonav/ajax/refreshing-data/design.html
- [10] http://codinginparadise.org/projects/dhtml_history/README.html
- [11] http://www.cooper.com/articles/art_your_programs_posture.htm
- [12] http://www.developer.com/java/other/article.php/3554271
- [13] http://developers.sun.com/prodtech/portalserver/reference/techart/ajax-portlets.html
- [14] http://www.acces-pour-tous.net/
- [15] http://mozbraille.mozdev.org/
- [16] http://www.adae.gouv.fr/article.php3?id_article=246
- [17] http://www.w3.org/TR/WAI-WEBCONTENT/
- [18] http://www.w3.org/TR/2006/WD-aria-roadmap-20060926/
- [19] http://www.google.fr/search?q=javascript+compress
- [20] http://forum.alsacreations.com/topic-24-10462-1-AJAX-et-sessions.html
- [21] http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp
- [22] http://www.opquast.com/bonnes-pratiques/liste/
- [23] http://developer.yahoo.com/javascript/howto-proxy.html
- [24] http://code.google.com/webtoolkit/
- [25] http://namb.la/popular/tech.html
- [26] http://www.denimgroup.com/Sprajax/
- [27] http://java.sun.com/javaee/javaserverfaces/ajax/tutorial.jsp
- [28] http://www.yourtotalsite.com/archives/javascript/yellowfade_technique_for/Default.aspx
- [29] http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19
- [30] http://en.wikipedia.org/wiki/Design_pattern_(computer_science)
- [31] http://java.sun.com/products/javawebstart/
- [32] http://support.microsoft.com/kb/837909/en-us
- [33] http://www.zimbra.com/blog/archives/2006/05/openajax_update.html
 Retrouvez cet article dans : Linux Magazine 91

