corba - LaBRI

publicité
Xavier Blanc
[email protected]
L'environnement
C.O.R.B.A.
utilisation avec Java
1
Plan de la présentation
• Aperçu de C.O.R.B.A.
• Une première application avec C.O.R.B.A.
• Des applications plus conséquentes…
• Service de désignation
• Etude du type « Any »
• Les mécanismes dynamiques de C.O.R.B.A.
• Synthèse sur C.O.R.B.A.
2
Aperçu de C.O.R.B.A.
3
Qu'est ce que l'O.M.G. ?
• O.M.G. ( Object Management Group ) est un consortium qui
regroupe plus 800 entreprises du monde entier.
– Consortium ouvert aux horizons autres que les concepteurs de logiciels
( industriels, chercheurs, université, etc... ).
• Ce consortium définit des spécifications pour fournir un modèle de
coopération entre objets répartis.
4
Fonctionnement de l'OMG
• Plusieurs niveaux de souscriptions existent :
– contributing, domain contributing, influencing, auditing, university.
• Principe de création des spécifications
– request for information, request for proposal.
• Principe d'approbation des spécifications
– Task Force,
– Technical Comitee
– Architecture Board
5
Les spécifications de l'O.M.G.
• L'OMG spécifie tous les constituants d'un modèle objet global
appelé O.M.A. ( Object Model Architecture )
OMA
MDA
– CORBA est une partie de ce modèle,
– Utilitaires communs ( services ),
– Eléments spécifiques à des corps de métier ( objets de domaines ).
6
Qu'est ce que C.O.R.B.A. ?
• CORBA ( Common Object Request Broker Architecture ) est un
environnement réparti (middleware).
• Défini par l'OMG :
– première spécification : 1991
– seconde version majeure : 1995
– troisième version majeure : 2002
Version courante ( Septembre 2002) : 3.0
7
Objectifs de CORBA
• Fournir un environnement ouvert
– les membres participent aux spécifications
• Fournir un environnement portable
– les API sont définis pour rendre les applications portables ( quelque
soit le produit CORBA utilisé )
• Fournir un environnement interopérable
– Permettre aux applications CORBA de collaborer entre elles.
8
Le bus CORBA
Le bus CORBA = ORB
9
NT
UNIX
UNIX
PC
PC
Sparc
La vue réelle du bus CORBA
ORB
PC/NT
ORB
PC/UNIX
ORB
Sparc/UNIX
NT
UNIX
UNIX
PC
PC
Sparc
Réseau TCP/IP
10
Serveur et objets
• Un serveur CORBA peut héberger plusieurs objets CORBA.
• Chaque objet est accessible indépendamment des autres objets du
serveur.
• Chaque objet exprime son offre de services. Pour cela, on utiliser un
langage de description de services appelé IDL CORBA.
11
Le langage IDL CORBA
• Il s'agit de décrire au sein d'une interface ( vue cliente de l'objet )
la liste des services offerts ( ensemble de fonctions ).
interface Horloge
{
string donne_heure_a_paris();
string donne_heure_a_pekin();
};
12
La compilation IDL
• Une description IDL est compilée pour générer les amorces
nécessaires au mécanisme RPC.
souche
description
IDL
squelette
13
Intervention des amorces
C.O.R.B.A.
Client Java
Objet C++
Souche Java
Squelette C++
ORB Java
PC/NT
ORB
PC/UNIX
ORB C++
Sparc/UNIX
NT
UNIX
UNIX
PC
PC
Sparc
Protocole IIOP
14
Souche : Coté client
• Fonctions de la souche :
– Prépare les paramètres d’entrée de
l’invocation
– Décode les paramètres de sortie et le résultat
• Souche statique
– Une par type d’objet serveur à invoquer
– Identique aux talons clients RPC
– Générée à la compilation à partir de l’interface IDL
• Souche dynamique
15
– Souche générique construisant dynamiquement tout
type de requêtes
– Permet d’invoquer des objets serveurs que l’on
découvre à l’exécution (i.e. dont on ne connaît pas
l’interface à la compilation : Référentiel d’interfaces)
Squelette : Côté serveur
• Fonctions du squelette :
– décode les paramètres d’entrée des invocations
– prépare les paramètres de sortie et le résultat
• Squelette statique
– un par type d’objet serveur invoquable
– identique aux talons serveurs RPC
– généré à la compilation à partir de l’interface IDL
• Squelette dynamique
– squelette générique prenant en compte dynamiquement tout
type de requêtes
– permet de créer à l’exécution des classes d’objets serveurs (i.e.
que l’on ne connaissait pas à la compilation)
16
L'identité d'un objet C.O.R.B.A.
• Chaque objet C.O.R.B.A. est associé à une référence
d'objet qui forme son identité.
• Deux objets C.O.R.B.A. du même type ( exemple deux
objets Horloge ) ont deux identités différentes.
Les références d'objets sont
le moyen d'accès à un objet.
serveur
17
L'adaptateur d'objets
Serveur
Objet A
Objet B
Squelette A
Squelette B
Client
Souche A
Adaptateur d'objets
Le bus C.O.R.B.A. ( O.R.B. )
18
L'adaptateur d'objets
• Fonctions
– Interface entre les objets CORBA et l’ORB
– Enregistrement et recherche des implantations
d’objets
– Génération de références pour les objets
– Gestion de l’instanciation des objets serveurs
– Activation des processus dans le serveur
– Aiguillage des invocations de méthodes vers les
objets serveurs
• Différents type d’adaptateur
– BOA (Basic Object Adapter)
– POA (Portable Object Adapter)
19
Les communications avec CORBA
• Les participants à un échange CORBA communiquent à l'aide d'un
protocole spécifique à CORBA : IIOP ( Internet Inter-ORB
Protocol ).
• Le protocole IIOP est indépendant du langage de programmation,
du système d'exploitation et de la machine utilisée.
Un client Java pourra utiliser un serveur C++
20
Normalisation des communications
• Protocoles d’interopérabilité entre ORBs
conformes à CORBA 2
– GIOP : General Inter-ORB Protocol
• Messages : request, reply, cancelrequest, …
• nécessite un protocole de transport fiable, orienté connexion
– IIOP (Internet IOP) : instanciation de GIOP sur TCP
• Autres implantations de GIOP au-dessus de HTTP, RPC
DCE, RPC Sun
• Composants du protocole
– CDR : Common Data Representation
• Format de données d’encodage des données
21
– IOR : Interoperable Object References (références
d’objets)
Les services C.O.R.B.A.
• Pour accélérer et faciliter le développement d'applications avec
C.O.R.B.A., l'O.M.G a spécifiée un ensemble de services.
• A l'heure actuelle, plus de 17 services ont été définis.
• Les services sont vendus séparément du bus CORBA.
• Seul quelques services sont actuellement disponibles sur le marché.
22
L'annuaire C.O.R.B.A.
• L'annuaire C.O.R.B.A. est un service.
• Il s'agit d'un serveur qui enregistre des associations nom / référence
d'objet.
• Un serveur peut enregistrer ses objets dans l'annuaire.
• Un client peut récupérer l'accès à un objet en consultant l'annuaire.
23
Vue du modèle O.M.A.
Services
Annuaire
Transaction
Objets de domaines
Médecine
Electronique
Le bus C.O.R.B.A.
Client
Serveur
Applications utilisateurs
24
Administration
Impression
Utilitaires communs
Une première application
avec C.O.R.B.A.
25
Opérations à réaliser
1. Décrire les services offerts des objets CORBA
2. Développer les objets CORBA
3. Développer le serveur
4. Développer le client
26
Décrire les services offerts
• Le développement d'une application CORBA commence par
l'énumération des services offerts par chaque objet corba.
• Une même description IDL peut contenir plusieurs descriptions
d'objets.
• Une description IDL s'effectue au sein d'un fichier texte comportant
par convention l'extension « .idl »
• Chaque objet offre une interface qui contient une liste d'opérations
qui seront par la suite offertes aux applications clientes.
27
Premières règles sur l'IDL
• Une interface est une énumération d'opérations et de
définitions de types de données.
Pas de majuscule
interface Exemple
{
// contenu de l'interface
};
Se termine par un point virgule
• Une interface supporte l'héritage multiple.
28
interface AutreExemple : Exemple1, Exemple2
{
// contenu de l'interface
};
Décrire une opération
• Les opérations décrites dans une interface respectent le
format suivant :
type_de_retour nom_de_l'operation ( liste_des_paramètres ) ;
C.O.R.B.A. offre plusieurs types de données :
- les types de bases
- les types complexes
La liste des paramètres peut
être vide.
29
Les types de bases
• Les types de bases de CORBA sont :
–
–
–
–
–
–
–
–
–
–
–
boolean
octet
short ( ushort )
long ( ulong )
longlong ( ulonglong )
float
double
long double
char
wchar
string
– wstring
30
Les paramètres d'une opération
• La description d'un paramètre comporte trois parties :
– le modificateur
– le type de l'argument ( type de base ou type complexe )
– le nom de l'argument
• Le modificateur spécifie le sens d'échange du paramètre :
– in : du client vers l'objet CORBA
– out : en retour, de l'objet CORBA le client
– inout : équivalent à un passage par adresse.
31
Un exemple de description IDL
• L'exemple suivant décrit un objet qui offre une interface appelée
« Premier ». Cette interface comporte une opération dénommée
« affiche » qui entraîne l'affichage d'un message sur le serveur
( message passé en tant que paramètre ).
interface Premier
{
void affiche ( in string message ) ;
};
32
Compilation d'une description IDL
• La description doit être compilée afin de générer les amorces
( souche et squelette ) requises pour l'établissement de la
communication inter-processus.
• Exemple de compilation IDL :
idlj –fall –v Premier.idl
• A l'issu de la compilation, plusieurs fichier sont créés :
– PremierPOA.java : il s'agit du squelette,
– _PremierStub.java : il s'agit de la souche,
– Premier.java : il s'agit de l'interface
– PremierOperations.java : il s'agit des opérations de l'interface
33
Concept de « mapping »
• Une description IDL est traduite vers un langage de
programmation.
• Les règles de traduction sont appelées « mapping » et font partie de
la spécification CORBA.
• Grâce au mapping, deux fournisseurs d'ORBs offriront le même
modèle de programmation.
portabilité des applications
34
Correspondance des types de bases
35
IDL
boolean
octet
short
ushort
long
ulong
long long
ulong long
Java
boolean
byte
short
int
long
IDL
float
double
Java
float
double
IDL
string
wstring
Java
string
string
long double
char
wchar
char
char
Développer les objets CORBA
• Pour développer un objet CORBA plusieurs critères sont à prendre
à compte :
– le type de l'adaptateur d'objet utilisé,
– l'approche de développement.
• Deux adaptateurs d'objets sont disponibles :
– le B.O.A. ( Basic Object Adapter )
– le P.O.A. ( Portable Object Adapter )
• Deux approches existent :
– l'approche par héritage : ici l'implantation de l'objet doit hériter du
squelette ( c'est à dire de la classe Java correspondant au squelette qui à
été générée par le compilateur ).
– l'approche par délégation (prochaine partie).
36
L’approche par héritage
API de CORBA
org.omg.PortableServer.Servant
PremierPOA
Implantation
de l'objet
37
PremierOperations
A développer par le programmeur
Généré à
partir de l'IDL
Développement de notre
premier objet CORBA
public class PremierImpl extends PremierPOA
{
public void affiche( String message )
{
L'implantation hérite
du squelette.
System.out.println( message );
}
}
!
38
La seule obligation est de ne pas oublier l'héritage du squelette.
Ensuite, il faut tout simplement fournir le code des opérations
décrites dans l'interface IDL.
Développer le serveur
• Les étapes à respecter sont les suivantes :
– initialiser l'ORB
– initialiser l'adaptateur d'objets
– créer l'objet CORBA
– enregistrer l'objet CORBA
– exporter la référence de l'objet CORBA
– attendre les invocations clientes
39
Initialiser l'ORB
• Pour cela, on fait appel à la fonction statique « init » de la classe
« org.omg.CORBA.ORB ».
• Deux formes de cette fonction sont disponibles :
– org.omg.CORBA.ORB.init( )
– org.omg.CORBA.ORB.init( String [] args, java.util.Properties prop )
public static void main( String [ ] args )
{
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init( args, null );
// …
}
40
Initialiser l'adaptateur d'objets
• Une application serveur contient au minimum un POA
(elle peut en avoir plusieurs) appelé le RootPOA
• Le(s) POA(s) sont gérés par le POA Manager
• Une application serveur doit
– Récupérer une référence d’objet RootPOA
POA rootpoa =
POAHelper.narrow(orb.resolve_initial_refer
ences
(«RootPOA»));
et
– Activer le POA Manager
rootpoa.the_POAManager().activate();
41
POAManager & POA
SERVEUR
Requêtes
client
ORB
(orb)
POAManager
Servant
Servant
POA
POA
POA*
Servant
Servant
Servant
Servant
Servant
Servant
*RootPOA
(rootpoa)
42
Créer et enregistrer l'objet CORBA
• Pour créer l'objet CORBA, il suffit de créer une instance de la
classe d'implantation de l'objet ( PremierImpl ). Dans la
terminologie POA, cet objet s’appelle un servant
PremierImpl premier = new PremierImpl();
• Enregistrer un servant revient à lui associer une référence :
org.omg.CORBA.Object ref = rootpoa.servant_to_reference(premier );
43
Echanger une référence d'objet
• Chaque objet CORBA dispose d'une identité ( la référence d'objet ).
• Pour qu'un client puisse appeler un objet CORBA, celui-ci doit en
connaître la référence de l'objet.
– C'est pourquoi l'objet CORBA doit échanger avec le client sa référence
d'objet.
• Pour cela, on utilise deux opérations particulières de la classe
« org.omg.CORBA.ORB » :
– object_to_string : cette opération transforme une référence d'objet en
une chaîne de caractères.
– string_to_object : cette opération transforme une chaîne de caractères
en une référence d'objet.
44
Le code du serveur
import org.omg.CORBA.ORB;
import org.omg.PortableServer.*;
public class Serveur
{
public static void main( String [] args )
{
try {
ORB orb = ORB.init( args, null );
POA rootpoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
rootpoa.the_POAManager().activate();
PremierImpl premier = new PremierImpl();
org.omg.CORBA.Object objref = rootpoa.servant_to_reference(premier);
String ref = orb.object_to_string( objref );
java.io.FileOutputStream file = new java.io.FileOutputStream("ObjectID");
java.io.PrintStream output = new java.io.PrintStream( file );
output.println( ref );
output.close();
orb.run();
} catch ( Exception ex )
{ ex.printStackTrace(); }
}
45
}
Développer le client
• Les étapes à suivre sont les suivantes :
– Initialiser l'ORB,
– Récupérer la référence de l'objet à utiliser,
– Convertir la référence vers le type de l'objet à utiliser,
– Utiliser l'objet.
46
Conversion de références d'objets
object_to_string
org.omg.CORBA.Object
Premier
string_to_object
Conversion
47
org.omg.CORBA.Object
La conversion consiste à utiliser une fonction spécifique
appelée « narrow ».
Les classes helpers
• Pour chaque élément décrit en IDL, le compilateur génère une
classe supplémentaire appelée classe helper.
• Cette classe porte le nom de l'élément IDL avec pour suffixe
"Helper".
• Les classes helpers associées aux interfaces IDL comportent une
opération de conversion ( narrow ).
public class PremierHelper
{
public static Premier narrow( org.omg.CORBA.Object obj ) { //… }
//...
}
48
Le code du client
49
public class Client
{
public static void main( String [ ] args )
{
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init( args, null );
try {
java.io.FileInputStream file = new java.io.FileInputStream("ObjectID");
java.io.InputStreamReader input = new java.io.InputStreamReader( file );
java.io.BufferedReader reader = new java.io.BufferedReader(input);
String ref = reader.readLine();
file.close();
org.omg.CORBA.Object obj = orb.string_to_object(ref) ;
Premier premier = PremierHelper.narrow( obj );
premier.affiche("Bonjour du client…");
} catch ( java.lang.Exception ex )
{ ex.printStackTrace(); }
}
}
Exécuter l'application
• Suivre les étapes suivantes :
– lancer le serveur,
– copier le fichier contenant la référence d'objet sur le poste
client,
– lancer le client.
50
Synthèse
• Le développement d'une application CORBA respecte
toujours les même étapes.
– Description des objets à l'aide de l'IDL,
– Implantation des divers objets,
– Implantation du serveur avec échanges des références,
– Implantation du client.
51
Exercice
• Développez une application CORBA qui offre deux objets :
– l'objet Banque qui créer des comptes,
– et l'objet Compte qui gère diverses informations ( titulaire, solde ).
• Le client pourra créer de nouveaux comptes et manipuler chaque
compte pour y effectuer des crédits et débits.
• Les étapes sont :
– définir la description IDL des objets Banque et Compte,
– Développer les implantations de ces objets,
– Développer le serveur puis le client.
52
Des applications plus
conséquentes...
53
Gestion des exceptions
• Si une erreur se produit lors du traitement dans l'objet C.O.R.B.A. il
est possible de faire remonter une exception du côté client.
• Cette exception sera véhiculée sur le réseau entre le serveur et le
client.
• Comme tout élément échangé sur le réseau avec C.O.R.B.A. une
exception doit être décrite en IDL.
54
Décrire une exception en IDL
• Pour décrire une exception, on fait appel au mot clef IDL «
exception » :
exception nom_de_l'exception
{
membres_de_l'exception;
};
• Chaque membre respecte le format suivant :
type_idl nom_du_membre;
• L'exception peut ne pas avoir de membre.
55
Signaler qu'une opération peut
lancer une exception.
• Comme en Java, une opération décrite avec l'IDL doit signaler sa
capacité à lancer une exception.
• Pour cela, la description d'une opération doit comporter une clause
supplémentaire qui énumère les exceptions pouvant être lancées.
• Format de la clause « raises » :
raises ( liste_des_noms_d'exceptions )
• Exemple :
void f( ) raises ( monException );
56
Les catégories d'exceptions
• Il existe deux catégories d'exceptions sous C.O.R.B.A. :
– les exceptions systèmes ( héritent de
org.omg.CORBA.SystemException ),
– les exceptions utilisateurs ( héritent de
org.omg.CORBA.UserException ).
• Une exception décrite en IDL est une exception utilisateur qui sera
traduite en Java sous forme d'une classe.
57
Lancer une exception
depuis l'objet CORBA
• Pour lancer une exception CORBA on procède exactement de la
même façon qu'en Java.
• Chaque opération doit avoir une clause « throws » et l'on lance
l'exception avec l'instruction « throw ».
public void f() throws monException
{
// …
throw new monException();
}
58
Intercepter l'exception dans le client
• L'interception du côté client s'effectue toujours sur le même
principe qu'en Java.
• Un gestionnaire « catch » doit être placé pour intercepter
l'exception.
try
{
objet.f();
}
catch ( monException ex )
{
System.out.println("Une exception s'est produite…");
}
59
Mapping IDL/Java & Exception
•
Une exception IDL peut être définie au sein d'une interface IDL.
interface Diviseur
{
exception DivisionParZero { };
};
60
float division( in float nb1, in float nb2 )
raises ( DisivionParZero );
•
Dans ce cas, la traduction de « DivisionParZero » sera légèrement
différente car celle-ci sera placée dans un package Java portant le nom de
l'interface avec pour suffixe « Package ».
•
Ainsi, le nom de l'exception en Java sera :
DiviseurPackage.DivisionParZero
•
Cette règle s'applique à tous les types complexes qui sont décris dans une
interface.
Exercice
• Ecrire l'implantation de l'interface IDL suivante ainsi qu'un extrait
de client qui utiliserait celle-ci.
exception DivisionParZero
{ };
interface Diviseur
{
float division( in float nb1, in float nb2 )
raises ( DisivionParZero );
};
61
Les attributs IDL
• Il est possible dans une description IDL de définir des attributs
d'interface.
• Un attribut est une donnée accessible soit en lecture/écriture, soit en
lecture seulement.
• Pour décrire un attribut, on respecte le format suivant :
[ readonly ] attribute type_de_l'attribute nom_de_l'attribut;
Optionnel, ce mot clef signale que l'attribut
est accessible en lecture seule.
62
Traduction d'un attribut IDL en Java
• Un attribut est traduit en Java en deux opérations ( une pour la
lecture et une pour l'écriture ).
• Règle de traduction :
[ readonly ] attribute type nom ;
public void nom( type value );
public type nom( );
• Exemple :
attribute string nom;
public void nom( String value );
public String nom();
63
L'opération d'écriture n'existe
pas dans le cas d'un attribut
spécifié "readonly".
Le module IDL
• La notion de module est similaire à celle de package de Java.
• Un module introduit un espace de désignation supplémentaire. On
notera qu'un module peut contenir un autre module, une interface,
une description de type complexe.
• La description d'un module respecte la syntaxe suivante :
module nom_du_module
{
// corps du module
};
Un module est traduit en un package.
64
Exercice
• Implanter l'objet CORBA dont la description IDL est la suivante :
module Exemple
{
interface Personne
{
readonly attribute string nom;
attribute string adresse( );
readonly attribute long age();
void anniversaire();
};
};
65
Notion d'Alias
• Un alias permet de définir un autre « nom » pour un type existant.
• Pour décrire un alias en IDL, on respecte la règle suivante :
typedef nom_du_type nom_de_l'alias;
• Exemple :
typedef long Heure;
• Par la suite, on peut utiliser l'alias comme type :
void fixe_heure( in Heure h );
66
Traduction d'un Alias en Java
• La notion d'alias n'existe pas en Java. C'est pour cette raison que
l'alias est remplacé en Java par le type original.
// IDL
typedef long Heure;
interface Exemple
{
void fixe_heure( in Heure h );
};
// Java
public interface Exemple // …
{
public void fixe_heure( int h );
}
67
Notion de séquence IDL
• Une séquence est une donnée similaire à un tableau.
• Une séquence se décrit en IDL par le mot clef « sequence ». La
description d'une séquence est couplée à celle d'un alias.
• On distingue deux types de séquences :
– les séquences bornées : sequence< type, borne >
– les séquences non bornées : sequence< type >
• Exemples :
typedef sequence<String> liste;
typedef sequence<String, 100> liste_bornee;
68
Traduction d'une séquence en Java
• Une séquence IDL est traduite en un tableau Java.
• Exemples :
// IDL
typedef sequence<long> colonne;
// Java
int [ ]
// IDL
typedef sequence<colonne> matrice;
// Java
int [ ] [ ]
69
Notion de structure IDL
• Une structure IDL est une description qui permet de regrouper
plusieurs données appelées membres.
• Les structures IDL doivent contenir au minimum un membre.
• Chaque structure respecte le format suivant :
struct nom_de_la_structure
{
liste_des_membres;
};
chaque membre est décrit par :
type nom;
70
Exemple de structure
struct Personne
{
string nom;
string prenom;
Une structure peut ensuite servir de type de donnée.
};
typedef sequence< Personne > liste;
interface Course
{
attribute liste participants;
};
71
Traduction d'un structure
• Une structure est traduite en une classe Java ou chaque membre
est un attribut public de cette classe.
• Cette classe comporte deux constructeurs :
– un constructeur par défaut,
– un constructeur avec un paramètre pour chaque membre.
• Chaque membre est lui même traduit selon la règle standard qui lui
est propre ( exemple : une séquence est traduite en un tableau ).
72
Exemple de traduction de structure
// IDL
struct Personne
{
string nom;
string prenom;
};
// Java
public class Personne // …
{
public String nom;
public String prenom;
public Personne() { // … }
public Personne( String _nom, String _prenom ) { // … }
}
73
Héritage d'interfaces IDL
• La langage de description IDL supporte le concept d'héritage
multiple.
• Par contre aucune surcharge n'est autorisée.
• Pour convertir une référence d'objet vers une référence d'un objet de
base on doit utiliser l'opération « narrow » :
74
interface Base
{ //… };
Sub a = ….
interface Sub : Base
{ // … }:
Base b = BaseHelper.narrow( a );
Echange de référence d'objets
• Parmi les types de bases de l'IDL il existe celui de référence d'objet
symbolisé par « Object ».
• Ainsi, à l'aide de ce paramètre un client pourra échanger des
références avec un objet CORBA.
• On peut également échanger des références d'objets typées en
utilisant comme paramètre le nom d'une interface IDL.
75
Exemples
interface Exemple
{
// …
};
interface AutreExemple
{
void f ( in Object obj );
void g ( in Exemple obj );
};
76
On pourra grâce à « f » échanger des
références d'objets dont celle de « Exemple ».
Avec « g » on ne pourra échanger que des
références d'objets vers « Exemple » où
des références d'objets héritants
de « Exemple ».
Les classes Holders
• Afin d'échanger des paramètres d'opérations par adresses, une
classe supplémentaire est générée : la classe holder.
• Pour chaque type standard de CORBA ainsi que ceux définis en
IDL, une classe holder est générée.
• Une classe holder porte le même nom que le type avec pour suffixe
« Holder ».
• Cette classe comporte un attribut public appelé « value » qui
correspond au type associé à la classe holder.
77
Exemple de classe holder
Format général :
public class XXXHolder // …
{
public XXX value;
public XXXHolder() { // … }
public XXXHolder( XXX _value ) { … }
// ...
}
Exemple pour org.omg.CORBA.StringHolder :
78
public class StringHolder // ...
{
public String value;
public StringHolder() { // … }
public StringHolder( String _value ) { // … }
// ...
}
Quelques pièges...
Type standard IDL : string
Traduction en Java : String
Classe holder associée : org.omg.CORBA.StringHolder
Type utilisateur IDL : typedef long heure;
Traduction en Java : int
Classe holder associée : org.omg.CORBA.IntHolder
!
79
Aucune classe holder n'est générée pour une
re-définition de type excepté pour les séquences
et les tableaux.
Les paramètres « out » et « inout »
• Un paramètre de type « out » ou « inout » est traduit en un holder.
• Exemples :
// IDL
void retourne_heure( out Heure h );
// Java
public void retourne_heure( org.omg.CORBA.IntHolder h );
// IDL
typedef sequence<long> colonne;
typedef sequence<colonne> matrice;
void ajoute_matrices( in matrice m1, in matrice m2, out matrice result );
// Java
public void ajoute_matrices( int [ ][ ] m1, int [ ] [ ] m2, matriceHolder result );
80
Exercice
• Implanter l'interface suivante :
interface Exemple
{
typedef struct Personne
{
String nom;
String prenom;
} coureur;
typedef sequence< coureur > participants;
void inscrire_coureur( in coureur C );
void liste_des_coureurs( inout participants coureurs );
};
81
Approche par délégation
•
L’approche par héritage ne permet pas à un objet d’implanter plusieurs
interfaces.
•
Dans l'approche par délégation, l'implantation de l'objet n'hérite plus de
squelette mais implante l'interface d'opérations. L’héritage multiple
d’interface est donc possible.
•
L'implantation de l'objet est appelée : le délégué.
•
Une autre classe est générée : la classe de délégation. La classe de
délégation est un objet CORBA qui délègue ses opérations au délégués.
82
Illustration du principe de délégation
Client
Invoque
Objet de délégation
Délègue
Délégué
!
83
Le délégué n'est pas un objet CORBA. Il ne
dispose donc pas d'une référence d'objet.
Création de l’objet délégué
• L’objet délégué n’est plus un objet CORBA.
• Il implante l’interface PremierOperations
public class PremierImpl implements PremierOperations {
public void affiche(String message) {
System.out.println("le message : "+message);
}
}
84
Génération de l'objet de délégation
• L'objet de délégation est automatique généré à partir de la
description IDL.
• Pour cela, il faut appliquer une option spéciale du compilateur
d'IDL :
idl2java –fallTIE Premier.idl
• La classe de délégation porte le nom de l'interface à laquelle elle est
associée avec pour suffixe « Tie ».
PremierPOATie.java
85
Utilisation de l'objet de délégation
• L'objet de délégation comporte une opération importante :
– son constructeur qui prend en paramètre l'objet délégué
• Le serveur doit donc
– créer l'objet de délégation en lui donnant comme paramètre son
délégué : new PremierTie(new PremierImpl())
– connecter celui-ci à l'adaptateur d'objets.
– exporter au client la référence de l'objet de délégation.
• Il n’y a aucune modification du client
86
Exercice
• Reprendre l'exercice précédent en utilisant cette fois
l'approche par délégation. On devra en plus développer
le serveur.
interface Diviseur
{
exception DivisionParZero { };
float division( in float nb1, in float nb2 )
raises ( DisivionParZero );
87
};
Service de désignation
88
Commençons par un exercice
• Exporter/Importer une référence d’objet dans un
fichier est fastidieux
• Pourquoi ne pas créer un objet CORBA qui
stocke les références d’objets et permet d’y
accéder à partir de noms symboliques (DNS)
• A vous de définir l’IDL
89
Service de désignation (nommage)
• Rôle : retrouver les références d’objet à partir de
noms symboliques
• Définition du service : dans une interface IDL
– Module CosNaming
• Structure : arborescence appelé graphe de
désignation (Naming Graph)
– Une racine
– Des répertoires, appelés « contexte de nommage »
– Des feuilles : les références d’objet
• Un contexte est un objet qui gère une liste de
liaisons (= associations nom-référence)
90
Enregistrer une IOR dans l’annuaire
• = Créer une liaison dans un contexte
– ~ ranger l’association nom-IOR dans un répertoire
• Récupérer la référence du contexte dans lequel on va
créer la liaison
– Hypothèse dans l’exemple : la liaison est créée à la racine de
l’arbre => on récupère l’IOR de la racine
NamingContext ncRef = NamingContextHelper
.narrow(orb.resolve_initial_references(("NameSe
rvice")));
• Faire la liaison (méthode bind() ou rebind()) de
l’objet contexte ncRef) entre le nom et l’IOR href
Qu’est-ce qu’un nom ?
91
Qu’est-ce qu’un nom ?
• Séquence ordonnée de doublons
(Identificateur, Qualificatif)
– Un seul doublon = nom simple
("Hello", "appliCORBA")
• classe NameComponent
• Définir un nom simple
– Créer une séquence à un doublon (~ 1 tableau à 1 élém.)
NameComponent [] name = new
NameComponent[1];
– Initialiser la séquence
name[0] = new NameComponent();
name[0].id = "Hello"; name[0].kind =
"appliCORBA";
92
La liaison
• Liaison : Méthodes bind ou rebind de l’interface
NamingContext
– bind(name, href) : crée la liaison name-href dans le
contexte ncref
– rebind(name, href) : crée la liaison name-href dans le
contexte ncref même si le nom est déjà lié
93
Obtenir une référence
• Retrouver une IOR étant donné un nom
= résolution de noms
• La résolution
– Commence à la racine => il faut se positionner sur la
racine, donc récupérer son IOR (cf le serveur)
– Est faite par la méthode resolve(name) de
l’interface NamingContext
=> il faut initialiser name, de type
NameComponent (cf le serveur)
– Ne pas oublier de caster (narrow) vers le type voulu
94
orbd
• Service de désignation du jdk1.4
• Lancer orbd :
– orbd –ORBInitialPort ?? –ORBInitialHost ??
• Dans le serveur, mettre les paramètres suivants
dans l’initialisation de l’ORB
– ORBInitialPort ??
– ORBInitialHost ??
95
Etude du type « Any »
96
Any : un méta type !
• Le type Any est un type de donnée de CORBA.
• En IDL, le mot clef correspondant est « any ».
• Un type Any peut contenir une valeur de n’importe quel autre type
de donnée de CORBA ( types de bases et types complexes ).
• Ainsi, un Any peut contenir un entier, un réel et même une structure
ou une séquence.
97
Le type Any en Java
• CORBA fournit une classe appelée « org.omg.CORBA.Any » qui
correspond à la traduction en Java du type IDL « any ».
• Cette classe comporte de nombreuses opérations dont certaines pour
insérer une valeur et d’autres pour extraire une valeur.
• Ainsi, pour chaque type de base de CORBA il existe un couple
d’opérations ( insertion / extraction ) qui respecte le format suivant :
– void insert_XXXX( xxxxx valeur );
– xxxxx extract_XXXX( ) throws org.omg.CORBA.BAD_OPERATION;
Le nom Java du type
98
Le nom IDL du type
Cette exception est lancée si
le type demandé n’est pas celui contenu.
Création d’un type Any
• Pour créer un type Any on utilise l’opération « create_any »
proposée par la classe ORB.
• Exemple :
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
org.omg.CORBA.Any monAny = orb.create_any();
99
Exemple d’utilisation
public class Exemple
{
public static void main( String [] args )
{
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init( args, null );
org.omg.CORBA.Any any = orb.create_any();
int nombre = 100;
any.insert_long( nombre );
int extrait = any.extract_long( );
}
}
100
Exercice
• Développer l’application suivante ( client et objet ) :
interface Calculatrice
{
any addition( in any nb1, in any nb2 );
};
• Le client pourra alors additionner des entiers ( int ) et
des réels ( float ).
101
Insérer et extraire des types complexes
• Pour tous les types définis par l’utilisateur en IDL, le compilateur
génère une classe dite Helper qui porte le nom du type et ayant pour
suffixe « Helper ».
• Une classe Helper comporte deux opérations statiques pour
respectivement insérer et extraire une valeur du type auquel elle est
associée .
• Les opérations respectent le format suivant :
– void insert( org.omg.CORBA.Any any, xxxxx valeur );
– xxxxx extract( org.omg.CORBA.Any any );
102
• Si le type Any ne contient pas la valeur attendue, alors une
exception de type « org.omg.CORBA.MARSHAL » est lancée.
Connaître le type de la valeur d’un Any
• Il est également possible d’interroger le type Any afin de connaître
le type de la valeur qu’il contient.
• En effet, chaque Any est associé à deux informations :
– La valeur qu’il contient,
– La description du type de la valeur.
• L’opération « type » de la classe « org.omg.CORBA.Any » retourne
la description du type.
103
La description du type
• La description du type est en fait une classe qui comporte un grand
nombre d’opérations pour obtenir des informations sur le type.
• Le type est représenté par un TypeCode dont la classe Java se
nomme « org.omg.CORBA.TypeCode ».
• Tous les types CORBA ( simples et complexes ) ont un TypeCode
( une description ).
• Les informations retournées par un TypeCode sont forcément
fonction du type qu’il décrit. De ce fait, toutes les opérations de la
classe TypeCode ne sont pas utilisables à chaque fois.
104
Les familles de types
•
Chaque type CORBA est associé à une famille de type appelé TCKind.
•
Chaque type simple dispose de sa propre famille dont le nom est tk_xxxx (
boolean = tk_boolean ).
•
Les types complexes appartiennent chacun à une famille précise comme :
tk_struct, tk_sequence, …
•
En Java, la classe « org.omg.CORBA.TCKind » correspond à la traduction
du type CORBA TCKind.
– Cette classe comporte pour chaque catégorie de famille un attribut public de
valeur entière dont le nom est celui de la catégorie précédé de « _ » :
_tk_boolean
– Cette classe comporte également pour chaque catégorie un objet de type
TCKind dont le nom est celui de la catégorie. Pour obtenir la valeur entière de
ce TCKind, on utilise l’opération « value ».
105
Les principales opérations d’un TypeCode
• Parmi les opérations les plus utiles, on distingue :
– String name() : retourne le nom du type
– TCKind kind() : retourne la famille du type
– int member_count() : retourne le nombre de membres ( structure et
exceptions )
– String member_name( int index ) : retourne le nom d’un membre
– TypeCode member_type( int index ) : retourne la description du type
d’un membre
– int length( ) : retourne la taille du type ( séquences et tableaux )
– TypeCode original_type() : retourne le type original ( alias )
106
Obtenir le TypeCode d’un type
• On distingue deux méthodes selon que le type soit
simple ou complexe :
– Les types simples : on utilise l’opération « get_primitive_tc »
proposée par la classe ORB. Cette opération requiert en
paramètre le TCKind du type demandé.
– Les types complexes : les classes Helpers fournissent une
opération statique appelée « type ».
107
Exemple
// Initialise l’ORB
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
// Récupère le TypeCode d’un type simple : octet
org.omg.CORBA.TypeCode tc_simple =
orb.get_primitive_tc( org.omg.CORBA.TCKind.tk_octet );
// Récupère le TypeCode d’une structure « Personne » décrite en IDL
org.omg.CORBA.TypeCode tc_complexe = PersonneHelper.type( );
108
Exercice
• Reprendre l’application précédente en utilisant la notion
de TypeCode :
Typedef sequence<int> intSequence;
interface Calculatrice
{
any addition( in any nb1, in any nb2 );
};
• Les types à additionner seront soit des entiers, des réels
ou des séquences d’entiers.
109
Les mécanismes dynamiques
de C.O.R.B.A.
110
Concept de mécanismes dynamiques
• Il est possible dans C.O.R.B.A. de ne pas utiliser de
souche du côté client !
• De même, il est possible de ne pas utiliser de squelette
du côté serveur !
• Si l'application cliente n'utilise pas de souche, elle doit
alors construire elle même dynamiquement les
invocations vers les objets CORBA.
111
• De même, si une application serveur n'utilise pas de
squelette, elle doit alors intercepter dynamiquement les
invocations clientes.
Le mécanisme D.I.I.
• Le mécanisme D.I.I. ( Dynamic Invocation Interface ) fournit une
API pour créer manuellement ses requêtes et invoquer celles-ci
auprès d'un objet.
• Grâce à D.I.I. on peut facilement développer des applications
clientes génériques capable d'invoquer n'importe quel objet
CORBA.
• Le mécanisme D.I.I. est également utilisé pour fournir une
portabilité de la souche. En effet, en employant dans le code de la
souche uniquement des opérations de D.I.I. toutes les souches
seront portables d'un ORB à un autre.
112
Le mécanisme D.S.I.
• Le mécanisme D.S.I. ( Dynamic Server Interface ) permet de
concevoir des serveurs capables d'intercepter des invocations
clientes sans squelette.
• L'API de D.S.I. fournit toutes les fonctions nécessaires à la capture
d'une requêtes et l'interprétation des éléments qui la constitue.
• A l'aide de D.S.I. on peut définir des serveurs générique mais
également offrir la portabilité du squelette ( sur le même principe
que D.I.I. pour la souche ).
113
Notion de référentiel d'interfaces
• Le référentiel d'interfaces ( IR = Interface Repository ) est un
serveur CORBA.
• Ce serveur est une sorte de base de données qui contient des
descriptions d'objets CORBA.
• Ces descriptions ( identiques à IDL ) sont accessibles via un
ensemble d'interfaces.
• Le référentiel d'interfaces peut être utilisé par un client ou serveur
CORBA afin d'obtenir des informations sur la description d'un
objet. Couplé à D.I.I. ou D.S.I. le référentiel d'interfaces permet la
mise en œuvre d'applications totalement génériques.
114
Synthèse sur C.O.R.B.A.
115
Un environnement complet...
• C.O.R.B.A. est une architecture qui définit un environnement pour
permettre la collaboration entre applications réparties.
• C.O.R.B.A. est disponible sur de nombreuses plate-formes, dans de
nombreux langages et chez de nombreux fournisseurs.
• C.O.R.B.A. est simple à programmer en comparaison des
environnements équivalent.
• C.O.R.B.A. offre une homogénéisation du système d'informations.
116
Vue de l'architecture C.O.R.B.A.
Objet C.O.R.B.A.
CLIENT
SERVEUR
Squelette
souche
D.I.I.
Adaptateur d'objets
le bus C.O.R.B.A.
117
D.S.I.
Pour plus d'informations...
•
Quelques ouvrages
– Au cœur de CORBA
( J.DANIEL, Vuibert )
– CORBA : des concepts à la
pratique
( Ph.MERLE, InterEditions )
118
Téléchargement