Projet de fin d’étude Option ILR Passerelle WEB/ORACLE Antoine Sejournet Jérôme Pellegrin Table des matières 1. Technique côté serveur ..............................................................................................3 1.1. 1.2. CGI............................................................................................................................................. 3 Servlets Java .............................................................................................................................. 4 2. Présentation de la passerelle .....................................................................................4 2.1. 2.2. Aperçu de son rôle ..................................................................................................................... 4 Les paramètres d’utilisation ....................................................................................................... 4 3. Description de l’application ......................................................................................6 3.1. 3.2. 3.3. 3.4. Systèmes et structure de l’application ....................................................................................... 6 Code JAVA ................................................................................................................................ 7 Modèle de données XML et les feuilles de style XSL .............................................................. 8 Méthode de développement ....................................................................................................... 8 4. TODOS ........................................................................................................................9 2 1. Technique côté serveur Il y a quelques années, la seule solution permettant d’envoyer des données dynamiques sur le Web était l’interface CGI. Les programmes CGI offraient un moyen simple de créer des applications WEB acceptant les données de l’utilisateur, et interrogeant une base de données, puis envoyant les résultats au navigateur. Les développeurs de serveur WEB ont élaboré des interfaces de programmation (API), afin de développer du code in-process utilisé pour traiter les requêtes WEB. Les dernières technologies WEB côté serveur sont appelées servlets Java, JSP (Java Server Pages) et pages ASP (Active Server Pages). 1.1. CGI CGI est la technologie WEB côté serveur la plus courante. C’est pourquoi les programmes CGI sont pris en charge par la plupart des serveurs WEB actuels. Un programme CGI peut être écrit dans presque tous les langages de programmation. Pourtant le langage le plus utilisé est le langage PERL. Les serveurs WEB qui mettent en œuvre CGI agissent comme une passerelle entre la requête de l’utilisateur et les données dont elle a besoin. Pour cela, ils commencent par créer un processus dans lequel le programme sera exécuté (voir figure 1). Ensuite, ils chargent les environnements d’exécution nécessaires, ainsi que le programme. Enfin, ils transmettent une requête et appellent le programme. Une fois le programme terminé, le serveur WEB lit la réponse dans le STDOUT. Serveur WEB Interface CGI Processus 1 Processus 2 Processus 3 Environnement d’exécution Environnement d’exécution Environnement d’exécution Variable d’environnement Variable d’environnement Variable d’environnement Programme Programme Programme Figure 1: Fonctionnement d’un CGI L’inconvénient majeur de CGI réside dans son manque d’évolutivité. En effet, chaque fois que le serveur WEB reçoit une requête, un processus est créé. Il est aisé de deviner ce qui se produit sur le serveur lorsqu’un grand nombre de requêtes sont reçues au même moment. Dans ce cas, le serveur est très sollicité et peut même planter. 3 1.2. Servlets Java Une alternative aux scripts CGI est la technologie servlet Java. Cette technologie est intégrée à l’API J2EE permettent l’interconnection des programmes avec les services et les données de l’entreprise. Elle permet de créer facilement des pages dynamiques et d’enrichir les fonctionnalités d’un serveur WEB. Une servlet Java est un programme côté serveur qui traite les requêtes HTTP et renvoie des résultats sous forme de réponse HTTP. A cet égard, Java ressemble beaucoup au CGI, mais la comparaison s’arrête là. Une servlet est comme une applet dépourvue d’interface graphique, qui s’exécute sur le serveur WEB. Son cycle de vie est semblable à une applet et elle s’exécute au sein d’une machine virtuelle. Un des avantages des servlets sur les CGI est que lorsqu’un utilisateur émet une requête relative à une servlet particulière, le serveur utilise simplement un autre thread et non un autre processus, puis traite la requête en question. Les performances n’en sont qu’améliorées car plusieurs requêtes ne génèrent pas systématiquement plusieurs processus. L’autre avantage majeur est la portabilité due à l’utilisation de la machine virtuelle pour l’exécution des servlets. 2. Présentation de la passerelle 2.1. Aperçu de son rôle Le principe de fonctionnement de la passerelle est rigoureusement identique à celui de sa précédente version écrite par Bruno Defude en Pro C et appelée par l’intermédiaire d’un script CGI. Un ensemble de formulaires plus ou moins complexes font appel à la passerelle pour interagir de manière structurée avec un serveur Oracle. La construction de ces formulaires est l’œuvre du webmaster mais n’entre pas dans la conception de la passerelle. Dans le cas de la passerelle CGI, tous les formulaires font appel à un script CGI unique résidant sur le serveur dont la réponse est modulable selon les valeurs des paramètres transmis par le formulaire de départ. Au niveau du serveur, un serveur WEB reçoit les requêtes HTTP des utilisateurs et transmet ces requêtes à la passerelle qui analyse les paramètres, interroge le serveur Oracle, puis formate le ou les résultat(s) au format HTML. 2.2. Les paramètres d’utilisation La description des paramètres se trouve en ligne sur le site BD de l’INT. Néanmoins, leur utilisation est légèrement différente avec notre version finale de la passerelle. Nous allons voir la liste des variables à positionner avec les valeurs possibles et leurs interdépendances. Nous donnons ici la liste des variables en précisant celles qui sont obligatoires ou non. Les noms de variables sont donnés ici en minuscules et doivent être déclarée en minuscules : uid : obligatoire, donne la chaîne de connexion à Oracle (par exemple defude/[email protected]) sqlstatement : obligatoire, donne la requête SQL à soumettre à Oracle (si elle n'est pas utilisée, comme dans le cas d'une insertion, on peut lui mettre une valeur vide). Par exemple « select * from applivins ». mode : obligatoire, donne le mode avec lequel on veut lancer le programme. Les différentes valeurs sont les suivantes (doivent être données en majuscules) : - NOR (pour NORmal) : c'est le mode standard dans le sens ou aucun traitement particulier n'est fait, si ce n'est exécuter la requête transmise et afficher le résultat. 4 - - - - INS (pour INSertion) : c'est le mode qui permet de sélectionner une relation (indiquée dans la variable table qui doit alors être positionnée) pour produire un formulaire d'insertion d'un tuple dans celle-ci. MAJ (pour Mise A Jour) : c'est le mode qui permet de sélectionner une relation (indiquée dans la variable table qui doit alors être positionnée) pour produire un formulaire d'insertion d'un tuple dans celle-ci. COP (pour COPie) : ce mode permet de générer un formulaire permettant de copier la valeur d'un attribut retourné dans une variable d'un autre formulaire QBE (pour Query By Example) : c'est le mode qui permet de générer un formulaire d'interrogation "à la QBE" pour la relation sélectionnée (donnée dans la variable table qui est donc obligatoire pour ce mode). L'interrogation se fait en saisissant les contraintes dans les colonnes de la relation (cela s'exprime sous la forme d'un opérateur de comparaison, = par exemple, suivi d'une constante ou d'un nom d'attribut. HYP (pour (HYPpertexte) : c'est le mode qui permet une navigation dans la base. Le point de départ doit être une requête SQL de type SELECT. Le principe de la navigation est d'interpréter les clés primaires comme donnant un accès en mode NOR au tuple sélectionné et les clés étrangères comme donnant un accès en mode NOR au tuple sélectionné. Les clés primaires et étrangères peuvent être soit calculées à partir du dictionnaire de données (si la requête spécifiée porte sur une seule relation) ou bien données dans les variables pkey et fkey. Pour distinguer à l'affichage les clés primaires et étrangères, nous utilisons la couleur bleu dans les boutons représentant les clés primaires et la couleur rouge pour les clés secondaires. Lors du premier appel en mode HYP, les boutons permettant la génération des formulaires d'interrogation type QBE et d'insertion d'un tuple sont générés. pkey, obligatoire en mode HYP si la requête porte sur plus d'une relation (sauf si fkey est présente). La valeur de pkey est une liste (d'au moins un élément) de couples nom d'attribut, nom de relation. Le séparateur entre attribut et relation est le caractère « : » et le séparateur entre couples est le caractère « ; ». Par exemple NUM:VINS;NVIN:RECOLTES . Il faut noter qu'il ne faut pas de caractères blancs et que les noms d'attributs et de relations doivent être en majuscules. Les attributs et relations cités dans la variable pkey doivent apparaitre dans la requête donnée dans la variable sqlstatement. Celle ci peut être multi-relations (c'est pourquoi un nom de relation est associé au nom de l'attribut). Seules les clés mono-attributs peuvent être utilisées. De même, l'ordre d'énumération des couples doit être conforme à celui des attributs dans la clause SELECT de la requête. fkey, obligatoire en mode HYP si la requête porte sur plus d'une relation (sauf si pkey est présente). La valeur de fkey est une liste de triplets (d'au moins un élément) nom d'attribut (dans la relation source), nom de relation cible, nom d'attribut dans la relation cible. Le séparateur à l'intérieur du triplet est le caractère « : » et le séparateur de triplets est le caractère « ; ». Si on veut indiquer que l'attribut NVIN de la requête est clé étrangère sur l'attribut NUM de la relation VINS, on notera : NVIN:VINS:NUM . Si par hasard, le nom de l'attribut cible est le même que celui de l'attribut source, il peut être omis (on aura alors un couple et non un triplet). On retrouve également les contraintes de pkey portant sur les caractères majuscules et blancs, l'appartenance des attributs sources à la requête, le fait que la clé doit être mono-attribut ainsi que l'ordre d'écriture des triplets. table, obligatoire en mode INS ou en mode HYP si pkey et fkey ne sont pas présentes. Par exemple RECOLTES. copy, optionnel, permet de produire comme résultat un formulaire permettant de copier la valeur d'un attribut retourné dans une variable d'un autre formulaire. Ceci n'est possible qu'en mode 5 COPie. La valeur de copy est le nom de la variable de formulaire dans laquelle on veut copier la valeur retournée et le nom de l'attribut (doit être présent dans la liste du SELECT). Les deux champs de copy sont séparés par un caractère « : ».Par exemple pour renvoyer l’attribut « NUM » de la clause SELECT dans une variable de formulaire de nom "essai", on va avoir la valeur suivante de copy: top.fenetre.formulaire.essai.value=:NUM. 3. Description de l’application 3.1. Systèmes et structure de l’application La passerelle est actuellement implantée sur le serveur Apache Mica situé dans le laboratoire BD du département informatique. Afin de faire fonctionner une application de type Java Servlet nous devons utiliser un moteur de servlet. Pour des raisons de coup nous avons choisi le serveur d’application Tomcat qui est distribué de manière libre. De plus étant développé par les mêmes équipes que celle du serveur WEB APACHE, leur interconnection est censée être des plus aisée. Dans ce mode de fonctionnement le serveur Apache gère toutes les connections HTTP et envoie les requêtes relatives aux servlets à Tomcat. Il est possible de faire fonctionner le serveur d’application en « stand alone » mais la gestion des requêtes HTTP est moins bien faîte notamment lors de charges importantes. Voici un schéma donnant la structure de l’application : Requête HTTP Réception des paramètres HTTP -> analyse du mode Instanciation d'objets Java Stockage des paramètres dans une structure intermédiaire Traitement Oracle via JDBC Réponse HTTP Transformation XSL paramétrée du document XML en HTML Stockage des résultats dans une structure XML variable selon le mode Traitement XML via JAXP Java Servlet Figure 2: Structure de l’application Nous allons maintenant entrer dans les détails concernant l’organisation des données. L’ensemble des fichiers .java et .class sont situés dans le répertoire ‘/var/tomcat/Webapps/bdWeb/WEB_INF/classes/’. Les fichiers HTML que nous avons écrits pour tester la passerelle se situent dans le répertoire ‘/var/tomcat/Webapps/bdWeb/public_html/’. Ils sont tous visibles depuis l’extérieur. Par exemple, l’adresse http://mica.int-evry.fr:8080/bdWeb/public_html/hypertext.html permet de tester le mode HYP. On remarquera que c’est Tomcat et non pas Apache qui fait office de serveur WEB, d’où le port 8080 à spécifier. 6 Les fichiers XML temporaires sont créés dans le répertoire ‘/var/tomcat/Webapps/bdWeb/xml/’ puis supprimés. Ce répertoire est donc sensé être vide lorsque aucune requête n’est traitée. Néanmoins, durant le développement, il est possible d’empêcher la destruction du fichier résultat XML afin de déboguer. Les fichiers XSL qui définissent les critères de transformation du contenu XML vers le HTML sont situés dans le répertoire ‘/var/tomcat/Webapps/bdWeb/xsl/’. Pour l’instant, il n’existe qu’un seul fichier XSL par mode. 3.2. Code Java Nous avons développé la passerelle selon le modèle UML suivant : Figure 3: Modèle UML de l’ application La classe WebOracle gère les entrées-sorties au niveau Servlet. Elle prend en charge la récupération des paramètres et la transformation XSL finale. Les variables de classe xml_dir et xsl_dir contiennent les répertoires où sont stockés respectivement les fichiers XML et les fichiers XSL. La classe Mode est une classe abstraite dont le seul rôle est de factoriser la procédure de connexion à Oracle. La méthode abstraite genererXML est implémentée dans les classes Normal, Insertion, MiseAJour, QueryByExample, Hypertext et Copie qui héritent de la classe Mode. Ces classes 7 utilisent la classe DocumentXML pour créer et écrire dans le fichier XML qui contient le résultat. Chacune de ces sous-classes de Mode implémente de manière spécifique la récupération des résultats et leur mise en forme dans un contenu XML. Des méthodes privées sont parfois utilisées pour éviter d’avoir un code trop dense et pour factoriser des portions de code. 3.3. Modèle de données XML et les feuilles de style XSL Nous avons choisi l’api JAXP (Java Api for Xml Processing) pour parser et transformer les documents XML. Cette API utilise Xerces2 comme parseur de XML et Xalan comme moteur de XSLT par défaut. Cependant l’architecture modulaire of JAXP autorise l’utilisation d’autres implémentations de la norme XML. Nous avons utilisé un modèle de données différent pour chaque mode. Cela permet une simplification du code Java qui génère le fichier XML. Cependant les modèles sont tout de même très proches et généralement ce sont uniquement les attributs des tags qui changent. Les fichiers XML sont générés par la méthode genererXML et par conséquent chaque modèle est codé en dur dans la passerelle. En ce qui concerne les feuilles de style XSL elles sont spécifiques à chaque mode. Elles ont été défini grâce à la l’outil XmlSpy qui fonctionne sous windows. Pour des raisons de coups nous avons utilisé une version d’essai complète fonctionnant pendant 30 jours. Les feuilles de styles portent le nom de chaque mode. Ces feuilles de styles sont les feuilles de style par défaut c’est à dire qu’elle sont des plus basiques. Le résultat s’affiche de manière basique et pratique sous forme de tableaux. Il est cependant possible de les modifier très simplement pour obtenir un design plus évolué. 3.4. Méthode de développement La première étape a consisté à installer Tomcat. L’essentiel des difficultés rencontrées tournaient autour des droits liés à l’utilisateur et de l’initialisation des variables d’environnement nécessaires à l’exécution de Tomcat. Une fois ces problèmes résolus, la phase de développement à proprement dite a pu démarrer. Le développement de la passerelle s’est d’abord effectué sur Mica. En effet, nous avons cherché dans un premier temps à tester une application minimale afin de pouvoir tester proprement l’application réelle. Cette application minimale ne faisait que récupérer le résultat d’une requête simple et renvoyer directement une réponse HTML (sans passer par XML). Nous avons rencontré des difficultés avec la connexion à Oracle. En effet, 2 types de drivers sont disponibles pour communiquer avec un serveur Oracle : le driver de type 4 THIN qui est entièrement écrit en Java et le driver de type 2 OCI (Oracle Call Interface) qui est mi-java mi-natif (il fait appel à une librairie en C). Nous n’avons pour l’instant réussi à utiliser que le driver THIN avec une chaîne de connexion complexe de type @MICA :1521 :ENSE soit @serveur :port :instance. Du reste, l’application minimale a fonctionné sans problème majeur. Le développement s’est ensuite fait par étape, chaque mode étant testé l’un après l’autre. Le développement s’est partiellement fait à distance. En effet, Tomcat faisant office de serveur, Mica est accessible depuis l’extérieur de l’INT en passant par Python. La procédure est la suivante : telnet Python puis rlogin Mica et utilisation de l’éditeur VI si l’on est en mode texte (sous Windows sans émulateur par exemple) ou Xemacs si l’on travaille depuis Unix (en exportant le display). 8 4. TODOS Nous allons dresser une liste non exhaustive des évolutions à apporter à la passerelle. Cette liste reflète un ordre de priorité. Mettre en place l’interface Apache/Tomcat. Pour interfacer Tomcat à Apache, il semble qu’il faille lancer un module depuis Apache (à rajouter dans un fichier de config). Toutefois, nous n’avons pas réussi à faire fonctionner le tout. Rendre fonctionnelle l’interface OCI. Il semble que les variables d’environnement dont le driver a besoin doivent être initialisées par Tomcat. En effet, le driver ‘oci8’ est chargé dans la librairie (jdbc_oracle.jar située dans le répertoire /var/tomcat/lib/common/) par Tomcat. Les fichiers de configuration de Tomcat doivent donc être mis à jour. Mettre en place le système de nommage Java pour la gestion des UID avec des noms logiques. Le principe est d’appeler dans le code Java le service de nommage afin de préserver les informations sensibles transmises actuellement dans la variable uid. Utiliser le potentiel des Servlets pour faire du suivi de session. Le principe est d’attribuer à chaque utilisateur une clé de session pour laquelle une connexion avec Oracle est ouverte. Donc pas besoin de fermer la connexion pour en ouvrir une autre pour chaque requête de cet utilisateur. Un système de timer doit permettre de faire expirer la session lorsque l’utilisateur ne fait pas de requête pendant un temps limite (2 min par exemple). Ce type d’optimisation vise à améliorer les performances de la passerelle en cas de nombreuses requêtes (pour un TP par exemple). Ajouter les modes SUP (suppression) et MAJ (mise à jour). Ces modes sont très proches du mode INS et doivent être facilement implémentés en adaptant le code existant. Ecrire des feuilles XSL et permettre à l’utilisateur de choisir entre les différents styles avec la variable de formulaire ‘xslt’ (contient le nom du fichier XSL). L’intérêt est uniquement esthétique, c’est-à-dire améliorer la présentation du résultat pour chaque mode. Permettre la gestion des clés multiples en mode HYP. Pour l’instant, seule les clés primaires uniques sont identifiées à l’aide du dictionnaire de données Oracle. On pourrait étudier les solutions possibles pour identifier les clés primaires multiples. 9