 |
 |
15) Informatique distribuée |
|
 |
|
Texte original |
 |
Traducteur :
Jean-Pierre Vidal, Alban Peignier |
|
 |
|
 |
 |
 |
 |
 |
 |
|
 |
|
 |
 |
 |
Creating stubs and skeletons
|
 |
Création des stubs et des skeletons
|
 |
 |
 |
If you compile and run
PerfectTime.java, it won’t work even if you have the
rmiregistry running correctly. That’s because the framework for RMI
isn’t all there yet. You must first create the
stubs and
skeletons that provide the
network connection operations and allow you to pretend that the remote object is
just another local object on your machine.
|
 |
Si l'on compile et exécute PerfectTime.java, cela ne
fonctionnera pas même si rmiregistry a été correctement mis en route. Cela parce
que la machinerie pour RMI n'est pas complète. Il faut d'abord créer les stubs et skeletons qui
assurent les opérations de connexions réseaux et permettent de faire comme si l'objet distant était
juste un objet local sur de la machine.
|
 |
 |
 |
What’s going on behind the scenes
is complex. Any objects that you pass into or return from a remote object must
implement Serializable
(if you want to pass remote references instead of the entire objects, the object
arguments can implement Remote), so you can imagine that the stubs and
skeletons are automatically performing serialization and deserialization as they
“marshal” all of the arguments across the network and return the
result. Fortunately, you don’t have to know any of this, but you do
have to create the stubs and skeletons. This is a simple process: you invoke the
rmic tool on your
compiled code, and it creates the necessary files. So the only requirement is
that another step be added to your compilation process.
|
 |
Ce qui se passe derrière la scène est complexe. Tous les objets envoyés à
un objet distant ou reçus de celui-ci doivent implémenter Serializable (pour
passer des références distantes plutôt que les objets complets, les arguments peuvent
implémenter Remote), ainsi on peut considérer que les stubs et les skeletons
assurent automatiquement la sérialisation et la déserialisation tout en gérant l'acheminement des
arguments et du résultat au travers du réseau. Par chance, vous n'avez rien à connaître de tout
cela, mais vous devez avoir créé les stubs et les skeletons. C'est une procédure simple :
on invoque l'outil rmic sur le code compilé, et il crée les fichiers nécessaires.
La seule chose obligatoire est donc d'ajouter cette étape à la procédure de compilation.
|
 |
 |
 |
The rmic tool is particular about
packages and classpaths,
however. PerfectTime.java is in the package c15.rmi, and even if
you invoke rmic in the same directory in which PerfectTime.class
is located, rmic won’t find the file, since it searches the
classpath. So you must specify the location off the class path, like
so:
|
 |
L'outil rmic est particulier en ce qui concerne les
packages et les classpaths. PerfectTime.java est dans le package
c15.rmi, et même rmic est invoqué dans le même répertoire que celui où se
trouve PerfectTime.class, rmic ne trouvera pas le fichier,
puisqu'il se repère grâce au classpath. Vous devez ainsi préciser la localisation du classpath,
comme ceci :
|
 |
 |
 |
rmic c15.rmi.PerfectTime
|
 |
rmic c15.rmi.PerfectTime
|
 |
 |
 |
You don’t have to be in the
directory containing PerfectTime.class when you execute this command, but
the results will be placed in the current directory.
|
 |
La commande ne nécessite pas d'être exécutée à partir du répertoire
contenant PerfectTime.class, mais les résultats seront placés dans le répertoire
courant.
|
 |
 |
 |
When rmic runs successfully,
you’ll have two new classes in the directory:
|
 |
Lorsque rmic a été exécuté avec succès, deux nouvelles
classes sont obtenues dans le répertoire :
|
 |
 |
 |
PerfectTime_Stub.class
PerfectTime_Skel.class
|
 |
PerfectTime_Stub.class PerfectTime_Skel.class
|
 |
 |
 |
corresponding to the stub and skeleton.
Now you’re ready to get the server and client to talk to each
other.
|
 |
correspondant au stub et au skeleton. Dès lors, vous êtes prêt à faire
communiquer le serveur et le client.
|
 |
 |
 |
Using the remote object
|
 |
Utilisation de l'objet distant
|
 |
 |
 |
