A CORBA server has to provide an implementation object, called a servant, for each of the proxy objects manipulated by the client. Our server needs to implement the initial bank servant, and then create new servants for each of the account objects created in response to openAccount
, openCheckingAccount
and retrieveAccount
requests.
Each of these servants needs to be registered in the CORBA environment and assigned an object reference, so that the ORB can direct incoming requests to the appropriate servant.
In CORBA, the primary means for an object implementation to access ORB services such as object reference generation is via an object adapter . The object adapter is responsible for the following functions:
The LispWorks ORB provides an implementation of the Portable Object Adapter (POA). This object adapter forms part of the CORBA standard and, like the ORB, has an interface that is specified in pseudo IDL (PIDL). The Common Lisp interface to the POA conforms closely to the interface obtained by applying the Common Lisp mapping rules to the POA's PIDL specification.
A POA object manages the implementation of a collection of objects, associating object references with specific servants. While the ORB is an abstraction visible to both the client and server, POA objects are visible only to the server.
User-supplied object implementations are registered with a POA and assigned object references.When a client issues a request to perform an operation on such an object reference, the ORB and POA cooperate to determine the servant on which the operation should be invoked, and perform the invocation as an upcall through a skeleton method.
The POA allows several ways of using servants although it does not deal with the issue of starting the server process. Once started, however, there can be a servant started and ended for a single method call, a separate servant for each object, or a shared servant for all instances of a particular object type. It allows for groups of objects to be associated by means of being registered with different instances of the POA object and allows implementations to specify their own activation techniques. If the implementation is not active when an invocation is performed, the POA can start one.
Unfortunately, the flexibility afforded by the POA means that its interface is complex and somewhat difficult to use. The example in this tutorial makes only elementary use of the POA.
Here is the PIDL specification of the facilities of the POA that the bank tutorial uses:
module PortableServer {
native Servant;
interface POAManager {
exception AdapterInactive{};
void activate() raises (...);
...
};
interface POA {
exception WrongAdapter {};
readonly attribute POAManager the_POAManager;
Object servant_to_reference(in Servant p_servant)
raises (...);
Servant reference_to_servant(in Object reference)
raises (WrongAdapter, ...);
...
};
...
};
The POA-related interfaces are defined in a module separate from the CORBA
module, called the PortableServer
module. It declares several interfaces, of which only the POA
and POAManager
are shown here.
The PortableServer
module specifies the type Servant
. Values of type Servant
represent language-specific implementations of CORBA interfaces. Since this type can only be determined by the programming language in question, it is merely declared as a native type in the PIDL.
In the Common Lisp mapping, the Servant
type maps to the abstract class PortableServer:Servantbase
. User defined Common Lisp classes that are meant to implement CORBA objects and be registered with a POA must inherit from this class.
Each POA
object has an associated POAManager
object. A POA manager encapsulates the processing state of the POA it is associated with. Using operations on the POA manager, an application can cause requests for a POA to be queued or discarded, and can cause the POA to be deactivated.
A POA manager has two main processing states, holding and active, that determine the capabilities of the associated POA and the handling of ORB requests received by that POA. Both the POA manager and its associated POA are initially in the holding state.
When a POA is in the holding state, it simply queues requests received from the ORB without dispatching them to their implementation objects. In the active state, the POA receives and processes requests. Invoking the POA Manager's activate
operation causes it, and its associated POAs, to enter the active state.
A POA object provides two useful operations that map between object references and servants. The servant_to_reference
operation has two behaviors. If the given servant is not already active in the POA, then the POA generates a new object reference for that servant, records the association in the POA, and returns the reference. If the servant is already active in the POA, then the operation merely returns its associated object reference.
The reference_to_servant
operation returns the servant associated with a given object reference in the POA. If the object reference was not created by this POA, the operation raises the WrongAdapter
exception.
Developing Component Software with CORBA - 14 Feb 2015