F. Boyer, S. Chassande, D. Feliot, S. Krakowiak, D. Donsez
Projet de DESS-GI option SRR et RICM3 option SR
Année Universitaire 2001-2002
Université Joseph Fourier, Grenoble
PLAN 1.
Présentation de CORBA
1.1 Clients et serveurs
1.2 IDL
1.3 Talons et squelettes
2 Application bancaire
2.1 Architecture proposée
2.2 Interface IDL proposée
2.3 Organisation logicielle
proposée
3 Documentation des
services utilisés
URL des services utilisés
ORBacus : www.ooc.com
Site de l'OMG (donnant accès à la spécification IDL entres autres) : www.omg.org
Un serveur CORBA est un support permettant de rendre accessible un ensemble
d'objets (écrits dans un langage de programmation quelconque) de manière
distribuée. Nous allons utiliser ce support pour programmer une application
bancaire qui permet à des clients ou à des organismes distants de consulter, et
selon le cas de modifier des données bancaires (comptes, clients, agences, etc).
Cette note pésente tout d'abord les principes d'utilisation d'un serveur CORBA,
puis propose une architecture pour réaliser une application bancaire.
La norme CORBA à donné lieu à diverses implémentations, dont ORBacus
qui est celle que nous utiliserons dans le cadre de ce projet. Nous allons plus
précisément utiliser la version ORBacus 4, qui implémente la spécification
CORBA V2, incluant les Portable Objects Adaptors (POA).
CORBA est une norme proposée par l'OMG, pour permettre
d'interconnecter des composants logiciels (objets) écrits dans des
langages de programmation divers et s'exécutant sur des machines distantes.
Bien que permettant de réaliser des appels à distance sur
des objets, la norme CORBA est basée sur un modèle client/serveur.
Les objets distribués (c'est à dire, ceux que l'on souhaite rendre accessible à
distance) doivent être crées et gérés par un serveur CORBA, qui a pour rôle
d'exécuter les méthodes appelées par les clients sur ces objets.
N'importe quel client peut appeler une méthode sur un objet distribué, à partir
du moment où il connait la référence CORBA (appelée IOR, Inter Object
Reference) de cet objet. Cette référence précise à la fois quel est le serveur
"chez qui" se trouve l'objet, et quel est l'objet appelé. En général,
une IOR est transmise à un client soit par passage de paramètres, soit par
l'utilisation d'un serveur de noms.
La figure ci-après illustre un scénario de communication entre objets distribués sur des serveurs CORBA. En (1), un client récupère l'IOR d'un objet O dans le serveur X. En (2), le client accède à l'objet O. La méthode qu'il appelle sur O crée un deuxième objet O', dont l'IOR est renvoyée au client. Ce dernier peut alors ensuite accéder à O'.
Selon la norme CORBA, les objets que l'on souhaite rendre accessible de manière répartie doivent être décrits en termes de l'interface qu'ils offrent. Le développement d'applications distribuées sur des plates-formes hétérogènes nécessite en effet une séparation stricte entre les interfaces des objets et leur implémentation. Un langage spécifique, appelé IDL (Interface Definition Language) a été défini à cet effet par l'OMG (Object Management Group). Ce langage permet de définir les interface des méthodes appelables sur un objet distribué, en termes des types des paramètres et du résultat des méthodes.
Par exemple, nous allons considérer l'interface hello définie
ci-après qui permet d'afficher un message (méthode print), ainsi que de
comptabiliser le nombre d'appels effectués à la méthode print. Cette interface
est définie dans le module Example. Un module IDL définit une portée pour les
noms d'interfaces.
module Example { |
Exemple de fichier IDL ( example.idl )
Tout objet distribué possède deux représentations : une
représentation client (appelée talon) et une représentation serveur
(appelée squelette).
Un client possède un talon par objet distant qu'il est suceptible d'appeler. Un
talon associé à un objet O a pour rôle de transfèrer les appels de méthodes
effectués par le client au serveur gérant O.
De manière symétrique, un serveur possède un squelette par objet distribué
qu'il gère.Un squelette associé à un objet O réceptionne les appels de méthodes
sur O, et se charge d'engendrer leur exécution.
Au moment où un client effectue un appel de méthode sur un objet, l'interconnexion
entre le talon et le squelette de l'objet appelé est réalisée au travers d'une
couche de communication appelée Bus CORBA, ou plus généralement ORB
(Object Request Broker). Le protocole de transfert des appels de méthode
(définissant le format des messages échangés entre la machine cliente et la
machine serveur) est appelé IIOP (Internet InterOrb Protocol).
Remarque : l'OMG spécifie en fait un protocole de communication entre ORB appelé GIOP (General Inter-ORB Protocol). Ce protocole doit être implémenté au-dessus d'une couche transport orientée connexion. IIOP est une spécialisation de GIOP utilisant TCP/IP. La spécification de GIOP est constituée de deux parties. La première est générale ; elle spécifie une représentation commune des données (CDR), le format des messages GIOP et les caractéristiques supposées de la couche de transport sous-jacente. La seconde partie, propre à IIOP, décrit la manière dont clients et serveurs CORBA établissent des connexions TCP/IP pour transmettre des messages GIOP.
La génération des classes définissant les talons et les squelettes est prise en charge par le compilateur IDL. Cette génération s'effectue à partir de l'interface IDL décrivant un objet donné, ainsi que de l'implémentation de cet objet. Autrement dit, pour tout objet distribué, le programmeur doit décrire son interface IDL, et son implémentation dans un langage supporté par CORBA (C, C++, Java, etc).
La figure ci-après récapitule ces informations. On peut voir qu'un squelette est connecté au Bus CORBA via un adaptateur d'objets (Object Adapter). Initialement, la spécification Corba version1 proposait un adaptateur d'objets basique (Basic Object Adaptator), qui était limité en terme de portabilité. C'est la raison pour laquelle la norme Corba version 2.2 définit un nouvel adaptateur, appelé Portable Object Adaptor. Dans tous les cas, un adaptateur gère différents objets distribués dans un serveur Corba donné. C'est lui qui rend accessible ou inaccessible un objet donné, et qui invoque les méthodes appelées sur cet objet par l'intermédiaire de son squelette. Nous verrons le rôle plus précis des adaptateurs au travers de l'étape 3.
Figure 2. Interaction entre un client et un serveur CORBA
1.4 Notion d'activation
Lorsqu'un objet distribué est créé au sein d'un
serveur donné, il n'est pas immédiatement accessible à distance. Pour le rendre
accessible, il faut l'activer auprès de l'un des POA du serveur courant.
L'activation d'un objet distribué consiste en :
Deux modèles d'activation existent, selon que le POA
auprès duquel a lieu l'activation fonctionne selon le mode implicite ou
explicite. Avec le mode activation implicite, la création d'une
référence distribuée (ou d'un objectId) pour un objet O auprès d'un POA entraîne
automatiquement l'activation de O si celle-ci n'a pas encore été faite. Les
différents moyens de créer une référence distribuée sont résumés en 1.5.
Avec le mode activation explicite, le
programmeur doit explicitement activer un objet distribué auprès d'un POA. Les
méthodes fournies par la classe PortableServer.POA sont :
Dans la terminologie Corba, l'objet qui implante une interface IDL est appelé
un servant. Le type ObjectId correspont au
type byte[] de Java, et son contenu n'a pas de signification particulière pour
un POA. La contrainte à respecter est que deux objets distincts doivent
posséder des objectId différents s'ils sont actifs au sein du même POA. Un
exemple de génération d'objectId à partir d'une chaîne de caractères est donné
ci-après :
String anObjectId = "myObjectId";
byte[] id = anObjectId.getBytes();
1.5 Identification d'un objet distribué et accès à cet
objet
Pour accéder à un objet situé dans un serveur
distant, un client doit posséder une référence distribuée vers cet objet. Une
référence distribuée contient :
Une référence distribuée (type org.omg.Object) peut
être construite au travers des méthodes suivantes qui peuvent être appelées
autant de fois que nécessaire dans un programme. Si le POA auprès duquel est
appelé l'une de ces méthodes fonctionne selon le mode implicite, et que l'objet
n'a pas encore été activé, alors l'appel de la méthode provoque son activation.
Méthodes fournies par le servant (classe org.omg.Servant) :
// ces méthodes sont l'équivalent du connect de l'ORB Jonathan
Méthodes
fournies par le POA auprès duquel l'objet est (ou doit être) activé (classe org.omg.PortablePOA)
:
// ces methodes engendrent l'activation de l'objet si le mode du POA est implicite
Si l'on souhaite simplement connaître l'identificateur unique d'un objet sans forger une référence distribuée complète, alors la méthode suivante est disponible. Comme précédemment, si le POA auprès duquel est appelé cette méthodes fonctionne selon le mode implicite, et que l'objet n'a pas encore été activé, alors l'appel de la méthode provoque son activation.
Inversement, depuis une référence distribuée, il est
possible d'obtenir l'identification unique de l'objet (objectId), ainsi que la
référence Java locale de l'objet servant.
Méthodes fournies par le POA auprès duquel l'objet est activé (classe org.omg.PortablePOA) :
1.6 Exemple simplifié de serveur CORBA
Cette section décrit la mise en oeuvre d'un serveur Corba très simple, donnant
accès à un objet distribué implémentant l'interface IDL hello définie en 1.2. En 1.4.1, nous décrivons comment compiler l'interface
hello. Après la compilation des interfaces IDL d'une application, il est
nécessaire de définir les implémentations de ces interfaces. Il existe deux
modèles pour ce faire :
Selon le modèle de programmation, un servant peut
donc hériter de son squelette, ou bien utiliser un délégué pour
l'implémentation des méthodes. Les deux modèles sont décrits
respectivement en 1.4.2 et 1.4.3. Enfin, en 1.4.4 nous expliquons comment
écrire le programme du serveur qui va créer et héberger l'objet distribué, et
nous donnons un exemple de client qui accède cet objet à distance.
Nous supposons dans la suite que l'organisation logicielle est la suivante :
Example
/
/
\
\
idl
generated
src
build.xml
(fichiers
idl)
(fichiers générés)
(implémentations)
1.6.1 Compilation des interfaces IDL selon le modèle par héritage
Pour compiler cette interface, nous utilisons le compilateur IDL/Java (au
travers de la commande jidl Example.idl) qui va générer les classes
talon et squelette Java associées à l'interface hello. Toutes les
classes générées appartiennent au package Example (nom du module). Ces
classes sont les suivantes :
1.6.2 Ecriture d'une implémentation selon le modèle par héritage
Nous devons définir la classe helloImpl.java comme une extension de la classe helloPOA. Dans
cette application très simple, la classe ExampleServer.java crée une instance de la classe helloImpl, puis crée une
référence distribuée sur cet objet (méthode _this(orb)), et enfin enregistre
cette référence auprès du serveur de noms. La méthode _this crée une
référence distribuée en activant l'objet auprès du POA affecté par défaut au
serveur courant. Ce POA (appelé RootPOA) fonctionne en effet selon le mode
d'activation implicite. La classe ExampleClient.java donne un exemple de client.
Dans le modèle par héritage, le servant d'un objet
distribué d'interface XXX a pour classe XXXImpl qui étend XXXPOA. Cet objet met
en oeuvre à la fois l'implémentation et le squelette de l'objet.
1.6.3 Compilation des interfaces IDL selon le modèle par délégation
Pour compiler l'interface Example.idl selon le modèle par délégation, nous
utilisons le compilateur IDL/Java avec l'option -tie (au travers de la
commande jidl -tie Example.idl). Les classes générées comportent
un fichier supplémentaire par rapport à une compilation selon le modèle par
héritage : helloPOATie.java. Cette classe
implémente le squelette associé aux objets d'interface hello. Ce squelette, qui
doit être considéré comme servant, utilise un objet de classe helloImpl
comme délégué.
Note : l'option de compilation --impl permet d'obtenir des squelettes
des classes d'implémentation.
1.6.4 Ecriture d'une implémentation selon le modèle par délégation
Nous devons cette fois définir la classe helloImpl.java comme une implémentation de l'interface helloOperations.
Dans la classe ExampleServer.java, il faut d'abord
instancier la classe helloImpl, puis créer un servant en instanciant la
classe helloPOATie et en lui passant, comme paramètre de construction,
une référence vers la classe d'implémentation.
helloImpl hello = new
helloImpl();
helloPOATie helloTie = new
helloPOATie(hello);
L'activation de l'objet crée peut être réalisée par
son créateur (classe ExampleServer), ou bien par lui-même, selon les
choix de programmation que l'on réalise. Dans le premier cas, le créateur n'a
qu'à appeler la méthode activate_object(helloTie) sur le POA choisi.
Dans le second cas, c'est dans la classe helloImpl que l'on souhaite
effectuer cette activation. La classe ExampleClient.java donne un exemple de client.
1.6.5 Lancement de l'application
Pour exécuter l'application, il
faut effectuer les commandes suivantes qui vous sont fournies dans le fichier
ant build.xml:
java -cp <classpath> com.ooc.CosNaming.Server --ior > Naming.ref &
java -cp <classpath> Example.ExampleServer -OAport 2200 -ORBnaming `cat
Naming.ref` &
java -cp <classpath> Example.ExampleClient -OAport 2000 -ORBnaming `cat
Naming.ref` &
Cette section propose une architecture pour la réalisation de l'application bancaire en termes de serveurs CORBA. Bien entendu, il est tout à fait possible d'étendre ou de modifier cette architecture.
Nous proposons qu'une application bancaire soit mise en oeuvre par trois types de serveurs CORBA :
Le schéma ci-dessous montre l'enchaînement des opérations pour obtenir la
référence d'une agence.
Cette dernière opération crée automatiquement un talon correspondant à un objet
Agency sur le site client. Ce dernier peut donc par la suite appeler les
méthodes de l'interface Agency sur l'objet correspondant.
Les banques doivent fournir un ensemble de services spécifiés par des interfaces IDL. Nous proposons les interfaces IDL suivantes (fichier bankServices.idl, sous ${GICOM}/Java/Bank), qui peuvent bien entendu être modifiées et/ou complétées par vos soins. L'accès initial à une banque étant donné son nom sera réalisé au travers du serveur de noms fourni par ORBacus.
Les méthodes registerAgency et removeAgency permettent respectivement d'enregistrer et de retirer une agence d'une banque donnée. La référence d'une agence rattachée à une banque peut être récupérée par la méthode getAgency. La méthode getAgenciesList permet de récupérer les références de toutes les agences rattachées à une banque donnée.
A partir d'un objet Agence, on doit pouvoir enregistrer ou retirer des clients, et récupérer leur référence distribuée. Les objets Clients sont donc également accessibles au travers d'une interface IDL.
A partir d'un objet Client, on peut récupérer des informations (nom, adresse, etc) sur le client, et l'on peut également créer, consulter ou détruire des comptes pour ce client, ainsi que récupérer leur référence.
Les objets Account devront principalement permettre de consulter ou de modifier un solde.
L'organisation logicielle recommendée pour conserver une structuration claire des programmes ainsi que des talons et des squelettes générés lors de la compilation des interfaces IDL est la suivante.
GICOM
|
Java
|
Bank /
/
|
\
\
\ bankServices.idl
bankServices classes
src
applet
Naming.ref
URL Java: http://java.sun.com/products/jdk/1.2/docs/api/index.html
URL ORBacus 3.0 (Société : Oriented Object Concepts (USA))
: www.ooc.com
Votre environnement doit être configuré comme suit (cf. fichier CONFIGENV):
- accès aux binaires du jdk1.2
(/usr/Solaris_JDK_1.2.1_03/bin sur les Tx)
- accès aux binaires d'ORBacus
(${GICOM_ENS}/ORBacus/bin sur les Tx)
OB.jar,OBBiDir.jar,OBEvent.jar,OBIMR.jar,OBNaming.jar,
OBProperty.jar,OBTest.jar,OBTime.jar,OBTrading.jar,OBUtil.jar
L'appletviewer se trouve dans ${JAVA_HOME}/bin. Le lancer par la commande appletviewer.
ORBacus for C++ and Java (Mark Laukien, Uwe Seimet, Matthew
Newhook, Mark Spruiell)
Manuels de référence de l'ORB développé par Object Oriented Concepts.
Au coeur de Corba (Jérôme Daniel), Editions Vuibert, Paris, 2000.
Contact : informatique@vuibert.fr
www.omg.org (Site de l'OMG)
www.objectweb.org (Un ORB Java fourni en Open Source)
www.inf.fu-berlin.de/~brose/jacorb (Jacorb est un ORB écrit en Java)
www.cs.wustl.edu/~schmidt/ (L'ORB TAO est disponible sur ce site)