t
t
t
t
t t   15) Informatique distribuée
tttt
t
carrea) Préface carreb) Avant-propos carre1) Introduction sur les &laqo; objets » carre2) Tout est &laqo; objet » carre3) Contrôle du flux du programme carre4) Initialization & Cleanup carre5) Cacher l'implémentation carre6) Réutiliser les classes carre7) Polymorphisme carre8) Interfaces & classes internes carre9) Stockage des objets carre10) Error Handling with Exceptions carre11) Le système d’E/S de Java carre12) Identification dynamique de type carre13) Création de fenêtres & d'Applets carre14) Les &laqo; Threads » multiples 15) Informatique distribuée carreA) Passage et retour d'objets carreB) L'Interface Java Natif (JNI) carreC) Conseils pour une programation stylée en Java carreD) Resources
Texte original t Traducteur : Jean-Pierre Vidal, Alban Peignier
t
t
///
Ce chapitre contient 12 pages
1 2 3 4 5 6 7 8 9 10 11 12
\\\
t t t
t t t
t
t t t

Creating stubs and skeletons

t

Création des stubs et des skeletons

t t t
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.
t 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.
t t t
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.
t 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.
t t t
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:
t 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 :
t t t
rmic c15.rmi.PerfectTime t
rmic c15.rmi.PerfectTime
t t t
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.
t 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.
t t t
When rmic runs successfully, you’ll have two new classes in the directory:
t Lorsque rmic a été exécuté avec succès, deux nouvelles classes sont obtenues dans le répertoire :
t t t
PerfectTime_Stub.class PerfectTime_Skel.class t
PerfectTime_Stub.class
PerfectTime_Skel.class
t t t
corresponding to the stub and skeleton. Now you’re ready to get the server and client to talk to each other.
t correspondant au stub et au skeleton. Dès lors, vous êtes prêt à faire communiquer le serveur et le client.
t t t

Using the remote object

t

Utilisation de l'objet distant

t t t
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:
t 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:
t t t
//: 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()); } } ///:~ t
//: 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();
    }
  }
} ///:~
t t t
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.
t 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.
t t t
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.
t 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.
t t t
You can see in the method call
t Vous pouvez observer dans l'appel de la méthode
t t t
t.getPerfectTime() t
t.getPerfectTime( )
t t t
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).
t 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).
t t t

CORBA

t

Introduction à CORBA

t t t
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.
t 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.
t t t
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.
t 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.
t t t
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.
t 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.
t t t

CORBA fundamentals

t

Principes de base de CORBA

t t t
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.
t 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.
t t t
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.
t 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.
t t t
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.
t 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.
t t t

CORBA Interface Definition Language (IDL)

t

CORBA Interface Definition Language (IDL - Langage de Définition d'Interface)

t t t
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:
t 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 :
t t t
CORBA IDL
Java
C++
Module
Package
Namespace
Interface
Interface
Pure abstract class
Method
Method
Member function
t
CORBA IDL Java C++
Module Package Namespace
Interface Interface Pure abstract class
Method Method Member function
t t t
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.
t 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.
t t t
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.
t 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.
t t t

The naming service

t

Le service de nommage (naming service)

t t t
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.
t 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.
t t t
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.
t 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.
t t t
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.
t 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.
t t t

An example

t

Un exemple

t t t
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.
t 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.
t t t
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).
t 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é).
t t t

Writing the IDL source

t

Écrire le source IDL

t t t
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.
t 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.
t t t
The example below shows the IDL description of our ExactTime server:
t L'exemple qui suit montre la description IDL de notre serveur ExactTime :
t t t
//: 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(); }; }; ///:~ t
//: 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();
   };
}; ///:~
t t t
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.
t 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.
t t t

Creating stubs and skeletons

t

Création des stubs et des skeletons

t t t
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:
t 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 :
t t t
idltojava remotetime.idl t
idltojava remotetime.idl
t t t
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.
t 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.
t t t

Implementing the server and the client

t

Implémentation du serveur et du client

t t t
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.
t 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.
t t t
//: 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(); } } } ///:~ t
//: 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);
    }
  }
} ///:~
t t t
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.
t 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.
t t t

Some CORBA services

t

Quelques services CORBA

t t t
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.
t 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.
t t t
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.
t 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.
t t t
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.
t 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).
t t t
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.
t 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.
t t t
Now that we have an idea of what the server code is doing, let’s look at the client code:
t Maintenant que nous avons une idée de ce que fait le code du serveur, regardons le code du client :
t t t
//: 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); } } ///:~ t
//: 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);
    }
  }
} ///:~
t t t
t t t
t t
\\\
///
t t t
t
     
Sommaire Le site de Bruce Eckel