TP: `CORBA'

$Id: index.html,v 1.9 2009/10/19 07:59:01 pautet Exp $

Laurent Pautet (pautet.fr)

avec l'aide de A. Diaconscu, J. Hugues, F. Singhoff, B. Dupouy, Th. Vergnaud et B. Zalila.

Index

1 TP CORBA Java

1.1 Introduction

Vous trouverez un livre complet sur CORBA à l'URL suivante: http://ciaranmchale.com/download/corba-explained-simply.pdf.

L'objectif de ces exercices est la mise en pratique des concepts abordés lors du cours d'introduction à CORBA. Ce TP est composé de quatre exercices en Java.

Le premier est un exemple complet d'un client/serveur CORBA utilisant une interface IDL simple. Cet exercice utilise les outils de base nécessaires à la réalisation d'une application CORBA élémentaire et présente les principales règles de la projection IDL vers Java.

Dans le deuxième exercice, on vous demande de compléter l'exemple précédent avec de nouvelles méthodes.

Enfin, le troisième exercice illustre le fonctionnement d'une usine à objets; et le quatrième illustre l'utilisation de types complexes au travers de CORBA.

Note: il est conseillé d'étudier les deux premiers exercices de ce tutoriel avant d'effectuer le TP.

Les sources du tutoriel: src.tar.gz.

Nous faisons maintenant l'hypothèse que vous utilisez zsh et que vous avez récupéré les sources des exercices, puis, utilisé la commande

     gunzip src.tar.gz
     tar xf src.tar

pour les extraire de l'archive dans votre répertoire de TP CORBA. Pour utiliser l'environnement de développement pour CORBA JacORB, il suffit d'utiliser la commande :

     PATH=/usr/local/packages/jacorb/bin:$PATH

dans toutes les fenêtres où vous exécuterez des processus utilisant CORBA.

1.2 Une Calculatrice

L'ORB Java que nous allons utiliser, JacORB, est distribué sous licence LGPL. Cet ORB est conforme au standard CORBA 2.3. Il implante de nombreuses fonctionnalités de la norme, visibles à l'adresse suivante http://www.jacorb.org/.

Chaque exercice dispose d'un fichier Makefile, taper make pour le compiler.

Pour lancer le code d'un exercice, exécuter:

     jaco tpcorba.Client <argument>

pour lancer le client et

     jaco tpcorba.Serveur <argument>

pour lancer le serveur.

Les sources de cet exercice se trouvent dans le répertoire EXO1.

Ce premier exercice consiste en un exemple simple d'application client/serveur CORBA. Il s'agit d'une calculatrice disposant de plusieurs fonctions simples. Le serveur exporte plusieurs méthodes définies dans l'interface IDL calcul (fichier tpcorba.idl). Dans cet exercice, vous devez compiler et exécuter l'application. Pour ce faire, il faut :

On vous demande d'observer par quelles étapes passent le serveur et le client pour initialiser l'objet CORBA, et pour invoquer les méthodes de l'objet. Vous regarderez plus précisément les points suivants :

  1. Quelles sont les interactions entre le serveur et le POA ?
  2. Quelle est la relation entre la classe d'implantation (classe calcul_Impl.java) et le squelette (le squelette est défini par la classe calculPOA.java dans le répertoire tpcorba) ?
  3. Dans la souche (classe _calculStub.java), où se trouvent la construction et l'émission de la requête vers le serveur ? Comment le client obtient il la souche pour invoquer l'objet (voir la méthode narrow dans la classe calculHelper.java) ?
  4. Chercher dans le squelette (classe calculPOA.java) où se situent les appels à l'implantation de l'objet (classe calcul_Impl.java).
  5. Enfin, identifier dans le fichier calcul.ref (fichier qui contient la référence d'objet) l'adresse IP où se trouve le serveur et le port TCP utilisé pour les interactions entre les clients et le serveur. Vous utiliserez à cet effet la commande :
              dior -f calcul.ref
    

    qui affiche à l'écran le contenu de la référence d'objet.

Voici un rappel des principales règles de la projection IDL/Java nécessaires pour mener à bien ce TP. La projection (mapping) complète est accessible à l'URL http://www.omg.org/technology/documents/spec_catalog.htm.

  1. Ajoutez au fichier IDL les constructions suivantes
                  void ajouteMemoire(in double data);
                  void soustraitMemoire(in double data);
                  void multiplieMemoire(in double data);
                  void miseAZero();
                  void diviseMemoire(in double data) raises (divisionParZero);
    
  2. Que se passe-t-il lors de la compilation ?
  3. Compléter le code et tester les nouvelles méthodes à l'aide du client Java.

1.3 Une Usine De Calculatrices

Les sources de cet exercice se trouvent dans le répertoire EXO2.

Dans les exercices précédents, une seule instance de la calculatrice est présente; de ce fait tous les clients partagent la même zone mémoire où sont stockés les résultats intermédiaires.

Une solution possible à ce problème est d'utiliser plusieurs instances de l'interface calcul.

Pour ce faire, nous allons définir une usine à objets. Une usine à objets offre des services permettant de créer et gérer dynamiquement des objets CORBA. Nous allons donc offrir aux clients la possibilité de créer et détruire dynamiquement des objets calcul et éventuellement de se partager un même objet.

Le serveur doit maintenant gérer un ensemble de calculatrices. Pour chaque calculatrice, il maintient une référence sur l'objet CORBA, un identifiant (un nom sous la forme d'une chaîne de caractères utilisé par les clients pour désigner une calculatrice particulière) ainsi qu'un nombre d'utilisateurs (nombre de clients qui manipulent la calculatrice).

Un tableau interne à l'instance de usine stocke ces différentes informations et permet de retrouver les informations sur les calculatrices créées.

Dans cet exercice, il vous est demandé de :

  1. Modifiez le fichier tpcorba.idl en rédigeant pour l'interface usine les quatre méthodes décrites ci-dessous (n'oubliez pas de déclarer les exceptions utilisées par chaque méthode) :
  2. Complétez l'implantation de l'interface usine (c'est à dire le fichier usine_impl.java).
  3. Testez cette nouvelle interface avec le client.

Les méthodes que vous devez ajouter au fichier tpcorba.idl sont :

  1. La méthode creation qui prend :

    Cette méthode doit créer une nouvelle instance de la classe calcul_impl, puis l'enregistrer auprès du POA à l'aide de la méthode servant_to_reference du POA. Cette méthode enregistre l'objet auprès du POA, et retourne un objet de type CORBA.Object qu'il vous faudra ensuite transtyper en type calcul correspondant à l'objet à stocker (méthode narrow).

    Enfin, elle doit renvoyer au client une référence sur le nouvel objet CORBA créé (rappel : le mot-clé interface est un constructeur de type, “calcul” est donc un type IDL).

    La méthode doit lever :

  2. La méthode suppression qui prend un paramètre en in de type string désignant le nom de la calculatrice à détruire. L'objet CORBA pourra être désactivé simplement en mettant à null la référence de l'objet dans l'usine.

    La méthode doit lever :

  3. La méthode connecter qui prend :

    Cette méthode doit incrémenter le nombre d'utilisateurs associés à une calculatrice. Par contre, elle ne crée pas d'objet CORBA : elle permet d'avertir l'usine à objets qu'un client souhaite utiliser une calculatrice déjà existante. Elle doit renvoyer au client une référence sur l'objet CORBA concerné. La méthode doit lever une exception si le paramètre string adresse une calculatrice inexistante (exception calculatriceInconnue).

  4. La méthode deconnecter qui prend un paramètre en in de type string désignant le nom de la calculatrice concernée. Cette méthode “déconnecte” un utilisateur d'une calculatrice. Elle permet d'avertir l'usine à objets que le client ne souhaite plus utiliser la calculatrice.

    La méthode doit lever :

1.4 Utilisation Du Service De Nommage

Les exercices précédents ont utilisé un fichier pour transférer la référence du serveur vers le client. Une hypothèse importante était que ces deux programmes utilisent un système de fichiers commun, et qu'une unique référence soit transmise dans ce fichier.

Ces contraintes fortes sont difficilement compatibles avec les besoins liés au déploiement d'applications sur des noeuds distants qui peuvent avoir besoin de “retrouver” de nombreux objets.

De manière à lever cette limite, client et serveur peuvent utiliser un noeud intermédiaire, implantant les interfaces définies par le service de nommage normalisé de CORBA, le COS Naming.

Nous allons utiliser le service de nommage de JacORB, ns, et le configurer de manière à permettre au client et au serveur de l'utiliser.

Le service de nommage est un référentiel commun à plusieurs noeuds de l'application répartie qui permet d'associer un nom logique (un chaîne de caractères) à une référence sur un objet distant.

Le service de nommage fonctionne comme un objet corba classique, il faut dans un premier temps passer à chaque noeud une référence sur une instance de ce service, NamingContext. On peut ensuite accéder à ses méthodes pour enregistrer ou retrouver des objets applicatifs.

ns configure une instance de NamingContext. Un problème qui peut se poser lors de l'utilisation de ce service est celui de la référence initiale. Il faut disposer d'au moins une référence, celle du NamingContext pour qu'ensuite les noeuds de l'application puisse échanger leurs références.

ns permet de configurer la manière de publier cette référence: HTTP, fichier, etc.

Nous nous intéresserons ici à l'utilisation d'un système de fichier pour échanger cette référence. Passer à HTTP se fait en reconfigurant simplement ns et sort du cadre de ce TP.

Pour indiquer à ns dans quel fichier il doit stocker sa référence, il convient de faire :

     $ ns -Djacorb.naming.ior_filename=./ns.ref &

Dans ce cas, la référence du serveur de noms se trouve stockée dans le fichier ns.ref du répertoire local.

Il reste alors à lancer le serveur et le client en leur indiquant dans quel fichier se trouve la référence au serveur de noms.

Serveur :

     $ jaco -DORBInitRef.NameService=file://./ns.ref tpcorba.Serveur

Client :

     $ jaco -DORBInitRef.NameService=file://./ns.ref tpcorba.Client

La commande lsns vous permet de vérifier les références stockées dans le service comme suit:

     $ lsns -ORBInitRef.NameService=file://./ns.ref
        calculatrice
  1. Adapter le code source de Une Calculatrice pour utiliser le serveur de nommage de JacORB. Il faudra en particulier que

    L'API du serveur de nom est définie dans ce JavaDoc: http://java.sun.com/j2se/1.4.2/docs/api/, classe org.omg.CosNaming.

    Note: il vous faudra modifier l'interface de usine pour lui passer toutes les données que vous jugerez utiles; vous supprimerez le code devenu inutile.

1.5 Tous Les Types

Dans cet exercice, on s'intéresse plus en détail à la projection de certains types de données IDL vers Java.

On considère le module IDL suivant :

     module test_types {
       interface some_types {
     
         // enumerations
         enum Color { Red, Green, Blue };
         Color echoColor (in Color arg);
     
         // union
         union myUnion switch (long) {
         case 1: long    Counter;
         case 2: boolean Flag;
         case 3: Color   Hue;
         default: long Unknown;
         };
     
         myUnion echoUnion (in myUnion arg);
     
         // array
         typedef long simple_array[5];
         simple_array echoArray (in simple_array arg);
     
         // struct
         struct simple_struct {
           long a;
           string s;
         };
         simple_struct echoStruct (in simple_struct arg);
     
         // sequence
         typedef sequence<short> U_sequence;
         U_sequence echoUsequence (in U_sequence arg);
     
       };
     };

Il permet de tester certains types complexes de CORBA. Les

  1. En vous basant sur les serveurs et clients écrit précédemment, proposez une implantation de cette spécification Java.