Bank Application

The bank application demostrates creating POAs for transient and persistent objects, with user assigned Object Ids.

1 Bank Interface in IDL

The poaBank module contains two interfaces - Account, and Bank. The Account has methods for depositing, withdrawing, and checking balance. The Bank just method for getting an Account object for the given account number.
module poaBank
{
    interface Account 
    {
    |   exception InsufficientFunds {};
    |                                                                      
    |   float deposit(in float sum);
    |                                                                      
    |   float withdraw(in float sum) raises (InsufficientFunds);
    |                                                                      
    |   readonly attribute float balance;
    };
                                                                           
    interface Bank
    {
    |   exception noSuchAccount {};
    |                                                                      
    |   Account getAccount(in long accountNum) raises (noSuchAccount);
    };
};

2 Bank Server

The bank server creates a POA with user assigned object Ids, and persistent object lifecycle policies. It then creates a bank object using "bank" as the object id.

If this is the first incarnation of the server, it publishes the bank object in the COS Namespace. The server checks the namespace to determine if it published the object last time. This demonstrates the persistence of the object reference. No matter how many times the server terminates and restarts the object reference remains valid.

package poaBank;
                                                                           
import util.Util;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Policy;
                                                                           
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContext;
import org.omg.CosNaming.NamingContextHelper;
import org.omg.CosNaming.NamingContextPackage.NotFound;
                                                                           
import org.omg.PortableServer.POA;
import org.omg.PortableServer.Servant;
import org.omg.PortableServer.LifespanPolicyValue;
import org.omg.PortableServer.IdAssignmentPolicyValue;
                                                                           
public class Server
{
    public static void main(String[] args)
    {
    |   try {
    |   |                                                                  
    |   |   // create the jBroker ORB
    |   |   ORB orb = ORB.init(args, null);
    |   |                                                                  
    |   |   // get the root POA
    |   |   POA rootPOA = (POA) orb.resolve_initial_references("RootPOA");
    |   |                                                                  
    |   |   // create a persistent user assigned ids POA
    |   |   POA bankPOA = rootPOA.create_POA("bankPOA", 
    |   |       rootPOA.the_POAManager(),
    |   |       new Policy[] {
    |   |       |   rootPOA.create_id_assignment_policy(
    |   |       |       IdAssignmentPolicyValue.USER_ID),
    |   |       |   rootPOA.create_lifespan_policy(
    |   |       |       LifespanPolicyValue.PERSISTENT)
    |   |       });
    |   |                                                                  
    |   |   // create and activate the bank servant
    |   |   Servant bank = new BankImpl(bankPOA, args[0]);
    |   |   bankPOA.activate_object_with_id("bank".getBytes(), bank);
    |   |                                                                  
    |   |   // get the root of the NameService
    |   |   NamingContext root = NamingContextHelper.narrow(
    |   |       orb.resolve_initial_references("NameService"));
    |   |                                                                  
    |   |   // if not done before, publish the bank objref
    |   |   NameComponent nc = new NameComponent("bank", "");
    |   |   NameComponent[] name = new NameComponent[] { nc };
    |   |   try {
    |   |   |   root.resolve(name);
    |   |   } catch (NotFound ex) {
    |   |   |                                                              
    |   |   |   // create the bank objref
    |   |   |   Bank bankObj = BankHelper.narrow(bankPOA.
    |   |   |       create_reference_with_id("bank".getBytes(), 
    |   |   |           bank._all_interfaces(null, null)[0]));
    |   |   |                                                              
    |   |   |   System.out.println(orb.object_to_string(bankObj));
    |   |   |   root.rebind(name, bankObj);
    |   |   }
    |   |                                                                  
    |   |   // activate bankPOA
    |   |   bankPOA.the_POAManager().activate();
    |   |                                                                  
    |   |   // wait for invocations
    |   |   System.out.println("waiting for invocations ...");
    |   |   orb.run();
    |   |                                                                  
    |   } catch (Exception ex) {
    |   |   ex.printStackTrace();
    |   }
    }
}

3 Bank Implementation

This is the implementation of the Bank Object. It creates a transient object POA with user assigned Ids, pre-creates 10 Account objects, and saves them in a hashtable.
package poaBank;
                                                                           
import java.io.File;
import java.util.Hashtable;
                                                                           
import org.omg.CORBA.Policy;
                                                                           
import org.omg.PortableServer.POA;
import org.omg.PortableServer.Servant;
import org.omg.PortableServer.IdAssignmentPolicyValue;
                                                                           
