Keywords: doc

Next: IDL Compiler Up: POA Previous: Example

## Using a Servant Manager

While the previous example did introduce the POA, it did not demonstrate any of its abilities - the example would have been just as simple using the BOA.

As a more complex example, we want to show a server that generates ``virtual'' object references that point to non-existent objects. We then provide the POA with a servant manager that incarnates the objects on demand.

We continue our series of ``Account'' examples. We provide the implementation for a Bank object with a single ``create'' operation that opens a new account. However, the Account object is not put into existence at that point, we just return a reference that will cause activation of an Account object when it is first accessed. This text will only show some code fragments; find the full code in the `demo/poa/account-2` directory.

The implementation of the Account object does not differ from before. More interesting is the implementation of the Bank's `create` operation:

      Account_ptr
      Bank_impl::create ()
      {
        CORBA::Object_var obj = mypoa->create_reference ("IDL:Account:1.0");
        Account_ptr aref = Account::_narrow (obj);
        assert (!CORBA::is_nil (aref));
        return aref;
      }

The `create_reference()` operation on the POA does not cause an activation to take place. It only creates a new object reference encapsulating information about the supported interface and a unique (system-generated) Object Id. This reference is then returned to the client.

Now, when the client invokes an operation on the returned reference, the POA will first search its Active Object Map, but will find no servant to serve the request. We therefore implement a servant manager, which will be asked to find an appropriate implementation.

There are two types of servant managers: a `Servant Activator` activates a new servant, which will be retained in the POA's Active Object Map to serve further requests on the same object. A `Servant Locator` is used to locate a servant for a single invocation only; the servant will not be retained for future use. The type of servant manager depends on the POA's Servant Retention policy.

In our case, we use a servant activator, which will incarnate and activate a new servant whenever the account is used first. Further operations on the same object reference will use the already active servant. Since the `create_reference()` operation uses a unique Object Id each time it is called, one new servant will be incarnated for each Account - this represents the BOA's Unshared activation mode.

A servant activator provides two operations, `incarnate` and `etherealize`. The former one is called when a new servant needs to be incarnated to serve a previously unknown Object Id. `etherealize` is called when the servant is deactivated (for example in POA shutdown) and allows the servant manager to clean up associated data.

      class AccountManager : public virtual POA_PortableServer::ServantActivator
      { /* declarations */ };

      PortableServer::Servant
      AccountManager::incarnate (/* params */)
      {
        return new Account_impl;
      }

      void
      AccountManager::etherealize (PortableServer::Servant serv,
                                   /* many more params */)
      {
        delete serv;
      }

Our servant activator implements the `POA_PortableServer::ServantActivator` interface. Since servant managers are servants themselves, they must be activated like any other servant (see below).

The `incarnate` operation has nothing to do but to create a new Account servant. `incarnate` receives the current POA and the requested Object Id as parameters, so it would be possible to perform special initialization based on the Object Id that is to be served.

`etherealize` is just as simple, and deletes the servant. In ``real life'', the servant manager would have to make sure that the servant is not in use anywhere else before deleting it. Here, this is guaranteed by our program logic.

The `main()` code is a little more extensive than before. Because the Root POA has the `USE_ACTIVE_OBJECT_MAP_ONLY` policy and does not allow a servant manager, we must create our own POA with the `USE_SERVANT_MANAGER` policy.

      CORBA::ORB_var orb = CORBA::ORB_init (argc, argv, "mico-local-orb");
      CORBA::Object_var poaobj = orb->resolve_initial_references ("RootPOA");
      PortableServer::POA_var poa = PortableServer::POA::_narrow (poaobj);
      PortableServer::POAManager_var mgr = poa->the_POAManager();

      CORBA::PolicyList pl;
      pl.length(1);
      pl[0] = poa->
        create_request_processing_policy (PortableServer::USE_SERVANT_MANAGER);
      PortableServer::POA_var mypoa = poa->create_POA ("MyPOA", mgr, pl);

Note that we use the Root POA's POA Manager when creating the new POA. This means that the POA Manager has now control over both POAs, and changing its state affects both POAs. If we passed `NULL` as the second parameter to `create_POA()`, a new POA Manager would have been created, and we would have to change both POA's states separately.

We can now register the servant manager.

      AccountManager * am = new AccountManager;
      PortableServer::ServantManager_var amref = am->_this ();
      mypoa->set_servant_manager (amref);

After creating an instance of our servant manager, we obtain an object reference using the inherited `_this()` method. This also implicitely activates the servant manager in the Root POA.

      Bank_impl * micocash = new Bank_impl (mypoa);
      PortableServer::ObjectId_var oid = poa->activate_object (micocash);
      mgr->activate ();
      orb->run();

Now the only thing left to do is to activate a Bank object, to change both POAs to the active state, and to enter the ORB's event loop.

Next: IDL Compiler Up: POA Previous: Example