The Actual Client Application

The first application is perceived as slow and, consequently, not well designed; the second one is much faster. You can greatly improve perceived application performance by defining a rich set of exceptions and checking as many of them as possible on the client side. Do ATMs Really Do This? The example of checking to see whether a withdrawal amount is negative probably seems a little contrived. But look at your ATM machine the next time you make a withdrawal. There isnt even a minus key there. You are physically prevented from entering an incorrect amount. Moreover, if your bank is anything like mine, it has rules governing the amount you can withdraw. My bank has the following two rules: • The amount of money being withdrawn must be a multiple of 20. • No more than 300 can be withdrawn in any given day. These are enforced by two local checks and then three checks at the server. The local checks are: • The amount of money being withdrawn must be a multiple of 20. • The amount being withdrawn cannot be more than 300. The checks at the server are: • The amount of money being withdrawn must be a multiple of 20. • The amount being withdrawn cannot be more than 300. • The total withdrawn for the day cannot be more than 300. The first two checks are performed on the client side, for the reasons weve been discussing in the this chapter. Theyre also repeated on the server side, to prevent a badly written or malicious client from causing data integrity problems.

9.4.3 The Actual Client Application

The actual client application is a very simple GUI shown in Figur e 9- 1 . The implementation of this application consists of two objects. The first is simply a wrapper class that implements main , shown in Exam ple 9- 2 . Figure 9-1. The banking application GUI Example 9-2. BankClient.java package com.ora.rmibook.chapter9.applications; import java.rmi.; import java.rmi.server.; public class BankClient { public static void mainString[] args { new BankClientFrame.show ; } } Most of the client application is in a second object that creates the user interface and has a set of ActionListeners attached to buttons. This object is shown in Exam ple 9- 3 . Example 9-3. BankClientFrame.java public class BankClientFrame { private JTextField _accountNameField; private JTextField _balanceTextField; private JTextField _withdrawalTextField; private JTextField _depositTextField; private Account _account; protected void buildGUI { JPanel contentPane = new JPanelnew BorderLayout ; contentPane.addbuildActionPanel , BorderLayout.CENTER; contentPane.addbuildBalancePanel , BorderLayout.SOUTH; setContentPanecontentPane; setSize250, 100; } private void resetBalanceField { try { Money balance = _account.getBalance ; _balanceTextField.setTextBalance: + balance.toString ; } catchException e { System.out.printlnError occurre d while getting account balance\n + e; } } private JPanel buildActionPanel { JPanel actionPanel = new JPanelnew GridLayout3,3; actionPanel.addnew JLabelAccount Name:; _accountNameField = new JTextField ; actionPanel.add_accountNameField; JButton getBalanceButton = new JButtonGet Balance; getBalanceButton.addActionListenernew GetBalanceAction ; actionPanel.addgetBalanceButton; actionPanel.addnew JLabelWithdraw; _withdrawalTextField = new JTextField ; actionPanel.add_withdrawalTextField; JButton withdrawalButton = new JButtonDo it; withdrawalButton.addActionListenernew WithdrawAction ; actionPanel.addwithdrawalButton; actionPanel.addnew JLabelDeposit; _depositTextField = new JTextField ; actionPanel.add_depositTextField; JButton depositButton = new JButtonDo it; depositButton.addActionListenernew DepositAction ; actionPanel.adddepositButton; return actionPanel; } private JPanel buildBalancePanel { JPanel balancePanel = new JPanelnew GridLayout1,2; balancePanel.addnew JLabelCurrent Balance:; _balanceTextField = new JTextField ; _balanceTextField.setEnabledfalse; balancePanel.add_balanceTextField; return balancePanel; } private void getAccount { try { _account = AccountNaming.lookup_accountNameField.getText ; } catch Exception e { System.out.printlnCouldnt find account. Error was \n + e; e.printStackTrace ; } return; } private void releaseAccount{ _account = null; } private Money readTextFieldJTextField moneyField{ try { Float floatValue = new FloatmoneyField.getText ; float actualValue = floatValue.floatValue ; int cents = int actualValue 100; return new PositiveMoneycents; } catch Exception e { System.out.printlnField doesnt contain a valid value; } return null; } private class GetBalanceAction implements ActionListener { public void actionPerformedActio nEvent event { try { getAccount ; resetBalanceField ; releaseAccount ; } catch Exception exception{ System.out.printlnCouldnt talk to account. Error was \n + exception.printStackTrace ; } } } private class WithdrawAction implements ActionListener { public void actionPerformedActionEvent event { try{ getAccount ; Money withdrawalAmount = readTextField_withdrawalTextField; _account.makeWithdrawalwithdrawalAmount; _withdrawalTextField.setText; resetBalanceField ; releaseAccount ; } catch Exception exception{ System.out.printlnCouldnt talk to account. Error was \n + exception; exception.printStackTrace ; } } } private class DepositAction implements ActionListener { public void actionPerformedActionEvent event { try { getAccount ; Money depositAmount = readTextField_depositTextField; _account.makeDepositdepositAmount; _depositTextField.setText; resetBalanceField ; releaseAccount ; } catch Exception exception { System.out.printlnCouldnt talk to account. Error was \n + exception.printStackTrace ; } } } }

9.5 Deploying the Application