This brief overview of the Portable Object Adapter (POA) provides a summary of related terminology, a graphic view of the POA architecture, and a complete example that shows how to implement a POA.
An Object Adapter specifies how server-side CORBA objects interact with the ORB. Prior to CORBA 2.2, the Basic Object Adapter (BOA) was specified. The BOA specification was under specified which lead to different implementations by different vendors. This prevented portability on the server side. CORBA 2.2 now replaces the Basic Object Adapter with the Portable Object Adapter (POA).
The Portable Object Adapter specification provides server-side portability of implementations and has been more tightly specified to increase portability and it has a richer functionality.
First, some initial basic terminology used in the POA. The implementations of objects are now known as servants, and the creation of a servant is known as incarnation. To etherealize a servant means to destroy it. A CORBA object reference is associated with a servant by using an Active Object Map, in which each object reference is mapped to a servant using an Object ID.
The POA is designed to meet the following goals:
_this( ) method on a servant causes the servant to be registered with a POA and an object reference to be returned.
Upon invocation by the ORB, a POA is called to satisfy a client request. The POA must activate a servant that does the actual work required by the client request.
A client request is an invocation on a CORBA object (class Object) or a class derived from Object. The client may be either local (within the same process) or remote (from another process).
Processing a client request requires the following steps:
The following key terms are used in POA discussions. You should understand them and also have a general understanding of object-oriented programming terminology and concepts.
Figure 1. The POA Architecture
Writing a compliant, portable application is not difficult. The short program below illustrates how to set up the basic requirements.
// My header file contains a declaration of My_Servant_Impl
#include "my_imp.h"
int main(int argc, char *argv[])
{
// Initialize the ORB.
CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);
// Obtain an object reference for the Root POA.
CORBA::Object_var obj = orb -> resolve_initial_references("RootPOA");
PortableServer::POA_var poa = PortableServer::POA::_narrow(obj);
// Incarnate a servant.
My_Servant_Impl servant;
// Implicitly register the servant with the RootPOA.
obj = servant._this();
// Start the POA listening for requests.
poa -> the_POAManager() ->activate();
// Run the ORB's event loop.
orb -> run();
// Ready to work
}
|
This section contains the following subtopics:
The NonStop DOM ORB provides a POA object called a root POA, as required by OMG. The root POA, named RootPOA, is available to all servers and applications and is used by default if no other POA is specified. The ORB provides the object reference for RootPOA.
The following table shows the RootPOA default policies:
| Policy | Value |
|---|---|
| Thread | ORB_CTRL_MODEL |
| Lifespan | TRANSIENT |
| Object Id Uniqueness | UNIQUE_ID |
| Id Assignment | SYSTEM_ID |
| Servant Retention | RETAIN |
| Request Processing | USE_ACTIVE_OBJECT_MAP_ONLY |
| Implicit Activation | IMPLICIT_ACTIVATION |
The following example illustrates how to obtain the root POA reference.
CORBA::ORB_ptr = CORBA::ORB_init(argc, argv);
CORBA::Object_ptr pfobj =
orb ->resolve_initial_references("RootPOA");
PortableServer::POA_ptr rootPOA;
rootPOA = PortableServer::POA::narrow(pfobj);
|
If an application requires POA management or policies different from the root POA, the developer should create a child POA. A child POA can use policies different from the root POA and can have a different POA manager. Implementation of a child POA also provides an adapter activator and a servant manager. Each child POA creates a name space for application execution.
You create a child POA by calling the create_POA( ) method of the parent POA. The child POA name must not already be in use by any direct descendant of the parent POA.
A child POA created with a lifespan policy of PERSISTENT requires special consideration from the application writer. The application must re-create the POA that was initially used to create the persistent object. All ancestor POAs relative to this child POA must also be re-created as a consequence. (The child POA cannot be properly re-created without its parent and access to RootPOA, which always exists. This is required in order to call create_POA( ), and so on.) The POA names used in the original server process must all be re-created, and all the original policies for each of those POA must be re-created.
Failure to do this will cause CORBA::OBJECT_NOT_EXIST system exception for the old persistent references when used by clients. See the following example:
CORBA::ORB_ptr = CORBA::ORB_init(argc, argv);
CORBA::Object_ptr pfobj =
orb ->resolve_initial_references("RootPOA");
PortableServer::POA_ptr rootPOA;
rootPOA = PortableServer::POA::narrow(pfobj);
CORBA::PolicyList = my_policies(2);
my_policies[0] = rootPOA ->create_thread_policy(
PortableServer::ThreadPolicy::SINGLE_THREAD_MODEL);
my_policies[1] = rootPOA ->create_lifespan_policy(
PortableServer::LifespanPolicy::PERSISTENT);
PortableServer::POA_ptr poa =
rootPOA ->create_POA("my_poa",
PortableServer::POAManager::nil(),
my_policies);
|
This topic provides detailed information on the following policies:
The characteristic behavior of a POA (other than the root POA) is determined at the time of its creation by using policies. Once set, policies cannot be changed during the life of the POA. The policies are not inherited by child POAs.
POA policy interfaces are derived from CORBA::Policy. These interfaces are used with the POA::create_POA( ) operation.
The following sample shows a pattern for creating policies:
CORBA::PolicyList my_policies(2);
my_policies.length(2);
my_policies[0] = rootPOA ->create_thread_policy(
PortableServer::ThreadPolicy::SINGLE_THREAD_MODEL);
my_policies[1] = rootPOA ->create_lifespan_policy(
PortableServer::LifespanPolicy::PERSISTENT);
PortableServer::POA_ptr poa =
rootPOA ->create_POA("my_poa",
PortableServer::POAManager::nil(),
my_policies);
|
A POA can have each of its servants execute in multiple threads that are under NonStop DOM control, or the servants can be serialized for execution in a single thread. In that case, only one request is running at a time.
To create an object that uses the ThreadPolicy interface, call the POA::create_thread_policy( ) operation. The result is passed to the POA::create_POA( ) operation.
If no ThreadPolicy object is passed to the create_POA( ) operation, the default value ORB_CTRL_MODEL is used.
The ORB_CTRL_MODEL value allows multiple threads to concurrently execute client requests. The SINGLE_THREAD value forces new requests to proceed in a serial fashion. One thread might need to wait for a previous request to complete for the POA before being allowed to continue.
enum ThreadPolicyValue
{
ORB_CTRL_MODEL,
SINGLE_THREAD_MODEL
};
interface ThreadPolicy : CORBA::Policy
{
readonly attribute ThreadPolicyValue value;
};
|
ORB_CTRL_MODELSINGLE_THREAD_MODELUse this policy to specify whether CORBA objects created within a POA are persistent or transient.
To create an object that uses the LifespanPolicy interface, call the POA::create_lifespan_policy( ) operation. The result is passed to POA::create_POA( ) operation.
If no LifespanPolicy object is passed to the create_POA( ) operation, the default value used is TRANSIENT.
enum LifespanPolicyValue
{
TRANSIENT,
PERSISTENT
};
interface LifespanPolicy : CORBA::Policy
{
readonly attribute LifespanPolicyValue value;
};
|
TRANSIENTPERSISTENTUse this policy to specify whether a servant is associated with a single CORBA object or corresponds to multiple CORBA objects.
To create an object that uses the IdUniquesnessPolicy interface, call the POA::create_id_uniqueness_policy( ) operation. The result is passed to POA::create_POA( ) operation.
If no IdUniquenessPolicy object is passed to the create_POA( ) operation, the default value used is UNIQUE_ID.
enum IdUniquenessPolicyValue
{
UNIQUE_ID,
MULTIPLE_ID
};
interface IdUniquenessPolicy : CORBA::Policy
{
readonly attribute IdUniquesnessPolicyValue value;
};
|
UNIQUE_IDMULTIPLE_IDUse this policy to specify whether the POA assigns the Object Id or whether the application provides the Object Id.
To create an object that uses the IdAssignmentPolicy interface, call the POA::create_id_assignment_policy( ) operation. The result is passed to POA::create_POA( ) operation.
If no IdAssignmentPolicy object is passed to the create_POA( ) operation, the default value used is SYSTEM_ID.
enum IdAssignmentPolicyValue
{
USER_ID,
SYSTEM_ID
};
interface IdAssignmentPolicy : CORBA::Policy
{
readonly attribute IdAssignmentPolicyValue value;
};
|
USER_IDSYSTEM_IDUse this policy to specify whether the POA must retain the associations between servants and CORBA objects or whether it should establish a new association for each new request.
To create an object that uses the ServantRetentionPolicy interface, call the POA::create_servant_retention_policy( ) operation. The result is passed to the POA::create_POA( ) operation.
If no ServantRetentionPolicy object is passed to the create_POA( ) operation, the default value used is RETAIN.
enum ServantRetentionPolicyValue
{
RETAIN,
NON_RETAIN
};
interface ServantRetentionPolicy : CORBA::Policy
{
readonly attribute ServantRetentionPolicyValue value;
};
|
RETAINNON_RETAINUse this policy to specify how the POA must process a request.
To create an object that uses the RequestProcessingPolicy interface, call the POA::create_request_processing_policy( ) operation. The result is passed to the POA::create_POA( ) operation.
If no RequestProcessingPolicy object is passed to the create_POA( ) operation, the default value used is USE_ACTIVE_OBJECT_MAP_ONLY.
enum RequestProcessingPolicyValue
{
USE_ACTIVE_OBJECT_MAP_ONLY,
USE_DEFAULT_SERVANT,
USE_SERVANT_MANAGER
};
interface RequestProcessingPolicy : CORBA::Policy
{
readonly attribute RequestProcessingPolicyValue value;
};
|
USE_ACTIVE_OBJECT_MAP_ONLYUSE_DEFAULT_SERVANTUSE_SERVANT_MANAGERUse this policy to request implicit servant activation.
To create an object that uses the ImplicitActivationPolicy interface, call POA::create_implicit_activation_policy( ) operation. The result is passed to POA::create_POA( ) operation.
If no ImplicitActivationPolicy object is passed to the create_POA( ) operation, the default value used is NO_IMPLICIT_ACTIVATION.
enum ImplicitActivationPolicyValue
{
IMPLICIT_ACTIVATION,
NO_IMPLICIT_ACTIVATION
};
interface ImplicitActivationPolicy : CORBA::Policy
{
readonly attribute ImplicitActivationPolicyValue value;
};
|
IMPLICIT_ACTIVATIONImplicit activation is supported by the POA.
Implicit activation allows the POA to automatically activate a servant (that is, create an entry for it in the Active Object Map) under the following circumstances:_this( ) is called but the servant is not (yet) active._this( ), the POA used is the one returned by the servant's default_POA( ) call.
servant_to_reference( ) is called and the servant is active.NO_IMPLICIT_ACTIVATIONThe PortableServer::StatePolicy is a proprietary policy that that you can use to let stateless objects co-exist with persistent stateful objects in a server pool process. (Previous to this policy, a persistent object in a server pool process was assumed to be stateless; it had to read and publish the TS/MP profile in its IOR.)
A stateful object can retain state after a method invocation (for example, the object might store data in memory that is associated with the method invocation). With stateful objects, it is imperative that a client's object reference address the specific instance of that object.
A stateless object does not retain state between method invocations. A client reference can address any of a set of instances.
The State policy has two values: STATEFUL and STATELESS. The default value is dependent on the value of the LifeSpan policy. If LifeSpanPolicy is TRANSIENT, StatePolicy defaults to STATEFUL. Otherwise, LifeSpanPolicy is PERSISTENT and StatePolicy defaults to STATELESS.
This section also provides the following subtopic:
For the client to communicate with the server regarding a request, the client and the server must each know the identity of the object being used. Ensure this by using an object reference that is created by the server and communicated to the client.
The object reference provides all the necessary information for the ORB to uniquely identify the object, the POA, and the server that are being used in the client's request.
References can be created by the server in the following ways:
These operations only create the object reference, thereby bringing the object into existence. They do not associate the object with an active servant.
To map the servant to the corresponding reference, the application can use the servant_to_reference( ) or the id_to_reference( ) operation.
The reference for this object can be obtained from the POA::servant_to_reference( )
operation with an inactive servant. The reference can also be obtained by the _this( ) operation.
Once the server creates the object reference, the object reference can be made available to the client through the following mechanisms:
ORB::string_to_object( ) operation. In this case, the client should then use the ORB::string_to_object( ) operation. See the discussion in Object References topic.
The classic example is a factory method. The IOR of the factory object is stored in the Naming Service and clients then invoke a create( ) method on the factory that returns a new object reference.
This section contains the following subtopics:
A servant manager is an object derived from the ServantManager interface. This object is registered with the POA as a callback object. The callback object helps to provide on-demand activation of servants. Two subclasses are derived from ServantManager: Servant Locator and Servant Activator.
The servant manager:
When the POA receives a request for an inactive object (for example, the RETAIN policy is being used and there is no ObjectId entry for the object in the AOM), the servant manager is called to activate the servant associated with the object. If the object cannot be located, the POA returns the OBJECT_NOT_EXIST system exception to the client. It is the client's responsibility to handle OBJECT_NOT_EXIST appropriately. It is the server's responsibility to determine that the object it requests exists.
Note: Not every application requires a servant manager.
The following types of applications do not require a servant manager
The POA can invoke a servant manager if the Request Processing policy value is set to USE_SERVANT_MANAGER. The servant manager that is used depends on the following conditions:
NON_RETAIN policy value, go immediately to ServantLocator.
RETAIN policy value is used, look for it in the Active Object Map (AOM).
A server application can be designed so that it requires the POA to activate objects by invoking a user-defined servant manager. The user-defined servant manager must be registered with the POA. The application must call the set_servant_manager( ) method to register its servant manager.
The servant manager implements a callback interface capable of activating persistent or transient objects. The callback interface contains operations that find, return, and deactivate the desired servant. Selecting the appropriate servant manager depends on the POA policies that the application uses.
The servant manager must be local to the process that contains the POA objects with which it is registered.
See the topic Servant Manager Implementation for implementation details.
The application can use a single servant to implement all of its objects. By setting the Request Processing policy value to USE_DEFAULT_SERVANT, the server application requests the POA to invoke a user-defined servant. The application must call the POA's set_servant( ) operation to register the user-defined servant.
If the POA does not have a servant associated with the ObjectId of the target object in the Active Object Map, or if the NON_RETAIN policy is in use for this POA, and the application has registered a default servant with the POA, the request is processed by the default servant. If there isn't a registered default servant, the OBJ_ADAPTER exception is thrown. See the discussion in Request Processing Policy topic for details.
Using the default servant is best suited for applications that provide a Dynamic Skeleton Interface (DSI) or have the correct type for the request. A DSI server application does not require static skeletons for each object.
If the server application is not a DSI type, the default servant can be used only with a single IDL interface.
A servant manager object is derived from the ServantLocator interface (simply referred to as a Locator). The Locator is used when the application needs control over every method invocation on an object.
The callback object derived from ServantLocator interface uses the preinvoke( ) and postinvoke( ) operations to activate and deactivate servants, respectively. See the ServantLocator Declarations topic for details.
The preinvoke( ) operation can be implemented with any of the following possibilities.
new operator to create a servant.
ObjectId to create a servant specific to this task.
The postinvoke( ) operation is called when the servant completes a request. The operation should be implemented to release or free any resources allocated by preinvoke( ).
Use this servant manager with the following policies:
| Policy Type | Policy Value | Description |
|---|---|---|
| Servant Retention | NON_RETAIN | Servants are released after they are used. Requires use of a servant manager. |
| Request Processing | USE_SERVANT_MANAGER | Directs the POA to use a servant manager that must be registered via set_servant_manager( ). |
A servant manager object is derived from ServantActivator interface (referred to as an Activator). The Activator is used when an object reference is uniquely associated with a particular servant.
The callback object derived from ServantActivator interface uses the incarnate( ) and etherealize( ) operations to activate and deactivate servants, respectively. Therefore, the POA is said to incarnate (activate) or etherealize (deactivate) servants by calling the Activator. See the ServantActivator Declarations topic for details.
The incarnate( ) operation can be implemented with the following capabilities:
ObjectId parameter as an input.
UNIQUE_ID is not used, the operation can return an existing servant.
After the POA calls the Activator's incarnate( ) operation, the servant returned by the Activator is retained in the POA's AOM.
Note: If the POA has the UNIQUE_ID value in the Id Uniqueness Policy, the servant must be unique for that Object Id.
The etherealize( ) operation is invoked whenever a servant is to be deactivated. An attempt to etherealize a servant that is not known to the POA can lead to undefined behavior.
Use this servant manager with the following policies:
| Policy Type | Policy Value | Description |
|---|---|---|
| Servant Retention | RETAIN | Servants are retained in the Active Object Map (AOM) after they are used. |
| Request Processing | USE_SERVANT_MANAGER | When the RETAIN policy is being used, the POA looks for the servant's Object Id in the AOM. If the object cannot be identified through the AOM, the POA invokes the servant manager. |
Use this servant manager with NON_RETAIN and USE_SERVANT_MANAGER policies.
These declarations are contained in servantmanager.h header file:
#include "nsdorb/poa.h"
class My_Locator : public virtual PortableServer::ServantLocator
{
public:
My_Locator() {}
~My_Locator() {}
PortableServer::Servant preinvoke(
const PortableServer::ObjectId& oid,
PortableServer::POA_ptr adapter,
const char * operation,
void *& the_cookie,
CORBA::Environment & _env);
void postinvoke(
const PortableServer::ObjectId& oid,
PortableServer::POA_ptr adapter,
const char * operation,
void * the_cookie,
PortableServer::Servant the_servant,
CORBA::Environment & _env);
};
|
Use this servant manager with RETAIN and USE_SERVANT_MANAGER policies.
These declarations are contained in servantmanager.h header file.
class My_Activator : public virtual PortableServer::ServantActivator
{
public:
My_Activator() {}
~My_Activator() {}
PortableServer::Servant incarnate(
const PortableServer::ObjectId& oid,
PortableServer::POA_ptr adapter,
CORBA::Environment &_env);
void etherealize(
const PortableServer::ObjectId& oid,
PortableServer::POA_ptr adapter,
PortableServer::Servant serv,
CORBA::Boolean cleanup_in_progress,
CORBA::Boolean remaining_activations,
CORBA::Environment &_env);
};
|
These declarations are contained in servantmanager.cpp source file:
#include "servantmanager.h"
#include "myservant.h" // class definition for My_Servant, not supplied
#include "myfactory.h" // class definition for My_Factory, not supplied
My_Factory gv_my_factory; // used by My_Activator::incarnate
CORBA::Object_ptr My_Locator::init(PortableServer::POA_ptr pp_POA)
{
// Application dependent initialization can be implemented here.
}
PortableServer::Servant My_Locator::preinvoke(
const PortableServer::ObjectId& pr_oid,
PortableServer::POA_ptr ,
const char * ,
void *& ,
CORBA::Environment & )
{
return new My_Servant;
}
void My_Locator::postinvoke(
const PortableServer::ObjectId& ,
PortableServer::POA_ptr ,
const char * ,
void * ,
PortableServer::Servant pp_servant,
CORBA::Environment & )
{
delete pp_servant;
}
// Create a new servant for use by the POA, to be stored in the
// POA's active object map (AOM).
// This example assumes a factory that returns a new servant
// given the Object Id as an input.
PortableServer::Servant My_Activator::incarnate(
const PortableServer::ObjectId& oid,
PortableServer::POA_ptr adapter,
CORBA::Environment &_env)
{
return gv_my_factory->make_servant( oid );
}
// Delete the servant from the POA's active object map.
// If the servant is not being shared by other POAs and
// the fifth parameter of the call is false
// (remaining_activations) then the servant can be deleted.
void My_Activator::etherealize(
const PortableServer::ObjectId &pr_oid,
PortableServer::POA_ptr pp_adapter,
PortableServer::Servant pp_servant,
CORBA::Boolean ,
CORBA::Boolean pv_remaining_activations,
CORBA::Environment &)
{
if ( ! pv_remaining_activations )
delete pp_servant;
}
|
This section contains the following subtopics:
By default, the lifespan of objects is determined by the server process under which they are invoked. Such objects are said to have a transient lifespan. The default behavior of a CORBA-compliant ORB such as NonStop DOM is to remove from the server memory the object references for transient objects. Any clients that attempt to invoke the object by using the old object reference after the process has terminated cause NonStop DOM to raise the CORBA::OBJECT_NOT_EXIST exception.
The default behavior relieves the ORB from an obligation to maintain a persistent state. It is the application's responsibility to request that the POA create persistent objects and track such objects until such time as the application specifies that they should be released from the server process.
The POA provides the following support for transient objects:
A persistent object is one for which the object reference remains valid after the server process has terminated. Persistent, stateless objects implement an application logic paradigm in which method invocations directed to the same object can result in requests to different servants residing in different processes in a server pool.
Persistent objects are the key to NonStop DOM scalability. Such objects are said to be stateless because, typically, the object state resides on disk (hence persistent) and not within the servant or process memory (hence the servant is stateless).
An application can request persistent objects by setting the Lifespan Policy value to PERSISTENT for the POA that creates the object reference and by enabling the NonStop TS/MP protocol in the server.
The NonStop DOM POA provides the following support for persistent objects:
An application that must have scalable persistent objects should enable the NonStop TS/MP protocol. The following is an example of a config entry that enables the TS/MP protocol is the Bank sample which is included in the NonStop DOM distribution. The server uses this config entity:
entity bank_server_pool@ORB {
tcp_server true
use_comm_server true
tsmp_server true
pathmon $smon
server_class bank-server
tsmp_client true
fs_client true
tcp_client true
}
|
The key items here are the following.
tsmp_server is set to true
pathmon name for the server pool is given
This subtopic describes the steps required to modify the Stock example to create persistent objects. You should be familiar with the following:
The ordered steps required to implement an application that uses persistent objects include all of the following (the complete implementation is shown in the Example Implementation of POA Server for Persistent Objects subtopic):
create_lifespan_policy( PortableServer::LifespanPolicy::PERSISTENT);create_id_assignment_policy( PortableServer::IdAssignmentPolicy::USER_ID);
All policies are stored in the Policy List. See also the discussion in the subtopic Persistent Object With System Id.
create_POA( ) on the parent POA.
create_POA("my_persistent_POA", my_poa_mgr, my_policies);
The actual arguments passed, in order, to the create_POA( ) operation specify the following:
string_to_ObjectId( ) method with a character string as shown:
PortableServer::ObjectId_var oid =
string_to_ObjectId( "myObjId");
activate_object_with_id( ) causes the POA to register the object and the servant in the Active Object Map. The call is as shown:
myPOA -> activate_object_with_id( oid, &lp_servant);
If the application uses a POA for persistent objects but does not provide an Object Id, the default Id Assignment Policy value is used. That default value is SYSTEM_ID. The POA assigns Object Ids to objects it creates. When this policy is used and the PERSISTENT policy is also in effect, the assigned Object Ids must be unique for all instances of this POA.
When the application calls the create_reference( ) method, the POA picks a unique Object Id. This is done by looking in the configuration database for a special POA entry (essentially, this is a 64-bit number). The POA chooses an unused number and updates the value in the configuration database. The number will never be reused.
Note: If the configuration database is wiped out and reinitialized, the numbers will start at zero again and be reused. This scenario is a violation of the required properties.
It is the user's responsibility to store all persistent data associated with the persistent Object Id.
This example shows how to modify the Stock Example so that it uses persistent objects.
#include "stock.h"
#include "nsdorb/poa.h"
int main(int argc, char *argv[])
{
// Initialize the ORB
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
// Get object reference for root POA in the process
CORBA::Object_var pfobj =
orb -> resolve_initial_references("RootPOA");
PortableServer::POA_var myPOA;
myPOA = PortableServer::POA::_narrow(pfobj);
// Create the POA policies
CORBA::PolicyList my_policies(2);
my_policies.length(2);
my_policies[0] =
myPOA -> create_lifespan_policy(
PortableServer::LifespanPolicy::PERSISTENT);
my_policies[1] =
myPOA -> create_id_assignment_policy(
PortableServer::IdAssignmentPolicy::USER_ID);
// Create a POA for persistent objects
PortableServer::POAManager_var my_poa_mgr = my_POA;
myPOA -> POAManager();
// Since we won't need the POA object that we used to
// store the root POA defaults, it can be overwritten now.
// myPOA will be a different object now, initialized
// with our specifications
myPOA = myPOA -> create_POA(
"my_persistent_POA",
my_poa_mgr,
my_policies);
// Create servant
Stock_impl *lp_servant = new Stock_impl;
// Convert a string to an Object Id
PortableServer::ObjectId_var oid =
string_to_ObjectId( "myObjId");
// Explicitly register the servant with the POA
myPOA -> activate_object_with_id( oid, &lp_servant);
myPOA -> obj = create_reference_with_id( oid, "IDL::Stock:1.0");
delete oid;
// Activate the POA
myPOA -> the_POAManager() -> activate();
// Service requests
orb -> run();
return 0;
} // main
|
This section contains the following subtopics:
An Adapter Activator can be used to create child POAs as required by the application. The Adapter Activator is an object derived from the PortableServer::AdapterActivator interface.
The Adapter Activator enables an existing POA to create a child POA as a result of one of the following actions:
find_POA( ) operation is invoked and its activate_it parameter value is TRUE.
find_POA( ) operation is successful, the operation returns a POA.
AdapterNonExistent exception.
Note: Not every application requires an Adapter Activator.
The following types of applications do not require implementation of the Adapter Activator:
create_POA( ) operation to explicitly create the required POAs
The POA must be active to call an Adapter Activator.
When a POA calls an Adapter Activator, all requests are queued for the POA being created (and for any of its descendant POAs). The queued requests are serviced only after the Adapter Activator creates the child POA. If the Adapter Activator fails to create a POA, the initial request results in the OBJECT_NOT_EXIST exception. Queued requests are retried.
The Adapter Activator must be local to the process that contains the POA objects with which it is registered.
The Adapter Activator must be associated with its POA. See also the topic Adapter Activator Association topic for details.
This section contains the following subtopics:
The NonStop DOM ORB invokes the unknown_adapter( ) on the registered Adapter Activator whenever the ORB receives a request for a target POA that does not exist. If the ORB receives requests for numerous nonexistent POAs, the operation is invoked separately for each required POA. The unknown_adapter( ) operation is associated with the parent POA that requests a child POA. The implementation of unknown_adapter( ) can be tailored so that the child POA is created with characteristics specified by its policies.
#ifndef _ADAPTER_H_
#define _ADAPTER_H_
#include "nsdorb/poaclass.h"
// Well-known name of the POA that this adapter will 'activate'
#define GrandChildPOA "RetainBat"
// Example class for an application's Adapter Activator.
class My_Adapter : public virtual PortableServer::AdapterActivator
{
public:
My_Adapter() { }
~My_Adapter() { }
CORBA::Boolean unknown_adapter( PortableServer::POA_ptr parent,
const char* name,
CORBA::Environment &_env);
};
#endif
|
This implementation of unknown_adapter( ) allows the calling POA to create another POA. The name of the POA that gets created is specified in the <pp_name> argument. See also the topic Adapter Declarations topic for details.
This implementation creates a child POA with the following characteristics.
In addition to the characteristics above, the operation also has the following default policy values applied to the child POA:
See the topic ServantActivator Declarations for the details on My_Activator.
#include "adapter.h"
#include "servantmanager.h"
My_Activator gv_activator; // Servant Activator
CORBA::Boolean
My_Adapter::unknown_adapter( PortableServer::POA_ptr pp_parent,
const char *pp_name,
CORBA::Environment &pr_env)
{
NSDOMAssert( pr_env.ok() );
if (strcmp(pp_name, GrandChildPOA) != 0)
return false; // don't create if incorrect name
// Set the Request Processing Policy for servant manager
PortableServer::RequestProcessingPolicy_ptr lp_request_po =
pp_parent->create_request_processing_policy(
PortableServer::USE_SERVANT_MANAGER, pr_env);
// Set the Id Assignment Policy value for user id
PortableServer::IdAssignmentPolicy_ptr lp_assignment_po =
pp_parent->create_id_assignment_policy(
PortableServer::USER_ID, pr_env);
// Set the Lifespan Policy for persistent objects
PortableServer::LifespanPolicy_ptr lp_lifespan_po =
pp_parent->create_lifespan_policy(
PortableServer::PERSISTENT, pr_env);
// Create policy list
// Note: List 'owns' policy objects and will release them
CORBA::PolicyList lv_policies(3);
lv_policies.length(3); // must set length before any access is allowed.
lv_policies[0] = lp_request_po;
lv_policies[1] = lp_assignment_po;
lv_policies[2] = lp_lifespan_po;
PortableServer::POA_ptr lp_child_POA =
pp_parent->create_POA(pp_name,
pp_parent->the_POAManager(),
&lv_policies,
pr_env);
NSDOMAssert( pr_env.ok() );
NSDOMAssert( lp_child_POA );
// Register the servant manager for use with the child POA
lp_child_POA->set_servant_manager( &gv_activator, pr_env );
return true;
}
|
The Adapter Activator must be associated with its POA. This example uses the_activator to identify the Adapter Activator that my_poa will use when creating a child POA.
// A POA my_poa can register its Adapter Activator as follows
int main()
{
PortableServer::AdapterActivator_ptr my_adapter = new My_Adapter;
my_poa->the_activator( my_adapter );
}
|