Naming and persistent IORs


One of the trickiest problems in CORBA is the bootstrap problem: how does a CORBA client get an initial object on which to invoke object references?

Introduction and terminology of naming

Recall that in CORBA, every object has a unique Interoperable Object Reference, or IOR, that can be used to locate the object. The IOR contains information such as the host on which the object resides, the TCP/IP port on which the object is listening for requests, and an object key that distinguishes the object from other objects listening on that port.

An IOR has an opaque string representation, called a stringified IOR that may be read by any CORBA-compliant ORB. An typical stringified IOR (or just IOR for short) looks like (we have added line breaks indicated with a \ for readability):

IOR:005858580000001549444C3A69646C746573742F746573743A312E3000585858\
0000000100000000000000350001005800000006636F726261009B44000000214F52\
424C696E6B3A3A636F7262613A33393734383A3A736B656C65746F6E202330

CORBA itself defines two operations in the ORB pseudo interface for acting on stringified IORs:

module CORBA {
   pseudo interface ORB {
    string object_to_string (in Object obj);
    Object string_to_object (in String ior);
   };
}

Thus, given a stringified IOR bound to the string str, a Lisp proxy for the object represented by the string can be created via:

(op:string_to_object corba:orb str)

Given an object, its stringified IOR can be formed via:

(op:object_to_string corba:orb str)

Recall here that corba:orb is always bound the the ORB itself.

The simplest way for a client to access the server object on which it is to make invocations is for it to retrieve the stringified IOR of the server object.

ORBLink offers two utility functions to facilitate this.

The function orblink:read-ior-from-file, given a filename, returns a proxy for the IOR string stored in that filename.

The function orblink:write-ior-to-file, given an object and a pathname, writes the IOR of the given object to the file denoted by its argument.

The definition of these functions are located in the file examples/ior-io/cl/sample-ior-ior.cl.

This method for bootstrapping, although simple to understand and test, has several disadvantages, preeminent among which is the need for the client and the server to share access to a file system.

CORBA also defines a naming service. A Name Service is simply a standard CORBA object which contains operations that bind human-readable names to objects.

ORBLink itself will interoperate with other CORBA-compliant name services and, in addition, ORBLink contains a name service that is bundled, with source, with the ORB. The source to the ORBLink name service is located in the directory examples/naming/.

However, configuring and using a CORBA compliant name service has two disadvantages:

  1. Its API is somewhat complicated (although standardized).
  2. The IOR of the name service itself must be published.

The advantage of 1. above is that, although the CORBA Naming API is complicated, there are numerous third-party books that describe it. Once the CORBA Naming API and the IDL/Lisp mapping are learned, the Lisp API to the naming service is immediate.

In particular, if a CORBA naming service is already in use in your organization, this can be a good solution.

Another good solution to the naming problem is for the server to write the IOR to a file as usual, but for the client to retrieve the file via http:. This requires that a Web server have access to the file system to which the application server wrote the IOR. Such an architecture is particularly useful when the client is in Java and the server is in Lisp.

Finally, the process of disseminating IORs can be made simpler if the IOR is persistent; that is, if it does not change over even when the process holding the object it represents is started and stopped.

Creating persistent IORs

The IOR of an ORBLink object is formed from three fields:

The host and the port are attributes of the ORB, the object bound to corba:orb.

The salient IDL for these attributes is located in the file: orblink-idl.htm:

module ORBLink{
  pseudo interface ORB : CORBA::ORB {
  ...
    attribute unsigned long port;
    attribute string host;
};
};

These attributes are described in more detail in the section on the ORB pseudo-interface.

Each servant has a readonly attribute, its _marker. The name of this attribute is _marker, from the IDL

module CORBA {
  pseudo interface Servant {
    readonly attribute string _marker; // Only apples to servants
  };

A CORBA implementation object inherits from corba:servant. You can assign a marker, a unique name for the implementation object within the ORB, by using the :_marker initarg at object creation time. It is an error to assign the same marker to distinct objects.

Thus, the following sample code should return an object whose IOR is constant over different invocations. We assume that the class grid-implementation has been defined to inherit from corba:servant, for example using

      (defclass grid-implementation (interface_name-servant)...)

(setf (op:port corba:orb) 50000) ; Set the port on which the ORB listens. (setq grid-object (make-instance 'grid-implementation :_marker "GridServer")) (corba:object_to_string grid-object) ; get the IOR and start the socket listener

The string returned by the call to object_to_string should be constant across Lisp world invocations on the same host.

Architecting naming services

If you do not already have a Naming Service configuration, we recommend the following architecture.

  1. Set up a single factory object for your application. This server will simply provide the IOR of the actual entities in your application. You can customize and design it as you wish, but it is better to separate it from the application logic. For example sample IDL might be:
    	module ObjectFactory{
    	  interface ApplicationFactory{
    		Object GetApplicationInstance();};};
    
  2. Implement the GetApplicationInstance operation in the IDL. Start the ApplicationFactory server and publish its IOR. There are several ways to publish the IOR as described above:
    • Write it to a file that can be read by all the clients.
    • Store it in a Web Server.
    • Start the ApplicationFactory server as a persisent IOR and hardcode the IOR into application code or into the applet parameter fields in HTML.