CORBA: Servant Invocation with the POA

 

 

In the CORBA examples so far you explicitly activated instances of your servant and then created an object reference to that servant instance:

 

Account_impl* server = new Account_impl ;

CORBA::String_var ref = orb->object_to_string(server) ;

 

But this is not a very efficient or flexible way of managing servants in situations where there are many thousands of object instances (for example a bank server has many thousands of accounts to manage). Ideally we would activate only those account objects that actually receive requests. Also we might want to persist the state of an object beyond the lifetime of the server. To achieve this we need to separate the lifecycle of a CORBA Object, which has a unique id and possibly persistent state, from the lifecycle of the servant, which is the code that implements an interface. To improve scalability a single servant could incarnate one or more CORBA objects during its lifetime. To achieve persistence, a CORBA Object could be incarnated by more than one servant in its lifetime.  The POA (Portable Object Adapter) API is the CORBA solution to separating servants and objects.  In this class you will build a bank server that activates accounts using the POA. We will use the java J2SE 1.4 CORBA implementation:

 

 

1. Generate client and server stubs from idl:

Copy the bank.idl file from the following directory:

 

http://www.cs.ucl.ac.uk/staff/w.emmerich/lectures/Z23-04-05/poa/sample/bank.idl

 

or copy from Unix shell:

 

cp /cs/research/sse/home1/rigel/ucacwxe/public_html/lectures/Z23-04-05/poa/sample/bank/bank.idl .

 

Make sure you understand the interface definitions before continuing. Now generate the client and server stubs using the jdk idl comipiler:

 

idlj –fall bank.idl

 

A subdirectory called “bank” is created. In this directory you will find all the stubs and skeletons needed to create the bank server. Change to this as your working directory:

 

cd bank

 

2. Copy over the “AccountImpl.java” servant code. This is a fairly straightforward implementation of the Account interface.

 

3. Create an Account Servant Manager by extending org.omg.PortableServer.ServantActivatorPOA implementing the etherealize and incarnate methods. The incarnate method should return Account servant instances.

 

4. Create a class for the BankServer

 

The BankServer code should create 2 POAs. One to manage the bank object and one to manage the account objects.

 

1.     Get a reference to the root POA using the ORB “resolve_ initial_references” method:

 

ORB orb = ORB.init(args, null);

POA rootPOA = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));

 

 

2.     Next create the BankPOA defining a number of policies that determine various aspects of the POA’s behaviour.

a.     Set the lifespan policy to TRANSIENT. (Objects activated by a POA with a transient lifespan policy cannot outlive the server process. Objects activated by a POA with a persistent lifespan policy can outlive the server process).  

b.     The Request Processing Policy determines how the POA associates an object id in the request with a servant implementation. Set this to the constant USE_ACTIVE_OBJECT_MAP_ONLY, which means the object reference is looked up in a special lookup table maintained by the POA called the “Active Object Map” (AOM).

c.     The Servant Retention policy determines whether the POA maintains a map of active servants (RETAIN) or not (NON_RETAIN).

3.     Create the AccountPOA with a Request Process Policy that delegates the location and incarnation of servants to the Servant Manager.

4.     Create a servant and an object ID for the Bank Object. Hint:

byte[] objectID = new String("CORBABank").getBytes();

 

5.     Activate the object using the POA “activate_object_with_id” method.

6.     Obtain an object reference using the create_reference_with_id and bind it to root context of naming service under the name “BankServer”:

 

org.omg.CORBA.Object objRef =  

              orb.resolve_initial_references("NameService");

      NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);

 

      String name = "BankServer";

      NameComponent path[] = ncRef.to_name( name );

      ncRef.rebind(path, bref);

 

7.     Start the POA’s and run the orb

  

// Start the POAs

      accountPOA.the_POAManager().activate();

      bankPOA.the_POAManager().activate();

      rootPOA.the_POAManager().activate();

 

      // Ready, Set, and Go...

      System.out.println("BankServer ready and waiting ...");

 

      // wait for invocations from clients

      orb.run();

 

 

 