import poaBank.BankPackage.noSuchAccount;
                                                                           
public class BankImpl extends BankPOA
{
    POA       _acctPOA;
    Hashtable _accounts;
                                                                           
    BankImpl(POA bankPOA, String dir) throws Exception
    {
    |   // make sure that the DB dir exists
    |   File dbDir = new File (dir);
    |   if (!dbDir.exists()) dbDir.mkdir();
    |                                                                      
    |   // create the POA for Transient Account Objects
    |   _acctPOA = bankPOA.create_POA("acctPOA", bankPOA.the_POAManager(),
    |       new Policy[] {
    |       |   bankPOA.create_id_assignment_policy(
    |       |       IdAssignmentPolicyValue.USER_ID)
    |       });
    |                                                                      
    |   // create the account objects
    |   _accounts = new Hashtable(19);
    |   byte objectId[] = new byte[1];
    |   for (int i=100; i < 110; i++) {
    |   |                                                                  
    |   |   // construct the object id for account
    |   |   objectId[0] = (byte) (i & 0xFF);
    |   |                                                                  
    |   |   // create a servant
    |   |   Servant servant = new AccountImpl(dbDir, i);
    |   |                                                                  
    |   |   // activate the object and get an object reference
    |   |   _acctPOA.activate_object_with_id(objectId, servant);
    |   |   Account account = AccountHelper.narrow(
    |   |       _acctPOA.create_reference_with_id(objectId, 
    |   |           servant._all_interfaces(null, null)[0]));
    |   |                                                                  
    |   |   // save the objref 
    |   |   _accounts.put(new Integer(i), account);
    |   }
    }
                                                                           
    public Account getAccount(int acctNum) throws noSuchAccount
    {
    |   Account account = (Account) _accounts.get(new Integer(acctNum));
    |                                                                      
    |   if (account == null) throw new noSuchAccount();
    |                                                                      
    |   return account;
    }
}

4 Account Implementation

The account implementation uses a file to maintain the account balance. Since multiple deposit and withdraw methods may be fired at the object at the same time, these methods are made synchronized.
package poaBank;
                                                                           
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
                                                                           
import org.omg.CORBA.PERSIST_STORE;
                                                                           
import poaBank.AccountPackage.InsufficientFunds;
                                                                           
public class AccountImpl extends AccountPOA
{
    float _balance;
    File  _acctDb;
                                                                           
    public AccountImpl() {}
                                                                           
    public AccountImpl(File dir, int i)
    {
    |   _acctDb = new File(dir, new Integer(i).toString());
    |   if (_acctDb.exists()) _balance = readBalance();
    }
                                                                           
    public synchronized float deposit(float sum)
    {
    |   _balance += sum;
    |                                                                      
    |   writeBalance();
    |                                                                      
    |   return _balance;
    }
                                                                           
    public synchronized float withdraw(float sum) throws InsufficientFunds
    {
    |   if ((_balance - sum) < 0) throw new InsufficientFunds();
    |                                                                      
    |   _balance -= sum;
    |                                                                      
    |   writeBalance();
    |                                                                      
    |   return _balance;
    }
                                                                           
    public synchronized float balance()
    {
    |   return _balance;
    }
                                                                           
    void writeBalance()
    {
    |   try {
    |   |   FileOutputStream fos = new FileOutputStream(_acctDb);
    |   |   ObjectOutputStream oos = new ObjectOutputStream(fos);
    |   |                                                                  
    |   |   oos.writeObject(new Float(_balance));
    |   |                                                                  
    |   |   oos.close();
    |   } catch (Exception ex) {
    |   |   throw new PERSIST_STORE();
    |   }
    }
                                                                           
    float readBalance()
    {
    |   try {
    |   |   FileInputStream fis = new FileInputStream(_acctDb);
    |   |   ObjectInputStream ois = new ObjectInputStream(fis);
    |   |                                                                  
    |   |   float balance = ((Float) ois.readObject()).floatValue();
    |   |                                                                  
    |   |   ois.close();
    |   |                                                                  
    |   |   return balance;
    |   } catch (Exception ex) {
    |   |   throw new PERSIST_STORE();
    |   }
    }
}

5 Register the Server

