The Server The Launch and Client Code

_in = _invoke _out; } catch org.omg.CORBA.portable.ApplicationException _ex { _in = _ex.getInputStream ; String _id = _ex.getId ; if _id.equals IDL:com.ora.rmibook.chapter23.corbaaccounts + NegativeAmountException:1.0 throw NegativeAmountExceptionHelper.read _in; else if _id.equals IDL:com.ora.rmibook.chapter23.corbaaccounts + OverdraftException:1.0 throw OverdraftExceptionHelper.read _in; else throw new org.omg.CORBA.MARSHAL _id; } catch org.omg.CORBA.portable.RemarshalException _rm { makeWithdrawal amount; } finally { _releaseReply _in; } } makeWithdrawal the C++ version of the stub contains: void Account::makeWithdrawal const Money _amount { CORBA_MarshalInBuffer_var _ibuf; CORBA::MarshalOutBuffer_var _obuf; while 1 { _obuf = __ _root- _create_requestmakeWithdrawal, 1, 627418; VISostream _ostrm = VISostream CORBA::MarshalOutBuffer_obuf; _ostrm _amount; try { _ibuf = __ _root-_invoke_obuf; } catch const CORBA::TRANSIENT { continue; } break; } } Its not really all that different.

23.2.3 The Server

Lets briefly look at the code for an account server. Heres a simple implementation: package com.ora.rmibook.chapter23.corbaaccounts; public class Account_Impl extends _AccountImplBase { private Money _balance; public Account_ImplMoney startingBalance { _balance = startingBalance; } public Money getBalance { return _balance; } public void makeDepositMoney amount throws NegativeAmountException { checkForNegativeAmountamount; _balance.cents += amount.cents; return; } public void makeWithdrawalMoney amount throws NegativeAmountException, OverdraftException { checkForNegativeAmountamount; checkForOverdraftamount; _balance.cents -= amount.cents; return; } private void checkForNegativeAmountMoney amount throws NegativeAmountException { int cents = amount.cents; if 0 cents { throw new NegativeAmountException ; } } private void checkForOverdraftMoney amount throws OverdraftException { if amount.cents _balance.cents { throw new OverdraftException ; } return; } } This is a simple server, equivalent to the one we built for RMI back in Chapt er 9 , but its worth looking at anyway. The main reason for doing so is that most of the server code is identical to the RMI version. CORBA involves writing interfaces in IDL, and it automatically generates value objects. However, once you get past the IDL, much of the code is the same. If you can build an RMI system, you can build a CORBA system.

23.2.4 The Launch and Client Code

The launch and client code should also feel familiar. Finding a CORBA naming service is a little harder than finding an RMI registry but not harder than finding a JNDI naming context. However, the basic code and the overall structure of the application are the same. Here, for example, is our launch code: public class ImplLauncher { public static void mainString[] args { Collection nameBalancePairs = getNameBalancePairsargs; Iterator i = nameBalancePairs.iterator ; whilei.hasNext { NameBalancePair nextNameBalancePair = NameBalancePair i.next ; launchServernextNameBalancePair; } new JFrameDispatcher Server.show ; hack to keep JVM alive because JavaIDL uses Daemon threads } private static void launchServerNameBalancePair serverDescription { try { Account_Impl newAccount = new Account_ImplserverDescription.balance; OrbSetup.bindAccountServerserverDescription.name, newAccount; System.out.printlnAccount + serverDescription.name + successfully launched.; } catchException e{ e.printStackTrace ;} } .... } This is exactly parallel to the RMI launch code. The only difference is that weve added another class, OrbSetup , to handle the details of connecting to the CORBA naming service. Heres the entirety of that class: public class OrbSetup { private static Properties _properties; private static Properties getProperties { if null==_properties { _properties = new Properties ; _properties.putorg.omg.CORBA.ORBInitialPort, 3500; _properties.putorg.omg.CORBA.ORBInitialHost, localhost; } return _properties; } public static Account getAccountString name { try { Properties properties = OrbSetup.getProperties ; ORB orb = ORB.initString[] null, properties; org.omg.CORBA.Object objRef = orb. resolve_initial_referencesNameService; NamingContext nameServer = NamingContextHelper.narrowobjRef; NameComponent ourComponent = new NameComponentname, ; NameComponent path[] = {ourComponent}; org.omg.CORBA.Object accountRef = nameServer.resolvepath; return AccountHelper.narrowaccountRef; } catch Exception e { e.printStackTrace ; } return null; } public static void bindAccountServerString name, Account server throws Exception { Properties properties = OrbSetup.getProperties ; ORB orb = ORB.initString[] null, properties; orb.connectserver; This is pretty much a JavaIDL hack JavaIDL doesnt really support servers well org.omg.CORBA.Object objRef = orb.resolve_initial_referencesNameService; NamingContext nameServer = NamingContextHelper.narrowobjRef; NameComponent ourComponent = new NameComponentname, ; NameComponent path[] = {ourComponent}; nameServer.rebindpath, server; } } The client code changes in a similar way. By using the OrbSetup class, weve isolated the changes in the client application to a couple of lines in BankClientFrame s getAccount method. It changes from: private void getAccount { try { _account = AccountNaming.lookup_accountNameField.getText ; } catch Exception e { System.out.printlnCouldnt find account. Error was \n + e; e.printStackTrace ; } return; } to: private void getAccount { try { _account = OrbSetup.getAccount_accountNameField.getText ; } catch Exception e { System.out.printlnCouldnt find account. Error was \n + e; e.printStackTrace ; } return; }

23.3 A Quick Comparison of CORBA and RMI