5. Now copy the Bank servant  (BankImpl.java) and examine the “openAccount” method.  The line below shows the AccountPOA creating a new reference for an account object with an ID based on the user generated account number for the account.

 

Account theAccount =

AccountHelper.narrow(accountPOA.create_reference_with_id(accNum.getBytes(),"IDL:bank/Account:1.0"));

 

It is important to understand that although an object reference exists it has not yet been associated with a servant. This will only happen when and if a client actually tries to use the reference.

 

6. You need to copy the “DBUtils.java” which provides methods for creating and accessing account information from a simple file database. Finally copy the test directory which contains some example client code.

 

http://www.cs.ucl.ac.uk/staff/w.emmerich/lectures/Z23-04-05/poa/sample/bank/test

 

cp –R /cs/research/sse/home1/rigel/ucacwxe/public_html/lectures/Z23-04-05/poa/sample/bank/test .

 

 

5. Compile your sources: Go to the parent of the directory where you copied the .java files to:

 

cd ..

 

Create a new directory called “classes” and then compile as follows:

 

javac -d ./classes bank/*.java bank/test/*.java

 

 

6. Running the example:

 

  1. start the naming service:

orbd -ORBInitialPort 1050 -ORBInitialHost localhost

  1. start the BankServer:

java -cp ./classes bank.BankServer -ORBInitialPort 1050 -ORBInitialHost localhost

3. Run the client:

java -cp ./classes bank.test.BankClient -ORBInitialPort 1050 -ORBInitialHost localhost

 

Rerun the client a few times. Each time the client is run two new account objects are created. In the server standard output we see that the Account Servant Activator is accessed twice for each openAccount call.

 

The “find accounts” query is then executed selecting already existing accounts of type “saving”. But the Account Servant Activator is not accessed since active servants matching these references are found in the Account POA Active Object Map. (Review the USE_SERVANT_MANAGER policy if this does not make sense).  Now stop the server process (Control-C) and restart it. Run the client again. This time the Account Servant Activator was accessed not just for the two new accounts, but also for the existing accounts of type saving. The next time you run the client, what do you expect to happen? Try it and see if you were right.

 

 

Shutdown the naming service (Control-C) and remove the files “bankaccounts”, “temp” and (with –r option) the directory orb-db.

 

Now change the server code so that the Bank- and Account- POA use a persistent lifespan policy. Recompile and restart the naming service (orbd). The J2SE 1.4 CORBA implementation specifies that persistent servers must be registered and activated indirectly using the “servertool” utility. Start the servertool utility specifying the port and host of the orbd naming service:

 

 

servertool orbd -ORBInitialPort 1050 -ORBInitialHost localhost

 

 

Welcome to the Java IDL Server Tool

please enter commands at the prompt

 

 

Now register the BankServer using the “register” command as follows:

 

 

servertool > register -server bank.BankServer -applicationName BankServer -classpath ./classes -args -ORBInitialPort 1050 -ORBInitialHost localhost

 

        server registered (serverid = 257).

 

 

Check the server was registered:

 

servertool > list

 

        Server Id       Server Class Name               Server Application

        ---------       -----------------               ------------------

 

           257          bank.BankServer         BankServer

 

 

Run the client to check that the server functions as before. Now to demonstrate that this persistent server really does outlive the server process shutdown the BankServer with the “shutdown” command. Check the shutdown worked by running the “listactive” command.

 

servertool > shutdown -serverid 257

 

        server sucessfully shutdown.

 

servertool > listactive

 

 

        Server Id       Server Class Name               Server Application

        ---------       -----------------               ------------------

 

 

Now rerun the client. Because the server is persistent the servant manager transparently restarts the server when the client makes a request. To check the server is active again retype the “listactive” command: