The new account The launch code and the client

} public synchronized void serverNoLongerActiveString accountName throws RemoteException { _lockedaccountNames.removeaccountName; } private synchronized void checkLockString accountName throws LockedServerException { if null=_lockedaccountNames.getaccountName { throw new LockedServerExceptionaccountName; } return; } } Theres one important subtlety in how this works. Because the entire locking mechanism relies upon the Unreferenced interface, the factory can never store a stub on any account servers. If the factory held a stub to an account server, the factory would maintain a lease to the server and, therefore, unreferenced would never be called. Hence, the account would never be unlocked. This means that the protected method _getAccount actually needs to create the account servers or cause them to be created, when it is called. For now, well ignore this issue and simply hardwire the server creation code in a concrete subclass; the Activation Framework provides a convenient way to handle automatically launching servers. Heres the code for LockingAccountFactory_Impl , a concrete subclass of LockingFactory_Impl that simply creates accounts with random balances: public class LockingAccountFactory_Impl extends LockingFactory_Impl { public LockingAccountFactory_Impl throws RemoteException { } protected Remote _getAccountString accountName { try { Account returnValue = new Account_ImplgetRandomMoney , accountName; returnValue.setFactorythis; return returnValue; } catch Exception ignored { Creation of a local object should never fail} return null; } private Money getRandomMoney { int cents = int Math.random 100000; return new Moneycents; } }

17.4.2.2 The new account

Our new version of Account_Impl is one of the simpler implementations of Account weve written. It needs two extra fields to store its name and a stub to the factory, and it implements the Unreferenced interface, but other than those minor changes, it is the same as the very first implementation of Account we wrote back in Chapt er 8 . Heres the code: public class Account_Impl extends UnicastRemoteObject impleme nts Account, Unreferenced { private Money _balance; private LockingFactory _factory; private String _accountName; public Account_ImplMoney startingBalance, String accountName throws RemoteException { _balance = startingBalance; _accountName = accountName; } public synchronized Money getBalance throws RemoteException { return _balance; } public synchronized void makeDepositMoney amount throws RemoteException, NegativeAmountException { checkForNegativeAmountamount; _balance.addamount; return; } public synchronized void makeWithdrawalMoney amount throws RemoteException, OverdraftException, NegativeAmountException { checkForNegativeAmountamount; checkForOverdraftamount; _balance.subtractamount; return; } public void setFactoryLockingFactory factory throws RemoteException { _factory = factory; } private void checkForNegativeAmountMoney amount throws NegativeAmountException { int cents = amount.getCents ; if 0 cents { throw new NegativeAmountException ; } } private void checkForOverdraftMoney amount throws OverdraftException { if amount.greaterThan_balance { throw new OverdraftExceptionfalse; } return; } public void unreferenced { if null==_factory { return; } try { _factory.serverNoLongerActive_accountName; } catchRemoteException e { Factory is having issues} _factory = null; } }

17.4.2.3 The launch code and the client

The launch code and the client for this version of the bank example are essentially the same as they were for the version based on BasicAccountFactory_Impl . The only difference is that BankClientFrame s releaseAccount method no longer needs to tell the factory that it is done with a particular account server. releaseAccount is accordingly much simpler: private void releaseAccount { _account=null; return ; }

17.5 Persistence and the Server Lifecycle