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?
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:
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.
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.
If you do not already have a Naming Service configuration, we recommend the following architecture.
module ObjectFactory{ interface ApplicationFactory{ Object GetApplicationInstance();};};
GetApplicationInstance
operation in the IDL. Start the ApplicationFactory
server and publish its IOR. There are several ways to publish the IOR as described above: ApplicationFactory
server as a persisent IOR and hardcode the IOR
into application code or into the applet parameter fields in HTML.