The whole point of RMI is to make the use
of remote objects simple. The only extra thing that you must do in your client
program is to look up and fetch the remote interface from the server. From then
on, it’s just regular Java programming: sending messages to objects.
Here’s the program that uses PerfectTime:
|
 |
Le but de RMI est de simplifier l'utilisation d'objets distants. La seule
chose supplémentaire qui doit être réalisée dans le programme client est de rechercher et de
rapatrier depuis le serveur l'interface distante. Après quoi, c'est simplement de la programmation
Java classique : envoyer des messages aux objets. Voici le programme qui utilise
PerfectTime:
|
 |
 |
 |
//: c15:rmi:DisplayPerfectTime.java
// Uses remote object PerfectTime.
package c15.rmi;
import java.rmi.*;
import java.rmi.registry.*;
public class DisplayPerfectTime {
public static void main(String[] args)
throws Exception {
System.setSecurityManager(
new RMISecurityManager());
PerfectTimeI t =
(PerfectTimeI)Naming.lookup(
"//peppy:2005/PerfectTime");
for(int i = 0; i < 10; i++)
System.out.println("Perfect time = " +
t.getPerfectTime());
}
} ///:~
|
 |
//: c15:rmi:DisplayPerfectTime.java // Utilise l'objet distant PerfectTime. package c15.rmi; import java.rmi.*; import java.rmi.registry.*;
public class DisplayPerfectTime { public static void main(String[ « args) { System.setSecurityManager( new RMISecurityManager()); try { PerfectTimeI t = (PerfectTimeI)Naming.lookup( "//peppy:2005/PerfectTime"); for(int i = 0; i < 10; i++) System.out.println("Perfect time = " + t.getPerfectTime()); } catch(Exception e) { e.printStackTrace(); } } } ///:~
|
 |
 |
 |
The ID string is the same as the one used
to register the object with Naming, and the first part represents the URL
and port number. Since you’re using a URL, you can also specify a machine
on the Internet.
|
 |
L'identifiant alpha-numérique est le même que celui utilisé pour
enregistrer l'objet avec Naming, et la première partie représente l'adresse et le
numéro du port. Cette URL permet par exemple de désigner une machine sur Internet.
|
 |
 |
 |
What comes back from
Naming.lookup( ) must be cast to the remote interface, not to
the class. If you use the class instead, you’ll get an
exception.
|
 |
Ce qui est retourné par Naming.lookup( ) doit être
transtypé vers l'interface distante, pas vers la classe. Si l'utilisation de la classe à
la place renverrait une exception.
|
 |
 |
 |
You can see in the method
call
|
 |
Vous pouvez observer dans l'appel de la méthode
|
 |
 |
 |
t.getPerfectTime()
|
 |
t.getPerfectTime( )
|
 |
 |
 |
that once you have a reference to the
remote object, programming with it is indistinguishable from programming with a
local object (with one difference: remote methods throw
RemoteException).
|
 |
qu'une fois la référence vers l'objet distant obtenue, la programmation
avec celle-ci ou avec un object distant est identique (avec une différence : les méthodes distantes
émettent RemoteException).
|
 |
 |
 |
CORBA
|
 |
Introduction à CORBA
|
 |
 |
 |
In large, distributed applications, your
needs might not be satisfied by the preceding approaches. For example, you might
want to interface with legacy data stores, or you might need services from a
server object regardless of its physical location. These situations require some
form of Remote Procedure Call (RPC), and possibly language independence. This is
where CORBA can help.
|
 |
Dans le cadre d'importantes applications distribuées, vos besoins risquent
de ne pas être satisfaits par les approches précédentes : comme par exemple, l'intégration de bases
existantes, ou l'accès aux services d'un objet serveur sans se soucier de sa localisation physique.
Ces situations nécessitent une certaine forme de Remote Procedure Call (RPC), et peut-être une
indépendance par rapport au langage. Là, CORBA peut vous aider.
|
 |
 |
 |
CORBA is not a language feature;
it’s an integration technology. It’s a specification that vendors
can follow to implement CORBA-compliant integration products. CORBA is part of
the OMG’s effort to define a standard framework for distributed,
language-independent object interoperability.
|
 |
CORBA n'est pas une fonctionnalité du langage ; c'est une technologie
d'integration. C'est une spécification que les fabricants peuvent suivre pour implémenter des
produits supportant une intégration CORBA. CORBA fait partie du travail réalisé par OMG afin de
définir une structure standard pour l'interopérabilité d'objets distribués et indépendants du
langage.
|
 |
 |
 |
CORBA supplies the ability to make remote
procedure calls into Java objects and non-Java objects, and to interface with
legacy systems in a location-transparent way. Java adds networking support and a
nice object-oriented language for building graphical and non-graphical
applications. The Java and OMG object model map nicely
to each other; for example, both Java and CORBA implement the interface concept
and a reference object model.
|
 |
CORBA fournit la possibilité de faire des appels à des procédures distantes
dans des objets Java et des objets non-Java, et d'interfacer des systèmes existants sans se soucier
de leur emplacement. Java ajoute un support réseau et un langage orienté-objet agréable pour
construire des applications graphiques ou non. Le modèle objet de l'OMG et celui de Java vont bien
ensemble ; par exemple, Java et CORBA mettent tout deux en oeuvre le concept d'interface et le
modèle de référence objet.
|
 |
 |
 |
CORBA fundamentals
|
 |
Principes de base de CORBA
|
 |
 |
 |
The object interoperability specification
developed by the OMG is commonly referred to as the Object Management
Architecture (OMA). The OMA defines two components: the Core Object Model and
the OMA Reference Architecture. The Core Object Model states the basic concepts
of object, interface, operation, and so on. (CORBA is a refinement of the Core
Object Model.) The OMA Reference Architecture defines an underlying
infrastructure of services and mechanisms that allow objects to interoperate.
The OMA Reference Architecture includes the Object Request Broker (ORB), Object
Services (also known as CORBA services), and common facilities.
|
 |
La spécification de l'interopérabilité objet est généralement désignée
comme l'Object Manager Architecture (OMA). L'OMA définit deux composants : le Core Object Model et
l'OMA Reference Architecture. Le Core Object Model met en place les concepts de base d'objet,
d'interface, d'opération, et ainsi de suite (CORBA est un raffinement de Core Object Model). L'OMA
Reference Architecture définit l'infrastructure sous-jacente des services et des mécanismes qui
permettent aux objets d'inter-opérer. L'OMA Reference Architecture contient l'Object Request Broker
(ORB), les Object Services (désignés aussi comme les services CORBA) et les outils
communs.
|
 |
 |
 |
The ORB is the communication bus by which
objects can request services from other objects, regardless of their physical
location. This means that what looks like a method call in the client code is
actually a complex operation. First, a connection with the server object must
exist, and to create a connection the ORB must know where the server
implementation code resides. Once the connection is established, the method
arguments must be marshaled, i.e. converted in a binary stream to be sent across
a network. Other information that must be sent are the server machine name, the
server process, and the identity of the server object inside that process.
Finally, this information is sent through a low-level wire protocol, the
information is decoded on the server side, and the call is executed. The ORB
hides all of this complexity from the programmer and makes the operation almost
as simple as calling a method on local object.
|
 |
L'ORB est le bus de communication par lequel les objets peuvent réclamer
des services auprès des autres objets, sans rien connaître de leur emplacement physique. Cela
signifie que ce qui ressemble à un appel de méthode dans le code client est vraiment une opération
complexe. D'abord, une connexion avec l'objet servant doit exister et pour créer cette connexion,
l'ORB doit savoir où se trouve le code implémentant cette partie serveur. Une fois que la connexion
est établie, les arguments de la méthode doivent être arrangés (marshaled), c'est à dire convertis
en un flux binaire pour être envoyés à travers le réseau. Les autres informations qui doivent être
envoyées sont le nom de la machine serveur, le processus serveur et l'identité de l'objet servant
au sein de ce processus. Finalement, l'information est envoyée par l'intermédiaire d'un protocole
bas-niveau, elle est décodée du côté du serveur, l'appel est exécuté. L'ORB masque tout de cette
complexité au programmeur et rend l'opération presque aussi simple que l'appel d'une méthode d'un
objet local.
|
 |
 |
 |
There is no specification for how an ORB
Core should be implemented, but to provide a basic compatibility among different
vendors’ ORBs, the OMG defines a set of services that are accessible
through standard interfaces.
|
 |
Cette spécification n'a pas pour but d'expliquer comment le coeur de l'ORB
devrait être implémenté, mais elle permet une compatibilité fondamentale entre les différents ORBs
des fournisseurs, l'OMG définit un ensemble de services qui sont accessibles par l'intermédiaire
d'interfaces standards.
|
 |
 |
 |
CORBA Interface Definition Language
(IDL)
|
 |
CORBA Interface Definition Language (IDL - Langage de Définition
d'Interface)
|
 |
 |
 |
CORBA is designed for language
transparency: a client object can call methods on a server object of different
class, regardless of the language they are implemented with. Of course, the
client object must know the names and signatures of methods that the server
object exposes. This is where IDL comes in. The CORBA IDL is a language-neutral
way to specify data types, attributes, operations, interfaces, and more. The IDL
syntax is similar to the C++ or Java syntax. The following table shows the
correspondence between some of the concepts common to three languages that can
be specified through CORBA IDL:
|
 |
CORBA a été mis au point pour être transparent vis-à-vis du langage : un
objet client peut appeler des méthodes d'un objet serveur d'une classe différente, sans se
préoccuper du langage avec lequel elles sont implémentées. Bien sûr, l'objet client doit connaître
le nom et les prototypes des méthodes que l'objet servant met à disposition. C'est là que l'IDL
intervient. L'IDL de CORBA est un moyen indépendant du langage qui permet de préciser les types de
données, les attributs, les opérations, les interfaces, et plus encore. La syntaxe de l'IDL est
similaire à celles du C++ ou de Java. La table qui suit montre la correspondance entre quelques uns
des concepts communs au trois langages qui peuvent être spécifiés à travers l'IDL de CORBA
:
|
 |
 |
 |
CORBA IDL
|
Java
|
C++
|
Module
|
Package
|
Namespace
|
Interface
|
Interface
|
Pure abstract class
|
Method
|
Method
|
Member function
|
|
 |
CORBA IDL
|
Java
|
C++
|
Module
|
Package
|
Namespace
|
Interface
|
Interface
|
Pure abstract class
|
Method
|
Method
|
Member function
|
|
 |
 |
 |
The inheritance concept is supported as
well, using the colon operator as in C++. The programmer writes an IDL
description of the attributes, methods, and interfaces that are implemented and
used by the server and clients. The IDL is then compiled by a vendor-provided
IDL/Java compiler, which reads the IDL source and generates Java
code.
|
 |
Le concept d'héritage est également supporté, en utilisant le séparateur
deux-points comme en C++. Le programmeur écrit en IDL la description des attributs, des méthodes et
des interfaces qui seront implémentés et utilisés par le serveur et les clients. L'IDL est ensuite
compilé par un compilateur IDL/Java propre au fournisseur, qui lit le source IDL et génère le code
Java.
|
 |
 |
 |
The IDL compiler is an extremely useful
tool: it doesn’t just generate a Java source equivalent of the IDL, it
also generates the code that will be used to marshal method arguments and to
make remote calls. This code, called the stub and skeleton code, is organized in
multiple Java source files and is usually part of the same Java package.
|
 |
Le compilateur IDL est un outil extrêmement utile : il ne génère pas juste
le source Java équivalent à l'IDL, il génère aussi le code qui sera utilisé pour réunir les
arguments des méthodes et pour réaliser les appels distants. Ce code, appelé le code stub et le
code skeleton, est organisé en plusieurs fichiers source Java et fait habituellement partie d'un
même package Java.
|
 |
 |
 |
The naming service
|
 |
Le service de nommage (naming service)
|
 |
 |
 |
The naming service is one of the
fundamental CORBA services. A CORBA object is accessed through a reference, a
piece of information that’s not meaningful for the human reader. But
references can be assigned programmer-defined, string names. This operation is
known as stringifying the reference, and one of the OMA components, the
Naming Service, is devoted to performing string-to-object and object-to-string
conversion and mapping. Since the Naming Service acts as a telephone directory
that both servers and clients can consult and manipulate, it runs as a separate
process. Creating an object-to-string mapping is called binding an
object, and removing the mapping is called unbinding. Getting an
object reference passing a string is called resolving the
name.
|
 |
Le service de nommage est l'un des services fondamentaux de CORBA. L'objet
CORBA est accessible par l'intermédiaire d'une référence, une information qui n'a pas de sens pour
un lecteur humain. Mais les références peuvent être des chaînes de caractères définies par le
programmeur. Cette opération est désignée comme chaînifier la référence, et l'un des composants de
l'OMA, le service de nommage, est dévoué à la conversion nom-vers-objet et objet-vers-nom et gère
ces correspondances. Puisque le service de nommage joue le rôle d'un annuaire téléphonique que les
serveurs et les clients peuvent consulter et manipuler, il fonctionne dans un processus séparé.
Créer une correspondance objet-vers-nom est appelé lier (binding) un objet, et supprimer
cette correspondance est dit délier (unbinding). Obtenir l'objet référence en passant la
chaîne de caractères est appelé résoudre le nom.
|
 |
 |
 |
For example, on startup, a server
application could create a server object, bind the object into the name service,
and then wait for clients to make requests. A client first obtains a server
object reference, resolving the string name, and then can make calls into the
server using the reference.
|
 |
Par exemple, au démarrage, une application serveur peut créer un objet
servant, enregistrer l'objet auprès du service de nommage, et attendre que des clients fassent des
requêtes. Un client obtient d'abord une référence vers cet objet servant en résolvant le nom et
ensuite peut faire des appels auprès du serveur en utilisant cette référence.
|
 |
 |
 |
Again, the Naming Service specification
is part of CORBA, but the application that implements it is provided by the ORB
vendor. The way you get access to the Naming Service functionality can vary from
vendor to vendor.
|
 |
A nouveau, la spécification du service de nommage fait partie de CORBA,
mais l'application qui l'implémente est mise à disposition par le fournisseur de l'ORB. Le moyen
d'accéder à ce service de nommage peut varier d'un fournisseur à l'autre.
|
 |
 |
 |
An example
|
 |
Un exemple
|
 |
 |
 |
The code shown here will not be elaborate
because different ORBs have different ways to access CORBA services, so examples
are vendor specific. (The example below uses JavaIDL, a free product from Sun
that comes with a light-weight ORB, a naming service, and an IDL-to-Java
compiler.) In addition, since Java is young and still evolving, not all CORBA
features are present in the various Java/CORBA products.
|
 |
Le code montré ici ne sera pas très élaboré car les différents ORBs ont des
moyens d'accéder aux services CORBA qui divergent, ainsi les exemples dépendent du fournisseur.
L'exemple qui suit utilise JavaIDL, un produit gratuit de Sun, qui fournit un ORB basique, un
service de nommage, et un compilateur IDL-vers-Java. De plus, comme Java est encore jeune et en
constante évolution, les différents produits CORBA pour Java n'incluent forcément toutes les
fonctionnalités de CORBA.
|
 |
 |
 |
We want to implement a server, running on
some machine, that can be queried for the exact time. We also want to implement
a client that asks for the exact time. In this case we’ll be implementing
both programs in Java, but we could also use two different languages (which
often happens in real situations).
|
 |
Nous voulons implémenter un serveur, fonctionnant sur une machine donnée,
qui soit capable de retourner l'heure exacte. Nous voulons aussi implémenter un client qui demande
l'heure exacte. Dans notre cas, nous allons réalisons les deux programmes en Java, mais nous
pourrions faire de même avec deux langages différents (ce qui se produit souvent dans la
réalité).
|
 |
 |
 |
Writing the IDL source
|
 |
Écrire le source IDL
|
 |
 |
 |
The first step is to write an IDL
description of the services provided. This is usually done by the server
programmer, who is then free to implement the server in any language in which a
CORBA IDL compiler exists. The IDL file is distributed to the client side
programmer and becomes the bridge between languages.
|
 |
La première étape consiste à écrire une description en IDL des services
proposés. Ceci est généralement réalisé par le programmeur du serveur, qui est ensuite libre
d'implémenter le serveur dans n'importe quel langage pour lequel un compilateur CORBA IDL existe.
Le fichier IDL est communiqué au programme de la partie cliente et devient le pont entre les
langages.
|
 |
 |
 |
The example below shows the IDL
description of our ExactTime server:
|
 |
L'exemple qui suit montre la description IDL de notre serveur
ExactTime :
|
 |
 |
 |
//: c15:corba:ExactTime.idl
//# You must install idltojava.exe from
//# java.sun.com and adjust the settings to use
//# your local C preprocessor in order to compile
//# This file. See docs at java.sun.com.
module remotetime {
interface ExactTime {
string getTime();
};
}; ///:~
|
 |
//: c15:corba:ExactTime.idl //# Vous devez installer idltojava.exe de //# java.sun.com et ajuster le paramétrage pour utiliser //# votre préprocesseur C local pour compiler //# ce fichier. Voyez la documentation sur java.sun.com. module remotetime { interface ExactTime { string getTime(); }; }; ///:~
|
 |
 |
 |
This is a declaration of the
ExactTime interface inside the remotetime namespace. The interface
is made up of one single method that gives back the current time in
string format.
|
 |
C'est donc la déclaration de l'interface ExactTime au sein
de l'espace de nommage remotetime. L'interface est composée d'une seule méthode
qui retourne l'heure actuelle dans une chaîne de caractères.
|
 |
 |
 |
Creating stubs and skeletons
|
 |
Création des stubs et des skeletons
|
 |
 |
 |
The second step is to compile the IDL to
create the Java stub and skeleton code that we’ll use for implementing the
client and the server. The tool that comes with the JavaIDL product is
idltojava:
|
 |
La deuxième étape consiste à compiler l'IDL pour créer le code Java du stub
et du skeleton que nous utiliserons pour implémenter le client et le serveur. L'outil fournit par
le produit JavaIDL est idltojava :
|
 |
 |
 |
idltojava remotetime.idl
|
 |
idltojava remotetime.idl
|
 |
 |
 |
This will automatically generate code for
both the stub and the skeleton. Idltojava generates a Java package
named after the IDL module, remotetime, and the generated Java files are
put in the remotetime subdirectory. _ExactTimeImplBase.java is the
skeleton that we’ll use to implement the server object, and
_ExactTimeStub.java will be used for the client. There are Java
representations of the IDL interface in ExactTime.java and a couple of
other support files used, for example, to facilitate access to the naming
service operations.
|
 |
Cela générera automatiquement à la fois le code pour le stub et celui pour
le skeleton. Idltojava génère un package Java nommé selon le
module IDL remotetime et les fichiers Java générés sont déposés dans ce
sous-répertoire remotetime. _ExactTimeImplBase.java est le
skeleton que nous allons utiliser pour implémenter l'objet servant et
_ExactTimeStub.java sera utilisé pour le client. Il y a des représentations Java
de l'interface IDL dans ExactTime.java et toute une série d'autres fichiers de
support utilisés, par exemple, pour faciliter l'accès aux fonctions du service de
nommage.
|
 |
 |
 |
Implementing the server and the client
|
 |
Implémentation du serveur et du client
|
 |
 |
 |
Below you can see the code for the server
side. The server object implementation is in the ExactTimeServer class.
The RemoteTimeServer is the application that creates a server object,
registers it with the ORB, gives a name to the object reference, and then sits
quietly waiting for client requests.
|
 |
Ci-dessous, vous pouvez voir le code pour la partie serveur.
L'implémentation de l'objet servant est dans la classe ExactTimeServer.
RemoteTimeServer est l'application qui créé l'objet servant, l'enregistre auprès
de l'ORB, donne un nom à la référence vers l'objet, et qui ensuite s'assoit tranquillement en
attendant les requêtes des clients.
|
 |
 |
 |
//: c15:corba:RemoteTimeServer.java
import remotetime.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
import java.util.*;
import java.text.*;
// Server object implementation
class ExactTimeServer extends _ExactTimeImplBase {
public String getTime(){
return DateFormat.
getTimeInstance(DateFormat.FULL).
format(new Date(
System.currentTimeMillis()));
}
}
// Remote application implementation
public class RemoteTimeServer {
// Throw exceptions to console:
public static void main(String[] args)
throws Exception {
// ORB creation and initialization:
ORB orb = ORB.init(args, null);
// Create the server object and register it:
ExactTimeServer timeServerObjRef =
new ExactTimeServer();
orb.connect(timeServerObjRef);
// Get the root naming context:
org.omg.CORBA.Object objRef =
orb.resolve_initial_references(
"NameService");
NamingContext ncRef =
NamingContextHelper.narrow(objRef);
// Assign a string name to the
// object reference (binding):
NameComponent nc =
new NameComponent("ExactTime", "");
NameComponent[] path = { nc };
ncRef.rebind(path, timeServerObjRef);
// Wait for client requests:
java.lang.Object sync =
new java.lang.Object();
synchronized(sync){
sync.wait();
}
}
} ///:~
|
 |
//: c15:corba:RemoteTimeServer.java import remotetime.*; import org.omg.CosNaming.*; import org.omg.CosNaming.NamingContextPackage.*; import org.omg.CORBA.*; import java.util.*; import java.text.*;
// Implémentation de l'objet servant class ExactTimeServer extends _ExactTimeImplBase { public String getTime(){ return DateFormat. getTimeInstance(DateFormat.FULL). format(new Date( System.currentTimeMillis())); } }
// Implémentation de l'application distante public class RemoteTimeServer { public static void main(String[ « args) { try { // Crée l'ORB et l'initialise: ORB orb = ORB.init(args, null); // Crée l'objet servant et l'enregistre : ExactTimeServer timeServerObjRef = new ExactTimeServer(); orb.connect(timeServerObjRef); // Obtient la racine du contexte de nommage : org.omg.CORBA.Object objRef = orb.resolve_initial_references( "NameService"); NamingContext ncRef = NamingContextHelper.narrow(objRef); // Associe un nom // à la référence de l'objet (binding): NameComponent nc = new NameComponent("ExactTime", ""); NameComponent[ « path = { nc }; ncRef.rebind(path, timeServerObjRef); // Attend les requêtes des clients : java.lang.Object sync = new java.lang.Object(); synchronized(sync){ sync.wait(); } } catch (Exception e) { System.out.println( "Remote Time server error: " + e); e.printStackTrace(System.out); } } } ///:~
|
 |
 |
 |
As you can see, implementing the server
object is simple; it’s a regular Java class that inherits from the
skeleton code generated by the IDL compiler. Things get a bit more complicated
when it comes to interacting with the ORB and other CORBA
services.
|
 |
Comme vous pouvez le constater, implémenter l'objet servant est simple ;
c'est une classe Java classique qui hérite du code du skeleton généré par le compilateur IDL. Les
choses se complexifient un peu lorsqu'on en vient à interagir avec l'ORB et les autres services
CORBA.
|
 |
 |
 |
Some CORBA services
|
 |
Quelques services CORBA
|
 |
 |
 |
This is a short description of what the
JavaIDL-related code is doing (primarily ignoring the part of the CORBA code
that is vendor dependent). The first line in main( ) starts up the
ORB, and of course, this is because our server object will need to interact with
it. Right after the ORB initialization, a server object is created. Actually,
the right term would be a transient servant object: an object that
receives requests from clients, and whose lifetime is the same as the process
that creates it. Once the transient servant object is created, it is registered
with the ORB, which means that the ORB knows of its existence and can now
forward requests to it.
|
 |
Voici une courte description de ce qui réalise le code relevant de JavaIDL
(en évitant la partie de code CORBA qui dépend du fournisseur). La première ligne dans le
main( ) démarre l'ORB parce que bien sûr notre objet servant aura besoin
d'interagir avec celui-ci. Juste après l'initialisation de l'ORB, l'objet servant est créé. En
réalité, le terme correct serait un objet servant temporaire (transient) : un objet qui
reçoit les requêtes provenant des clients, et dont la durée de vie est limitée à celle du processus
qui l'a créé. Une fois l'objet servant temporaire créé, il est enregistré auprès de l'ORB,
ce qui signifie alors que l'ORB connaît son existence et peut rediriger les requêtes vers
lui.
|
 |
 |
 |
Up to this point, all we have is
timeServerObjRef, an object reference that is known only inside the
current server process. The next step will be to assign a stringified name to
this servant object; clients will use that name to locate the servant object. We
accomplish this operation using the Naming Service. First, we need an object
reference to the Naming Service; the call to
resolve_initial_references( ) takes the stringified object reference
of the Naming Service that is “NameService,” in JavaIDL, and returns
an object reference. This is cast to a specific NamingContext reference
using the narrow( ) method. We can use now the naming
services.
|
 |
A partir de là, tout ce dont nous disposons est
timeServerObjRef, une référence vers un objet qui n'est connu qu'à l'intérieur du
processeur serveur actuel. L'étape suivante va consister à associer un nom alphanumérique à cet
objet servant ; les clients utiliseront ce nom pour localiser l'objet servant. Cette opération sera
réalisée grâce à l'aide du service de nommage. Tout d'abord, nous avons besoin d'une référence vers
le service de nommage ; la méthode resolve_initial_references( ) utilise la
référence objet « chainifiée » du service de nommage qui s'appelle NameService dans
JavaIDL, et retourne la référence vers l'objet. Celle-ci est transformée en une référence
spécifique à NamingContext au moyen de la méthode narrow( ).
Nous pouvons maintenant utiliser les services de nommage.
|
 |
 |
 |
To bind the servant object with a
stringified object reference, we first create a NameComponent object,
initialized with “ExactTime,” the name string we want to bind to the
servant object. Then, using the rebind( ) method, the stringified
reference is bound to the object reference. We use rebind( ) to
assign a reference, even if it already exists, whereas bind( )
raises an exception if the reference already exists. A name is made up in CORBA
by a sequence of NameContexts—that’s why we use an array to bind the
name to the object reference.
|
 |
Pour associer l'objet servant avec une référence objet « chainifiée », nous créons d'abord un objet
NameComponent, initialisé avec la chaîne de caractères qui sera associée : face="Georgia">« ExactTime ». Ensuite, en utilisant la méthode
rebind( ), la référence alphanumérique est associée à la référence vers
l'objet. Nous utilisons rebind( ) pour mettre en place une référence, même si
celle-ci existe déjà. Un nom est composé dans CORBA d'une séquence de NameComponents (voilà
pourquoi nous utilisons un tableau pour associer le nom à la référence).
|
 |
 |
 |
The servant object is finally ready for
use by clients. At this point, the server process enters a wait state. Again,
this is because it is a transient servant, so its lifetime is confined to the
server process. JavaIDL does not currently support persistent
objects—objects that survive the execution of the process that creates
them.
|
 |
L'objet est enfin prêt à être utilisé par des clients. A ce moment-là, le
serveur entre dans un état d'attente. Encore une fois, ceci est nécessaire puisqu'il s'agit d'un
serveur temporaire : sa durée de vie dépend du processus serveur. JavaIDL ne supporte pas
actuellement les objets persistants, qui survivent après la fin de l'exécution du processus qui les
a créés.
|
 |
 |
 |
Now that we have an idea of what the
server code is doing, let’s look at the client code:
|
 |
Maintenant que nous avons une idée de ce que fait le code du serveur,
regardons le code du client :
|
 |
 |
 |
//: c15:corba:RemoteTimeClient.java
import remotetime.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
public class RemoteTimeClient {
// Throw exceptions to console:
public static void main(String[] args)
throws Exception {
// ORB creation and initialization:
ORB orb = ORB.init(args, null);
// Get the root naming context:
org.omg.CORBA.Object objRef =
orb.resolve_initial_references(
"NameService");
NamingContext ncRef =
NamingContextHelper.narrow(objRef);
// Get (resolve) the stringified object
// reference for the time server:
NameComponent nc =
new NameComponent("ExactTime", "");
NameComponent[] path = { nc };
ExactTime timeObjRef =
ExactTimeHelper.narrow(
ncRef.resolve(path));
// Make requests to the server object:
String exactTime = timeObjRef.getTime();
System.out.println(exactTime);
}
} ///:~
|
 |
//: c15:corba:RemoteTimeClient.java import remotetime.*; import org.omg.CosNaming.*; import org.omg.CORBA.*;
public class RemoteTimeClient { public static void main(String[ « args) { try { // Création et initialisation de l'ORB : ORB orb = ORB.init(args, null); // Obtient la racine du contexte de nommage : org.omg.CORBA.Object objRef = orb.resolve_initial_references( "NameService"); NamingContext ncRef = NamingContextHelper.narrow(objRef); // Résout la référence alphanumérique // du serveur d'heure : NameComponent nc = new NameComponent("ExactTime", ""); NameComponent[ « path = { nc }; ExactTime timeObjRef = ExactTimeHelper.narrow( ncRef.resolve(path)); // Effectue une requête auprès de l'objet servant : String exactTime = timeObjRef.getTime(); System.out.println(exactTime); } catch (Exception e) { System.out.println( "Remote Time server error: " + e); e.printStackTrace(System.out); } } } ///:~
|
 |
 |
 |
 |
 |
 |
 |
 |
|
 |
 |
 |