A server implementing persistent objects needs to be registered with the ORB. The ORB uses a server deployment descriptor to define a server. The server deployment descriptor can be expressed as a Java properties file.
server.main=poaBank.Server
server.alias=bank
server.classpath=c\:\\mp\\examples\\orb\\lib
server.args=c\:\\mp\\examples\\orb\\src\\poaBank\\db
Please see the
Server Activation section for details. Run `make deploy' to register the server.

6 Bank Client

The Bank application client gets the object reference of the Bank and presents a prompt to the user to do transactions on their choice of an Account object.
package poaBank;
                                                                           
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
                                                                           
import org.omg.CORBA.ORB;
                                                                           
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContext;
import org.omg.CosNaming.NamingContextHelper;
                                                                           
import poaBank.AccountPackage.InsufficientFunds;
                                                                           
public class Client
{
    ORB     _orb;
    Bank    _bank;
    Account _account;
                                                                           
    public static void main(String[] args)
    {
    |   try {
    |   |   new Client().run(args);
    |   } catch (Exception ex) {
    |   |   ex.printStackTrace();
    |   }
    }
                                                                           
    public void run(String[] args) throws Exception
    {
    |   // create the jBroker ORB
    |   _orb = ORB.init(args, null);
    |                                                                      
    |   // get the root of the NameService
    |   NamingContext root = NamingContextHelper.narrow(
    |       _orb.resolve_initial_references("NameService"));
    |                                                                      
    |   // get the bank object reference
    |   NameComponent nc = new NameComponent(args[0], "");
    |   NameComponent[] name = new NameComponent[] { nc };
    |   _bank = BankHelper.narrow(root.resolve(name));
    |                                                                      
    |   // enter the request processing loop
    |   processCommands();
    }
                                                                           
    void processCommands() throws Exception
    {
    |   // create a input stream reader
    |   BufferedReader reader = new BufferedReader(new InputStreamReader(
    |       System.in));
    |                                                                      
    |   // get the account number
    |   System.out.print("Enter Account number: ");
    |   System.out.flush();
    |   _account = _bank.getAccount(new Integer(reader.readLine()).intValue());
    |                                                                      
    |   // enter the read-execute loop
    |   while (true) {
    |   |   System.out.print("bank > ");
    |   |   executeCommand(readCommandLine(reader));
    |   }
    }
                                                                           
    void executeCommand(String[] command) throws Exception
    {
    |   if (command.length == 0) 
    |       printHelp();
    |                                                                      
    |   // get balance
    |   else if (command[0].equals("b"))
    |       System.out.println("\tbalance: $" + _account.balance());
    |                                                                      
    |   // check the command for addition parameter
    |   else if (command[0].equals("d")) {
    |   |   if (command.length != 2) printHelp();
    |   |   else System.out.println("\tbalance: $"+ _account.deposit(new Float(
    |   |       command[1]).floatValue()));
    |   }
    |                                                                      
    |   // deposit money
    |   else if (command[0].equals("w")) {
    |   |   if (command.length != 2) printHelp();
    |   |   else {
    |   |   |   try {
    |   |   |   |   System.out.println("\tbalance: $"+ _account.withdraw(
    |   |   |   |       new Float(command[1]).floatValue()));
    |   |   |   } catch (InsufficientFunds ex) {
    |   |   |   |   System.out.println("\tInsufficient Funds!");
    |   |   |   }
    |   |   }
    |   }
    |                                                                      
    |   // quit
    |   else if (command[0].equals("q")) {
    |   |   System.exit(0);
    |   }
    |                                                                      
    |   // print help
    |   else printHelp();
    }
                                                                           
    void printHelp()
    {
    |   System.out.println();
    |   System.out.println("\tCommands:");
    |   System.out.println("\t   b               // get balance");
    |   System.out.println("\t   d <sum>         // deposit sum");
    |   System.out.println("\t   w <sum>         // withdraw sum");
    |   System.out.println("\t   q               // quit");
    |   System.out.println();
    }
                                                                           
    String[] readCommandLine(BufferedReader reader) throws Exception
    {
    |   int i=0;
    |                                                                      
    |   String line = reader.readLine();
    |                                                                      
    |   if (line == null) System.exit(0);
    |                                                                      
    |   StringTokenizer tokenizer = new StringTokenizer(line);
    |   String[] command = new String[tokenizer.countTokens()];
    |   while (tokenizer.hasMoreTokens()) {
    |   |   command[i++] = tokenizer.nextToken();
    |   }
    |                                                                      
    |   return command;
    }
}
Run the client using `make runclient'.
Copyright © 2000-2003, Novell, Inc. All rights reserved.