Teach Yourself CORBA In 14 Days

Previous chapterNext chapterContents


Day 14
Web-Enabling the Bank Example with Java


On Day 13, "Developing for the Internet Using CORBA and Java," you were introduced to the Java programming language and proceeded to port the Bank application from C++ to Java. The porting process was straightforward, due to the similarities between C++ and Java and the fact that you didn't add any new functionality to the application when you ported it. The result was a CORBA application that behaved exactly like its predecessor, with no new bells or whistles.

Today, you'll take the Java version of the Bank example to its next logical evolutionary step. One of Java's greater potentials is in the development of graphical user interfaces (GUIs), and in this chapter you'll explore Java's capabilities in that area. Of course, the subject of developing GUIs in Java would by itself fill an entire book, so many of the details are omitted here. By the end of today, though, you will have built a functional Java applet that provides a GUI version of the functionality formerly provided by the ATMClient portion of the Bank application.

Developing the BankApplet

The process for developing the applet varies slightly from processes in previous chapters, primarily due to the inclusion of a GUI interface instead of the previous command-line interfaces. Here is the process you'll follow this time around:

Implementing the Server Functionality

As on Day 13, no changes will be made to the server components of the Bank application. When the time comes to run the sample application, you'll run the same BankServer, Bank, and ATM server components as on Day 13.

Implementing the Client Functionality

Before delving into the development of the BankApplet, you need to make a slight modification to the existing CustomerImpl. The reason is that, until now, all output of the client application (and of the server applications, for that matter) has been to the system console (the cout stream in C++ or the System.out stream in Java). Previously, the updateAccountBalance() method of CustomerImpl simply printed a message to System.out, which is fine for a console mode application such as the former ATMClient. However, for a graphical client application such as BankApplet, you probably want to deal with messages in a more graphical way. You'll see how the BankApplet handles such messages, but for now, just recognize that the CustomerImpl forwards the update message to another object--one that implements the AccountUpdateListener interface (which you'll also see in a moment).

Customer

The modifications to the CustomerImpl class are very minor; the CustomerImpl constructor now accepts an AccountUpdateListener parameter, which is used when account update messages are later sent to the CustomerImpl. Also, as mentioned previously, the updateAccountBalance() method itself, rather than print a message to System.out, now forwards the update message to the registered AccountUpdateListener object. (You'll soon see that the AccountUpdateListener object, in this case, is the BankApplet itself.) The modified CustomerImpl.java appears in Listing 14.1.

Listing 14.1. CustomerImpl.java.

  1: // CustomerImpl.java
  2: 
  3: import java.util.Enumeration;
  4: import java.util.Vector;
  5: 
  6: import idlGlobal.Account;
  7: 
  8: public class CustomerImpl extends idlGlobal._CustomerImplBase {
  9: 
 10:     // This Customer's name.
 11:     private String myName;
 12: 
 13:     // This Customer's Social Security number.
 14:     private String mySocialSecurityNumber;
 15: 
 16:     // This Customer's address.
 17:     private String myAddress;
 18: 
 19:     // This Customer's mother's maiden name.
 20:     private String myMothersMaidenName;
 21: 
 22:     // This Customer's list of Accounts.
 23:     private Vector myAccounts;
 24: 
 25:     // This Customer's list of ATMCards.
 26:     private Vector myATMCards;
 27: 
 28:     // This Customer's AccountUpdateListener (for simplicity, only
 29:     // one is allowed).
 30:     private AccountUpdateListener myAccountUpdateListener;
 31: 
 32:     public CustomerImpl(String name, String socialSecurityNumber,
 33:             String address, String mothersMaidenName,
 34:             AccountUpdateListener accountUpdateListener) {
 35: 
 36:             super(socialSecurityNumber);
 37: 
 38:             myName = new String(name);
 39:             mySocialSecurityNumber = new
 40:                     String(socialSecurityNumber);
 41:             myAddress = new String(address);
 42:             myMothersMaidenName = new String(mothersMaidenName);
 43:             myAccounts = new Vector();
 44:             myATMCards = new Vector();
 45:             myAccountUpdateListener = accountUpdateListener;
 46:     }
 47: 
 48:     protected CustomerImpl() {
 49: 
 50:         myName = new String();
 51:         mySocialSecurityNumber = new String();
 52:         myAddress = new String();
 53:         myMothersMaidenName = new String();
 54:         myAccounts = new Vector();
 55:         myATMCards = new Vector();
 56:     }
 57: 
 58:     public void name(String name) {
 59: 
 60:         myName = new String(name);
 61:     }
 62: 
 63:     public String name() {
 64: 
 65:         return myName;
 66:     }
 67: 
 68:     public String socialSecurityNumber() {
 69: 
 70:         return mySocialSecurityNumber;
 71:     }
 72: 
 73:     public void address(String address) {
 74: 
 75:         myAddress = new String(address);
 76:     }
 77: 
 78:     public String address() {
 79: 
 80:         return myAddress;
 81:     }
 82: 
 83:     public java.lang.String mothersMaidenName() {
 84: 
 85:         return myMothersMaidenName;
 86:     }
 87: 
 88:     public Account[] getAccounts() {
 89: 
 90:         Account[] list = new Account[myAccounts.size()];
 91:         myAccounts.copyInto(list);
 92: 
 93:         Enumeration e = myAccounts.elements();
 94:         while (e.hasMoreElements()) {
 95:             ((Account)e.nextElement())._duplicate();
 96:         }
 97: 
 98:         return list;
 99:     }
100: 
101:     public void updateAccountBalance(Account account, float
102:             balance) {
103: 
104:         myAccountUpdateListener.update(account, balance);
105:     }
106: } 

The AccountUpdateListener interface is simple, its only purpose being to accept update messages for Accounts. Consequently, its single method, update(), reflects the updateAccountBalance() method in CustomerImpl. Note that, as an interface, AccountUpdateListener doesn't provide an implementation for this method; the implementation is the responsibility of the class(es) implementing this interface. AccountUpdateListener.java appears in Listing 14.2.

Listing 14.2. AccountUpdateListener.java.

 1: // AccountUpdateListener.java
 2: 
 3: import idlGlobal.Account;
 4: 
 5: public interface AccountUpdateListener {
 6: 
 7:     /**
 8:      * Update the given Account with the new balance.
 9:      */
10:     public void update(Account account, float balance);
11: }

A Word About Java Development Tools

You're almost ready to begin work on the BankApplet itself. If you already took a peek at BankApplet.java (see Listing 14.3), you saw that the file is quite sizable--much larger than anything that has appeared in this book. Don't be alarmed. Much of the code was not written by hand but was generated by a development tool (a development tool, or a portion thereof, for defining GUI interfaces is often called a GUI builder). Symantec's Visual Café 2.0 (available at http://cafe.symantec.com/) was used to develop this particular applet, but any GUI builder for Java--such as Sun's Java Workshop (http://www.sun.com/), Microsoft's Visual J++ (http://www.microsoft.com/), Borland's JBuilder (http://www.borland.com/), IBM's Visual Age for Java (http://www.software.ibm.com/), or many others--can be used to perform the GUI design portion of this task. Each of these products generates different code, depending on the GUI components chosen, but produces a similar end result.

Although you can certainly write all the user interface code by hand, using a GUI builder makes your life a lot easier for all but the most trivial user interfaces. Describing even one of these tools is beyond the scope of this book, so it's hoped that you already have some experience with these. Many GUI builders not only enable you to place user interface components on forms (also called screens or dialogs) but also to define interactions between components without writing any code. The more work the GUI builder does, the less code you have to write by hand, and you can always take code the GUI builder generates and modify it by hand to get the exact results you want.

BankApplet

BankApplet.java, including code generated by Visual Café and code written by hand, appears in Listing 14.3. Again, most of this code (almost the entire init() method, for instance) was generated by Visual Café. In a few moments, you'll examine more closely the portions written by hand. You will see that the applet's behavior is similar to that of the client applications implemented in previous chapters. The structure, however, differs significantly, as the structures of GUI-based applications often differ from their console-based counterparts.

Before examining the code for the BankApplet, it's helpful to see what it produces. Figure 14.1 illustrates the main window of the BankApplet, as designed using Visual Café. Figure 14.2 shows the corresponding hierarchy of objects that make up the user interface.

Figure 14.1. BankApplet main window.

Figure 14.2. BankApplet main window hierarchy.

Listing 14.3. BankApplet.java.

  1: // BankApplet.java
  2: 
  3: import java.awt.*;
  4: import java.awt.event.ItemEvent;
  5: import java.applet.*;
  6: import java.util.Enumeration;
  7: import java.util.Hashtable;
  8: 
  9: import org.omg.CORBA.BOA;
 10: import org.omg.CORBA.ORB;
 11: 
 12: import idlGlobal.Account;
 13: import idlGlobal.ATM;
 14: import idlGlobal.Bank;
 15: import idlGlobal.BankServer;
 16: import idlGlobal.BankServerHelper;
 17: import idlGlobal.CheckingAccountHelper;
 18: import idlGlobal.Customer;
 19: 
 20: import idlGlobal.InsufficientFundsException;
 21: import idlGlobal.InvalidAccountException;
 22: import idlGlobal.InvalidAmountException;
 23: 
 24: public class BankApplet extends Applet implements
 25:         AccountUpdateListener {
 26: 
 27:     public static ORB myORB;
 28:     public static BOA myBOA;
 29: 
 30:     // This BankApplet's BankServer.
 31:     BankServer myBankServer;
 32: 
 33:     // This BankApplet's currently selected Bank, ATM, Customer,
 34:     // and Account.
 35:     Bank mySelectedBank;
 36:     ATM mySelectedATM;
 37:     Customer mySelectedCustomer;
 38:     Account mySelectedAccount;
 39: 
 40:     // This BankApplet's list of Banks, keyed on the Bank name.
 41:     Hashtable myBanks = new Hashtable();
 42: 
 43:     // This BankApplet's list of ATMs, keyed on the ATM name.
 44:     Hashtable myATMs = new Hashtable();
 45: 
 46:     // This BankApplet's list of Customers, keyed on the Customer
 47:     // name. Note that this means that Customer names must be
 48:     // unique in this applet!
 49:     Hashtable myCustomers = new Hashtable();
 50: 
 51:     // This BankApplet's list of Accounts. This Hashtable is keyed
 52:     // on Customer objects, which in turn point to Hashtables which
 53:     // are keyed on the concatenation of Bank names and Account
 54:     // numbers and identify Accounts.
 55:     Hashtable myAccounts = new Hashtable();
 56: 
 57:     // This BankApplet's map which links Accounts to Banks.
 58:     Hashtable myAccountBankMap = new Hashtable();
 59: 
 60:     public void init() {
 61: 
 62:         //{{INIT_CONTROLS
 63:         GridBagLayout gridBagLayout;
 64:         gridBagLayout = new GridBagLayout();
 65:         setLayout(gridBagLayout);
 66:         setSize(404, 327);
 67:         setBackground(new Color(-4144944));
 68:         bankChoice = new java.awt.Choice();
 69:         bankChoice.setBounds(112, 3, 322, 21);
 70:         GridBagConstraints gbc;
 71:         gbc = new GridBagConstraints();
 72:         gbc.gridx = 1;
 73:         gbc.gridy = 0;
 74:         gbc.weightx = 1.0;
 75:         gbc.fill = GridBagConstraints.HORIZONTAL;
 76:         gbc.insets = new Insets(2, 2, 2, 2);
 77:         gbc.ipadx = 100;
 78:         ((GridBagLayout)getLayout()).setConstraints(bankChoice,
 79:                 gbc);
 80:         add(bankChoice);
 81:         atmChoice = new java.awt.Choice();
 82:         atmChoice.setBounds(112, 30, 156, 21);
 83:         gbc = new GridBagConstraints();
 84:         gbc.gridx = 1;
 85:         gbc.gridy = 1;
 86:         gbc.weightx = 1.0;
 87:         gbc.fill = GridBagConstraints.HORIZONTAL;
 88:         gbc.insets = new Insets(2, 2, 2, 2);
 89:         ((GridBagLayout)getLayout()).setConstraints(atmChoice,
 90:                 gbc);
 91:         add(atmChoice);
 92:         customerChoice = new java.awt.Choice();
 93:         customerChoice.setBounds(112, 57, 156, 21);
 94:         gbc = new GridBagConstraints();
 95:         gbc.gridx = 1;
 96:         gbc.gridy = 2;
 97:         gbc.weightx = 1.0;
 98:         gbc.fill = GridBagConstraints.HORIZONTAL;
 99:         gbc.insets = new Insets(2, 2, 2, 2);
100:         ((GridBagLayout)getLayout()).setConstraints(customerChoice,
101:                 gbc);
102:         add(customerChoice);
103:         newCustomerButton = new java.awt.Button();
104:         newCustomerButton.setActionCommand("button");
105:         newCustomerButton.setLabel("New...");
106:         newCustomerButton.setBounds(272, 56, 48, 23);
107:         gbc = new GridBagConstraints();
108:         gbc.gridx = 2;
109:         gbc.gridy = 2;
110:         gbc.fill = GridBagConstraints.NONE;
111:         gbc.insets = new Insets(2, 2, 2, 2);
112:         ((GridBagLayout)getLayout()).
113:                 setConstraints(newCustomerButton, gbc);
114:         add(newCustomerButton);
115:         accountChoice = new java.awt.Choice();
116:         accountChoice.setBounds(112, 84, 156, 21);
117:         gbc = new GridBagConstraints();
118:         gbc.gridx = 1;
119:         gbc.gridy = 3;
120:         gbc.weightx = 1.0;
121:         gbc.fill = GridBagConstraints.HORIZONTAL;
122:         gbc.insets = new Insets(2, 2, 2, 2);
123:         ((GridBagLayout)getLayout()).setConstraints(accountChoice,
124:                 gbc);
125:         add(accountChoice);
126:         accountChoice.setEnabled(false);
127:         newAccountButton = new java.awt.Button();
128:         newAccountButton.setActionCommand("button");
129:         newAccountButton.setLabel("New...");
130:         newAccountButton.setBounds(272, 83, 48, 23);
131:         gbc = new GridBagConstraints();
132:         gbc.gridx = 2;
133:         gbc.gridy = 3;
134:         gbc.fill = GridBagConstraints.NONE;
135:         gbc.insets = new Insets(2, 2, 2, 2);
136:         ((GridBagLayout)getLayout()).
137:                 setConstraints(newAccountButton, gbc);
138:         add(newAccountButton);
139:         newAccountButton.setEnabled(false);
140:         autoUpdateButton = new java.awt.Button();
141:         autoUpdateButton.setActionCommand("button");
142:         autoUpdateButton.setLabel("AutoUpdate");
143:         autoUpdateButton.setBounds(324, 83, 78, 23);
144:         gbc = new GridBagConstraints();
145:         gbc.gridx = 3;
146:         gbc.gridy = 3;
147:         gbc.fill = GridBagConstraints.NONE;
148:         gbc.insets = new Insets(2, 2, 2, 2);
149:         ((GridBagLayout)getLayout()).
150:                 setConstraints(autoUpdateButton, gbc);
151:         add(autoUpdateButton);
152:         autoUpdateButton.setEnabled(false);
153:         selectBankLabel = new java.awt.Label("Select Bank");
154:         selectBankLabel.setBounds(2, 2, 79, 23);
155:         gbc = new GridBagConstraints();
156:         gbc.gridx = 0;
157:         gbc.gridy = 0;
158:         gbc.anchor = GridBagConstraints.WEST;
159:         gbc.fill = GridBagConstraints.NONE;
160:         gbc.insets = new Insets(2, 2, 2, 2);
161:         ((GridBagLayout)getLayout()).
162:                 setConstraints(selectBankLabel, gbc);
163:         add(selectBankLabel);
164:         selectATMLabel = new java.awt.Label("Select ATM");
165:         selectATMLabel.setBounds(2, 29, 74, 23);
166:         gbc = new GridBagConstraints();
167:         gbc.gridx = 0;
168:         gbc.gridy = 1;
169:         gbc.anchor = GridBagConstraints.WEST;
170:         gbc.fill = GridBagConstraints.NONE;
171:         gbc.insets = new Insets(2, 2, 2, 2);
172:         ((GridBagLayout)getLayout()).
173:                 setConstraints(selectATMLabel, gbc);
174:         add(selectATMLabel);
175:         selectCustomerLabel = new java.awt.
176:                 Label("Select Customer");
177:         selectCustomerLabel.setBounds(2, 56, 106, 23);
178:         gbc = new GridBagConstraints();
179:         gbc.gridx = 0;
180:         gbc.gridy = 2;
181:         gbc.anchor = GridBagConstraints.WEST;
182:         gbc.fill = GridBagConstraints.NONE;
183:         gbc.insets = new Insets(2, 2, 2, 2);
184:         ((GridBagLayout)getLayout()).
185:                 setConstraints(selectCustomerLabel, gbc);
186:         add(selectCustomerLabel);
187:         selectAccountLabel = new java.awt.Label("Select Account");
188:         selectAccountLabel.setBounds(2, 83, 94, 23);
189:         gbc = new GridBagConstraints();
190:         gbc.gridx = 0;
191:         gbc.gridy = 3;
192:         gbc.anchor = GridBagConstraints.WEST;
193:         gbc.fill = GridBagConstraints.NONE;
194:         gbc.insets = new Insets(2, 2, 2, 2);
195:         ((GridBagLayout)getLayout()).
196:                 setConstraints(selectAccountLabel, gbc);
197:         add(selectAccountLabel);
198:         accountActionPanel = new java.awt.Panel();
199:         gridBagLayout = new GridBagLayout();
200:         accountActionPanel.setLayout(gridBagLayout);
201:         accountActionPanel.setBounds(2, 110, 400, 188);
202:         gbc = new GridBagConstraints();
203:         gbc.gridx = 0;
204:         gbc.gridy = 4;
205:         gbc.gridwidth = 4;
206:         gbc.weightx = 1.0;
207:         gbc.weighty = 1.0;
208:         gbc.fill = GridBagConstraints.BOTH;
209:         gbc.insets = new Insets(2, 2, 2, 2);
210:         ((GridBagLayout)getLayout()).
211:                 setConstraints(accountActionPanel, gbc);
212:         add(accountActionPanel);
213:         accountInfoPanel = new java.awt.Panel();
214:         gridBagLayout = new GridBagLayout();
215:         accountInfoPanel.setLayout(gridBagLayout);
216:         accountInfoPanel.setBounds(0, 13, 246, 162);
217:         gbc = new GridBagConstraints();
218:         gbc.weightx = 0.65;
219:         gbc.anchor = GridBagConstraints.NORTH;
220:         gbc.fill = GridBagConstraints.HORIZONTAL;
221:         gbc.insets = new Insets(0, 0, 0, 2);
222:         ((GridBagLayout)accountActionPanel.getLayout()).
223:                 setConstraints(accountInfoPanel, gbc);
224:         accountActionPanel.add(accountInfoPanel);
225:         issuingBankTextField = new java.awt.TextField();
226:         issuingBankTextField.setEditable(false);
227:         issuingBankTextField.setBounds(136, 29, 108, 23);
228:         gbc = new GridBagConstraints();
229:         gbc.gridx = 2;
230:         gbc.gridy = 1;
231:         gbc.weightx = 1.0;
232:         gbc.fill = GridBagConstraints.HORIZONTAL;
233:         gbc.insets = new Insets(2, 2, 2, 2);
234:         ((GridBagLayout)accountInfoPanel.getLayout()).
235:                 setConstraints(issuingBankTextField, gbc);
236:         accountInfoPanel.add(issuingBankTextField);
237:         accountNumberTextField = new java.awt.TextField();
238:         accountNumberTextField.setEditable(false);
239:         accountNumberTextField.setBounds(136, 56, 108, 23);
240:         gbc = new GridBagConstraints();
241:         gbc.gridx = 2;
242:         gbc.gridy = 2;
243:         gbc.weightx = 1.0;
244:         gbc.fill = GridBagConstraints.HORIZONTAL;
245:         gbc.insets = new Insets(2, 2, 2, 2);
246:         ((GridBagLayout)accountInfoPanel.getLayout()).
247:                 setConstraints(accountNumberTextField, gbc);
248:         accountInfoPanel.add(accountNumberTextField);
249:         accountTypeTextField = new java.awt.TextField();
250:         accountTypeTextField.setEditable(false);
251:         accountTypeTextField.setBounds(136, 83, 108, 23);
252:         gbc = new GridBagConstraints();
253:         gbc.gridx = 2;
254:         gbc.gridy = 3;
255:         gbc.weightx = 1.0;
256:         gbc.fill = GridBagConstraints.HORIZONTAL;
257:         gbc.insets = new Insets(2, 2, 2, 2);
258:         ((GridBagLayout)accountInfoPanel.getLayout()).
259:                 setConstraints(accountTypeTextField, gbc);
260:         accountInfoPanel.add(accountTypeTextField);
261:         creationDateTextField = new java.awt.TextField();
262:         creationDateTextField.setEditable(false);
263:         creationDateTextField.setBounds(136, 110, 115, 23);
264:         gbc = new GridBagConstraints();
265:         gbc.gridx = 2;
266:         gbc.gridy = 4;
267:         gbc.weightx = 1.0;
268:         gbc.fill = GridBagConstraints.HORIZONTAL;
269:         gbc.insets = new Insets(2, 2, 2, 2);
270:         ((GridBagLayout)accountInfoPanel.getLayout()).
271:                 setConstraints(creationDateTextField, gbc);
272:         accountInfoPanel.add(creationDateTextField);
273:         currentBalanceTextField = new java.awt.TextField();
274:         currentBalanceTextField.setEditable(false);
275:         currentBalanceTextField.setBounds(136, 137, 115, 23);
276:         gbc = new GridBagConstraints();
277:         gbc.gridx = 2;
278:         gbc.gridy = 5;
279:         gbc.weightx = 1.0;
280:         gbc.fill = GridBagConstraints.HORIZONTAL;
281:         gbc.insets = new Insets(2, 2, 2, 2);
282:         ((GridBagLayout)accountInfoPanel.getLayout()).
283:                 setConstraints(currentBalanceTextField, gbc);
284:         accountInfoPanel.add(currentBalanceTextField);
285:         accountInfoLabel = new java.awt.
286:                 Label("Account Information", Label.CENTER);
287:         accountInfoLabel.setBounds(62, 2, 122, 23);
288:         gbc = new GridBagConstraints();
289:         gbc.gridx = 0;
290:         gbc.gridy = 0;
291:         gbc.gridwidth = 3;
292:         gbc.fill = GridBagConstraints.NONE;
293:         gbc.insets = new Insets(2, 2, 2, 2);
294:         ((GridBagLayout)accountInfoPanel.getLayout()).
295:                 setConstraints(accountInfoLabel, gbc);
296:         accountInfoPanel.add(accountInfoLabel);
297:         issuingBankLabel = new java.awt.Label("Issuing Bank");
298:         issuingBankLabel.setBounds(2, 29, 86, 23);
299:         gbc = new GridBagConstraints();
300:         gbc.gridx = 0;
301:         gbc.gridy = 1;
302:         gbc.anchor = GridBagConstraints.WEST;
303:         gbc.fill = GridBagConstraints.NONE;
304:         gbc.insets = new Insets(2, 2, 2, 2);
305:         ((GridBagLayout)accountInfoPanel.getLayout()).
306:                 setConstraints(issuingBankLabel, gbc);
307:         accountInfoPanel.add(issuingBankLabel);
308:         accountNumberLabel = new java.awt.Label("Account Number");
309:         accountNumberLabel.setBounds(2, 56, 105, 23);
310:         gbc = new GridBagConstraints();
311:         gbc.gridx = 0;
312:         gbc.gridy = 2;
313:         gbc.anchor = GridBagConstraints.WEST;
314:         gbc.fill = GridBagConstraints.NONE;
315:         gbc.insets = new Insets(2, 2, 2, 2);
316:         ((GridBagLayout)accountInfoPanel.getLayout()).
317:                 setConstraints(accountNumberLabel, gbc);
318:         accountInfoPanel.add(accountNumberLabel);
319:         accountTypeLabel = new java.awt.Label("Account Type");
320:         accountTypeLabel.setBounds(2, 83, 86, 23);
321:         gbc = new GridBagConstraints();
322:         gbc.gridx = 0;
323:         gbc.gridy = 3;
324:         gbc.anchor = GridBagConstraints.WEST;
325:         gbc.fill = GridBagConstraints.NONE;
326:         gbc.insets = new Insets(2, 2, 2, 2);
327:         ((GridBagLayout)accountInfoPanel.getLayout()).
328:                 setConstraints(accountTypeLabel, gbc);
329:         accountInfoPanel.add(accountTypeLabel);
330:         creationDateLabel = new java.awt.Label("Creation Date");
331:         creationDateLabel.setBounds(2, 110, 90, 23);
332:         gbc = new GridBagConstraints();
333:         gbc.gridx = 0;
334:         gbc.gridy = 4;
335:         gbc.anchor = GridBagConstraints.WEST;
336:         gbc.fill = GridBagConstraints.NONE;
337:         gbc.insets = new Insets(2, 2, 2, 2);
338:         ((GridBagLayout)accountInfoPanel.getLayout()).
339:                 setConstraints(creationDateLabel, gbc);
340:         accountInfoPanel.add(creationDateLabel);
341:         currentBalanceLabel = new java.awt.
342:                 Label("Current Balance");
343:         currentBalanceLabel.setBounds(2, 137, 103, 23);
344:         gbc = new GridBagConstraints();
345:         gbc.gridx = 0;
346:         gbc.gridy = 5;
347:         gbc.anchor = GridBagConstraints.WEST;
348:         gbc.fill = GridBagConstraints.NONE;
349:         gbc.insets = new Insets(2, 2, 2, 2);
350:         ((GridBagLayout)accountInfoPanel.getLayout()).
351:                 setConstraints(currentBalanceLabel, gbc);
352:         accountInfoPanel.add(currentBalanceLabel);
353:         dollarLabel1 = new java.awt.Label("$", Label.RIGHT);
354:         dollarLabel1.setBounds(111, 137, 21, 23);
355:         gbc = new GridBagConstraints();
356:         gbc.gridx = 1;
357:         gbc.gridy = 5;
358:         gbc.anchor = GridBagConstraints.EAST;
359:         gbc.fill = GridBagConstraints.NONE;
360:         gbc.insets = new Insets(2, 2, 2, 2);
361:         ((GridBagLayout)accountInfoPanel.getLayout()).
362:                 setConstraints(dollarLabel1, gbc);
363:         accountInfoPanel.add(dollarLabel1);
364:         transactionsPanel = new java.awt.Panel();
365:         gridBagLayout = new GridBagLayout();
366:         transactionsPanel.setLayout(gridBagLayout);
367:         transactionsPanel.setBounds(250, 13, 149, 162);
368:         gbc = new GridBagConstraints();
369:         gbc.weightx = 0.35;
370:         gbc.anchor = GridBagConstraints.NORTH;
371:         gbc.fill = GridBagConstraints.BOTH;
372:         gbc.insets = new Insets(0, 2, 0, 0);
373:         ((GridBagLayout)accountActionPanel.getLayout()).
374:                 setConstraints(transactionsPanel, gbc);
375:         accountActionPanel.add(transactionsPanel);
376:         transactionTextField = new java.awt.TextField();
377:         transactionTextField.setBounds(27, 29, 129, 23);
378:         gbc = new GridBagConstraints();
379:         gbc.gridx = 1;
380:         gbc.gridy = 1;
381:         gbc.weightx = 1.0;
382:         gbc.anchor = GridBagConstraints.NORTH;
383:         gbc.fill = GridBagConstraints.HORIZONTAL;
384:         gbc.insets = new Insets(2, 2, 2, 2);
385:         ((GridBagLayout)transactionsPanel.getLayout()).
386:                 setConstraints(transactionTextField, gbc);
387:         transactionsPanel.add(transactionTextField);
388:         transactionTextField.setEnabled(false);
389:         depositButton = new java.awt.Button();
390:         depositButton.setActionCommand("button");
391:         depositButton.setLabel("Deposit");
392:         depositButton.setBounds(2, 56, 154, 23);
393:         gbc = new GridBagConstraints();
394:         gbc.gridx = 0;
395:         gbc.gridy = 2;
396:         gbc.gridwidth = 2;
397:         gbc.anchor = GridBagConstraints.SOUTH;
398:         gbc.fill = GridBagConstraints.HORIZONTAL;
399:         gbc.insets = new Insets(2, 2, 2, 2);
400:         ((GridBagLayout)transactionsPanel.getLayout()).
401:                 setConstraints(depositButton, gbc);
402:         transactionsPanel.add(depositButton);
403:         depositButton.setEnabled(false);
404:         withdrawButton = new java.awt.Button();
405:         withdrawButton.setActionCommand("button");
406:         withdrawButton.setLabel("Withdraw");
407:         withdrawButton.setBounds(2, 83, 154, 23);
408:         gbc = new GridBagConstraints();
409:         gbc.gridx = 0;
410:         gbc.gridy = 3;
411:         gbc.gridwidth = 2;
412:         gbc.anchor = GridBagConstraints.SOUTH;
413:         gbc.fill = GridBagConstraints.HORIZONTAL;
414:         gbc.insets = new Insets(2, 2, 2, 2);
415:         ((GridBagLayout)transactionsPanel.getLayout()).
416:                 setConstraints(withdrawButton, gbc);
417:         transactionsPanel.add(withdrawButton);
418:         withdrawButton.setEnabled(false);
419:         updateAccountButton = new java.awt.Button();
420:         updateAccountButton.setActionCommand("button");
421:         updateAccountButton.setLabel("Update Account");
422:         updateAccountButton.setBounds(2, 137, 154, 23);
423:         gbc = new GridBagConstraints();
424:         gbc.gridx = 0;
425:         gbc.gridy = 4;
426:         gbc.gridwidth = 2;
427:         gbc.weighty = 1.0;
428:         gbc.anchor = GridBagConstraints.SOUTH;
429:         gbc.fill = GridBagConstraints.HORIZONTAL;
430:         gbc.insets = new Insets(2, 2, 2, 2);
431:         ((GridBagLayout)transactionsPanel.getLayout()).
432:                 setConstraints(updateAccountButton, gbc);
433:         transactionsPanel.add(updateAccountButton);
434:         updateAccountButton.setEnabled(false);
435:         transactionsLabel = new java.awt.Label("Transactions",
436:                 Label.CENTER);
437:         transactionsLabel.setBounds(31, 2, 86, 23);
438:         gbc = new GridBagConstraints();
439:         gbc.gridx = 0;
440:         gbc.gridy = 0;
441:         gbc.gridwidth = 2;
442:         gbc.anchor = GridBagConstraints.NORTH;
443:         gbc.fill = GridBagConstraints.NONE;
444:         gbc.insets = new Insets(2, 2, 2, 2);
445:         ((GridBagLayout)transactionsPanel.getLayout()).
446:                 setConstraints(transactionsLabel, gbc);
447:         transactionsPanel.add(transactionsLabel);
448:         dollarLabel2 = new java.awt.Label("$", Label.RIGHT);
449:         dollarLabel2.setBounds(2, 29, 21, 23);
450:         gbc = new GridBagConstraints();
451:         gbc.gridx = 0;
452:         gbc.gridy = 1;
453:         gbc.anchor = GridBagConstraints.EAST;
454:         gbc.fill = GridBagConstraints.NONE;
455:         gbc.insets = new Insets(2, 2, 2, 2);
456:         ((GridBagLayout)transactionsPanel.getLayout()).
457:                 setConstraints(dollarLabel2, gbc);
458:         transactionsPanel.add(dollarLabel2);
459:         statusTextField = new java.awt.TextField();
460:         statusTextField.setEditable(false);
461:         statusTextField.setText("BankApplet Ready.");
462:         statusTextField.setBounds(2, 302, 400, 23);
463:         gbc = new GridBagConstraints();
464:         gbc.gridx = 0;
465:         gbc.gridy = 5;
466:         gbc.gridwidth = 4;
467:         gbc.weightx = 1.0;
468:         gbc.anchor = GridBagConstraints.SOUTH;
469:         gbc.fill = GridBagConstraints.HORIZONTAL;
470:         gbc.insets = new Insets(2, 2, 2, 2);
471:         ((GridBagLayout)getLayout()).
472:                 setConstraints(statusTextField, gbc);
473:         add(statusTextField);
474:         //}}
475: 
476:         //{{REGISTER_LISTENERS
477:         SymAction lSymAction = new SymAction();
478:         newCustomerButton.addActionListener(lSymAction);
479:         newAccountButton.addActionListener(lSymAction);
480:         SymItem lSymItem = new SymItem();
481:         bankChoice.addItemListener(lSymItem);
482:         atmChoice.addItemListener(lSymItem);
483:         customerChoice.addItemListener(lSymItem);
484:         accountChoice.addItemListener(lSymItem);
485:         autoUpdateButton.addActionListener(lSymAction);
486:         depositButton.addActionListener(lSymAction);
487:         withdrawButton.addActionListener(lSymAction);
488:         updateAccountButton.addActionListener(lSymAction);
489:         //}}
490: 
491:         // Initialize the ORB and BOA.
492:         myORB = ORB.init(this);
493:         myBOA = myORB.BOA_init();
494: 
495:         // Locate a BankServer object and try to get a list of
496:         // Banks and ATMs from it.
497:         setStatus("Binding to a BankServer...");
498:         try {
499:             myBankServer = BankServerHelper.bind(myORB);
500:         } catch (Exception ex) {
501: 
502:             // The bind attempt failed...
503:             setStatus("Unable to bind to a BankServer.");
504:             System.out.println(ex);
505:             return;
506:         }
507:         setStatus("Successfully bound to a BankServer.");
508: 
509:         // Get lists of Banks and ATMs from the BankServer.
510:         ATM[] atms;
511:         Bank[] banks;
512:         setStatus("Getting list of available Banks...");
513:         try {
514:             banks = myBankServer.getBanks();
515:         } catch (Exception ex) {
516: 
517:             // The attempt failed...
518:             setStatus("Unable to get list of Banks.");
519:             return;
520:         }
521:         setStatus("Getting list of available ATMs...");
522:         try {
523:             atms = myBankServer.getATMs();
524:         } catch (Exception ex) {
525: 
526:             // The attempt failed...
527:             setStatus("Unable to get list of ATMs.");
528:             return;
529:         }
530:         addBanks(banks);
531:         addATMs(atms);
532:         setStatus(null);
533:     }
534: 
535:     //{{DECLARE_CONTROLS
536:     java.awt.Choice bankChoice;
537:     java.awt.Choice atmChoice;
538:     java.awt.Choice customerChoice;
539:     java.awt.Button newCustomerButton;
540:     java.awt.Choice accountChoice;
541:     java.awt.Button newAccountButton;
542:     java.awt.Button autoUpdateButton;
543:     java.awt.Label selectBankLabel;
544:     java.awt.Label selectATMLabel;
545:     java.awt.Label selectCustomerLabel;
546:     java.awt.Label selectAccountLabel;
547:     java.awt.Panel accountActionPanel;
548:     java.awt.Panel accountInfoPanel;
549:     java.awt.TextField issuingBankTextField;
550:     java.awt.TextField accountNumberTextField;
551:     java.awt.TextField accountTypeTextField;
552:     java.awt.TextField creationDateTextField;
553:     java.awt.TextField currentBalanceTextField;
554:     java.awt.Label accountInfoLabel;
555:     java.awt.Label issuingBankLabel;
556:     java.awt.Label accountNumberLabel;
557:     java.awt.Label accountTypeLabel;
558:     java.awt.Label creationDateLabel;
559:     java.awt.Label currentBalanceLabel;
560:     java.awt.Label dollarLabel1;
561:     java.awt.Panel transactionsPanel;
562:     java.awt.TextField transactionTextField;
563:     java.awt.Button depositButton;
564:     java.awt.Button withdrawButton;
565:     java.awt.Button updateAccountButton;
566:     java.awt.Label transactionsLabel;
567:     java.awt.Label dollarLabel2;
568:     java.awt.TextField statusTextField;
569:     //}}
570: 
571:     /**
572:      * Set the status bar message to the given string. If the
573:      * string is null, the status message is reset to the default.
574:      */
575:     public void setStatus(String status) {
576: 
577:         if (status != null) {
578:             statusTextField.setText(status);
579:         } else {
580:             statusTextField.setText("BankApplet ready.");
581:         }
582:     }
583: 
584:     /**
585:      * Update the given Account with the new balance.
586:      */
587:     public void update(Account account, float balance) {
588: 
589:         setStatus("Received AutoUpdate for Account \"" + ((Bank)
590:                 myAccountBankMap.get(mySelectedAccount)).name() +
591:                 ":" + account.accountNumber() + "\"");
592: 
593:         // If the updated Account is currently selected, update the
594:         // display immediately.
595:         if (account._is_equivalent(mySelectedAccount)) {
596:             currentBalanceTextField.setText(String.
597:                     valueOf(balance));
598:         }
599:     }
600: 
601:     /**
602:      * Add the given array of Banks to the Bank choice box and to
603:      * this BankApplet's internal data structures.
604:      */
605:     protected void addBanks(Bank[] banks) {
606: 
607:         for (int i = 0; i < banks.length; i++) {
608:             String name = banks[i].name();
609:             myBanks.put(name, banks[i]);
610:             bankChoice.add(name);
611:         }
612:         if (mySelectedBank == null && banks.length > 0) {
613:             mySelectedBank = banks[0];
614:         }
615:     }
616: 
617:     /**
618:      * Add the given array of ATMs to the ATM choice box and to
619:      * this BankApplet's internal data structures.
620:      */
621:     protected void addATMs(ATM[] atms) {
622: 
623:         for (int i = 0; i < atms.length; i++) {
624:             String name = atms[i].name();
625:             myATMs.put(name, atms[i]);
626:             atmChoice.add(name);
627:         }
628:         if (mySelectedATM == null && atms.length > 0) {
629:             mySelectedATM = atms[0];
630:         }
631:     }
632: 
633:     /**
634:      * Create a new Customer with the given name, Social Security
635:      * number, address, mother's maiden name, and PIN.
636:      */
637:     protected void createCustomer(String name, String
638:             socialSecurityNumber, String address, String
639:             mothersMaidenName) {
640: 
641:         // Create a new Customer and register it with the BOA.
642:         setStatus("Creating new Customer...");
643:         CustomerImpl customer = new CustomerImpl(name,
644:                 socialSecurityNumber, address, mothersMaidenName,
645:                 this);
646:         myBOA.obj_is_ready(customer);
647:         myCustomers.put(name, customer);
648:         customerChoice.add(name);
649:         if (mySelectedCustomer == null) {
650:             mySelectedCustomer = customer;
651:         }
652: 
653:         // Now that there is a Customer selected, the Account
654:         // operations can be enabled.
655:         accountChoice.setEnabled(true);
656:         newAccountButton.setEnabled(true);
657: 
658:         setStatus(null);
659:     }
660: 
661:     /**
662:      * Create a new Account with the given owner, Account type, and
663:      * initial balance.
664:      */
665:     protected void createAccount(Customer owner, String type, float
666:             initialBalance) {
667: 
668:         setStatus("Creating new Account...");
669:         Account account = mySelectedBank.createAccount(owner, type,
670:                 initialBalance);
671:         Hashtable accounts = (Hashtable)myAccounts.
672:                 get(mySelectedCustomer);
673: 
674:         // If there doesn't exist an index of Accounts for this
675:         // Customer already, create one.
676:         if (accounts == null) {
677:             accounts = new Hashtable();
678:             myAccounts.put(mySelectedCustomer, accounts);
679:         }
680:         String accountName = mySelectedBank.name() + ":" + account.
681:                 accountNumber();
682:         accounts.put(accountName, account);
683:         accountChoice.add(accountName);
684:         myAccountBankMap.put(account, mySelectedBank);
685: 
686:         if (mySelectedAccount == null) {
687:             mySelectedAccount = account;
688:         }
689: 
690:         // Now that there is an Account selected, the Account
691:         // features can be enabled. Also update the Account info
692:         // display.
693:         enableAccountFeatures(true);
694:         updateAccountInfo();
695: 
696:         setStatus(null);
697:     }
698: 
699:     /**
700:      * Enable/disable the Account-related features.
701:      */
702:     protected void enableAccountFeatures(boolean enable) {
703: 
704:         autoUpdateButton.enable(enable);
705:         transactionTextField.enable(enable);
706:         depositButton.enable(enable);
707:         withdrawButton.enable(enable);
708:         updateAccountButton.enable(enable);
709:         if (!enable) {
710:             issuingBankTextField.setText("");
711:             accountNumberTextField.setText("");
712:             accountTypeTextField.setText("");
713:             creationDateTextField.setText("");
714:             currentBalanceTextField.setText("");
715:             transactionTextField.setText("");
716:         }
717:     }
718: 
719:     /**
720:      * Update the Account information to correspond to the
721:      * currently selected Account.
722:      */
723:     protected void updateAccountInfo() {
724: 
725:         if (mySelectedAccount == null) {
726:             return;
727:         }
728: 
729:         issuingBankTextField.setText(((Bank)myAccountBankMap.
730:                 get(mySelectedAccount)).name());
731:         accountNumberTextField.setText(mySelectedAccount.
732:                 accountNumber());
733:         if (CheckingAccountHelper.narrow(mySelectedAccount) !=
734:                 null) {
735:             accountTypeTextField.setText("Checking");
736:         } else {
737: 
738:             // If Account is not a CheckingAccount, assume it is a
739:             // SavingsAccount
740:             accountTypeTextField.setText("Savings");
741:         }
742:         creationDateTextField.setText(mySelectedAccount.
743:                 creationDate());
744:         currentBalanceTextField.setText(String.
745:                 valueOf(mySelectedAccount.balance()));
746:     }
747: 
748:     class SymAction implements java.awt.event.ActionListener {
749: 
750:         public void actionPerformed(java.awt.event.ActionEvent
751:                 event) {
752:             Object object = event.getSource();
753:             if (object == newCustomerButton)
754:                 newCustomerButton_Action(event);
755:             else if (object == newAccountButton)
756:                 newAccountButton_Action(event);
757:             else if (object == autoUpdateButton)
758:                 autoUpdateButton_Action(event);
759:             else if (object == depositButton)
760:                 depositButton_Action(event);
761:             else if (object == withdrawButton)
762:                 withdrawButton_Action(event);
763:             else if (object == updateAccountButton)
764:                 updateAccountButton_Action(event);
765:         }
766:     }
767: 
768:     void newCustomerButton_Action(java.awt.event.ActionEvent event)
769:             {
770: 
771:         Container theFrame = this;
772:         do {
773:             theFrame = theFrame.getParent();
774:         } while ((theFrame != null) && !(theFrame instanceof
775:                 Frame));
776:         if (theFrame == null)
777:             theFrame = new Frame();
778: 
779:         CustomerDialog cd = new CustomerDialog((Frame)theFrame,
780:                 true);
781:         cd.show();
782:         if (cd.myOKPressed) {
783:             createCustomer(cd.nameTextField.getText(), cd.
784:                     socialSecurityNumberTextField.getText(), cd.
785:                     addressTextField.getText(), cd.
786:                     mothersMaidenNameTextField.getText());
787:         }
788:     }
789: 
790:     void newAccountButton_Action(java.awt.event.ActionEvent event)
791:             {
792: 
793:         Container theFrame = this;
794:         do {
795:             theFrame = theFrame.getParent();
796:         } while ((theFrame != null) && !(theFrame instanceof
797:                 Frame));
798:         if (theFrame == null)
799:             theFrame = new Frame();
800: 
801:         AccountDialog ad = new AccountDialog((Frame)theFrame,
802:                 true);
803:         ad.show();
804:         if (ad.myOKPressed) {
805:             createAccount(mySelectedCustomer, ad.checkingRadio.
806:                     getState() ? "checking" : "savings", new
807:                     Float(ad.initialBalanceTextField.getText()).
808:                     floatValue());
809:         }
810:     }
811: 
812:     class SymItem implements java.awt.event.ItemListener {
813: 
814:         public void itemStateChanged(java.awt.event.ItemEvent
815:                 event) {
816:             Object object = event.getSource();
817:             if (object == bankChoice)
818:                 bankChoice_ItemStateChanged(event);
819:             else if (object == atmChoice)
820:                 atmChoice_ItemStateChanged(event);
821:             else if (object == customerChoice)
822:                 customerChoice_ItemStateChanged(event);
823:             else if (object == accountChoice)
824:                 accountChoice_ItemStateChanged(event);
825:         }
826:     }
827: 
828:     void bankChoice_ItemStateChanged(java.awt.event.ItemEvent
829:             event) {
830: 
831:         if (event.getStateChange() == ItemEvent.SELECTED) {
832:             mySelectedBank = (Bank)myBanks.get(bankChoice.
833:                     getSelectedItem());
834:         }
835:     }
836: 
837:     void atmChoice_ItemStateChanged(java.awt.event.ItemEvent event)
838:             {
839: 
840:         if (event.getStateChange() == ItemEvent.SELECTED) {
841:             mySelectedATM = (ATM)myATMs.get(atmChoice.
842:                     getSelectedItem());
843:         }
844:     }
845: 
846:     void customerChoice_ItemStateChanged(java.awt.event.ItemEvent
847:             event) {
848: 
849:         if (event.getStateChange() == ItemEvent.SELECTED) {
850: 
851:             // Update the Account list to show the currently
852:             // selected Customer's Accounts.
853:             mySelectedCustomer = (Customer)myCustomers.
854:                     get(customerChoice.getSelectedItem());
855:             accountChoice.removeAll();
856:             Hashtable accounts = (Hashtable)myAccounts.
857:                     get(mySelectedCustomer);
858:             if (accounts != null) {
859:                 Enumeration e = accounts.keys();
860:                 while (e.hasMoreElements()) {
861:                     accountChoice.add((String)e.nextElement());
862:                 }
863:             }
864:             mySelectedAccount = null;
865:             enableAccountFeatures(false);
866:         }
867:     }
868: 
869:     void accountChoice_ItemStateChanged(java.awt.event.ItemEvent
870:             event) {
871: 
872:         if (event.getStateChange() == ItemEvent.SELECTED) {
873:             Hashtable accounts = (Hashtable)myAccounts.
874:                     get(mySelectedCustomer);
875:             mySelectedAccount = (Account)accounts.
876:                     get(accountChoice.getSelectedItem());
877:             enableAccountFeatures(true);
878:             updateAccountInfo();
879:         }
880:     }
881: 
882:     void autoUpdateButton_Action(java.awt.event.ActionEvent event)
883:             {
884: 
885:         setStatus("Requesting AutoUpdate service for selected " +
886:                 "Account...");
887:         try {
888:             ((Bank)myAccountBankMap.get(mySelectedAccount)).
889:                     requestUpdateService(mySelectedAccount);
890:         } catch (InvalidAccountException ex) {
891:             setStatus("Could not request AutoUpdate service for " +
892:                     "selected Account: InvalidAcccountException");
893:         }
894:         setStatus(null);
895:     }
896: 
897:     void depositButton_Action(java.awt.event.ActionEvent event) {
898: 
899:         String amount = transactionTextField.getText();
900:         setStatus("Depositing $" + amount + "...");
901:         float newBalance = 0.0f;
902:         try {
903:             newBalance = mySelectedAccount.deposit(new
904:                     Float(amount).floatValue());
905:         } catch (InvalidAmountException ex) {
906:             setStatus("Could not perform transaction: " +
907:                     "InvalidAmountException");
908:             return;
909:         } catch (NumberFormatException ex) {
910:             setStatus("Could not perform transaction: " +
911:                     "NumberFormatException");
912:             return;
913:         }
914:         currentBalanceTextField.setText(String.
915:                 valueOf(newBalance));
916:         setStatus("Deposited $" + amount + " into selected " +
917:                 "Account.");
918:     }
919: 
920:     void withdrawButton_Action(java.awt.event.ActionEvent event) {
921: 
922:         String amount = transactionTextField.getText();
923:         setStatus("Withdrawing $" + amount + "...");
924:         float newBalance = 0.0f;
925:         try {
926:             newBalance = mySelectedAccount.withdraw(new
927:                     Float(amount).floatValue());
928:         } catch (InvalidAmountException ex) {
929:             setStatus("Could not perform transaction: " +
930:                     "InvalidAmountException");
931:             return;
932:         } catch (InsufficientFundsException ex) {
933:             setStatus("Could not perform transaction: " +
934:                     "InsufficientFundsException");
935:             return;
936:         } catch (NumberFormatException ex) {
937:             setStatus("Could not perform transaction: " +
938:                     "NumberFormatException");
939:             return;
940:         }
941:         currentBalanceTextField.setText(String.
942:                 valueOf(newBalance));
943:         setStatus("Withdrew $" + amount + " from selected " +
944:                 "Account.");
945:     }
946: 
947:     void updateAccountButton_Action(java.awt.event.ActionEvent
948:             event) {
949: 
950:         updateAccountInfo();
951:     }
952: } 

Now take a look at selected portions of BankApplet.java. The three import statements in lines 3-5 import the definitions of several GUI-related Java classes. The java.awt package and related packages contain the classes and interfaces that compose the Abstract Windowing Toolkit (AWT). The AWT is a collection of user interface objects and the event handling mechanism that enables those objects to interact with each other. Applications and libraries can build on the core AWT classes to create more complex user interface objects and entire user interfaces.

The java.util package includes a number of utility classes and interfaces. One interface is the Enumeration (imported in line 6), which enables the iteration across collections (such as Vector, Dictionary, Hashtable, and so on), much like a C++ Standard Template Library (STL) iterator. The Hashtable class (imported in line 7), as its name suggests, implements a hash table (a data structure that maps one object instance to another).

The imports in lines 9 and 10 should look familiar. Because BankApplet is a CORBA application, it must be able to access the familiar CORBA ORB and BOA.

Like the ATMClient that came before it, BankApplet makes use of the preceding CORBA objects and exceptions. (Recall that you placed all these definitions in the idlGlobal package when you ran the IDL compiler on Day 13.) Lines 12-22 import these classes into the application.

Note in lines 24 and 25 that the BankApplet class is declared to implement the AccountUpdateListener interface. This means that the BankApplet class must be able to implement the update() method from that interface, and you'll see later that this is indeed the case. It also means that a BankApplet object can be used as a parameter to any method requiring an AccountUpdateListener as a parameter.

For various reasons, the BankApplet keeps track of the currently selected Bank, ATM, Customer, and Account. The definitions of these member variables are found in lines 33-38.

The BankApplet must also keep track of which Bank names correspond to which Bank objects, which ATM names correspond to which ATM objects, and so on. This is so that the user can select each of these objects from a list of names, and the applet will be able to determine the actual object, given its name. The Hashtable class is ideally suited to this purpose; in most of the cases appearing in lines 40-58, it maps Strings to the appropriate object type.

Most of the init() method is omitted from this discussion because it was automatically generated by Visual Café. However, there are some additions, such as the code appearing in lines 491-493. This illustrates a second method of initializing the ORB. Recall that the first method used the command-line parameters from the Java application. Because a Java applet does not have command-line parameters, another form of initialization is used. This form of ORB.init() accepts an Applet as a parameter. From the Applet, the ORB gets its configuration information.


Note:Keep in mind that the ORB.init() method used in the example is a feature of VisiBroker for Java. Other products might (and almost certainly will) use a different method for initializing the ORB.

The bit of code in lines 495-507 will look familiar, but with a small twist. Rather than use System.out.println(), the code calls the setStatus() method. You'll see later exactly what this method does, but for now you only need to know that the method delivers a status message to the user.

Appearing in lines 509-533 is the familiar section of code that obtains the available Bank and ATM objects. When these lists are obtained, the addBanks() and addATMs() methods are called. Again, you'll see shortly what these methods do.

The setStatus() method (lines 571-582), alluded to before, takes a String as a parameter. If the String is null, a default status message is displayed (in this case, "BankApplet ready."); otherwise, the supplied String is displayed. Closer inspection reveals that the status message is displayed in the statusTextField object, the text field spanning the bottom of the BankApplet window.

Recall that BankApplet was required to implement the update() method as a part of implementing the AccountUpdateListener interface. The implementation, appearing in lines 584-599, displays a status message (through--what else--the setStatus() method), and if the information for the updated Account is currently being displayed, the display is updated.

The addBanks() method (lines 601-615), called earlier in init(), adds the names of the given Bank objects to the choice box containing names. The names, along with the Banks themselves, are then added to the myBanks hash table so that the Banks can later be retrieved by name. addATMs() is similar, except it works with ATMs.

The createCustomer() method, in lines 633-659, performs functionality similar to that in the previous ATMClient example. Note, in particular, that the method creates a new CustomerImpl object and registers the object with the BOA, using the obj_is_ready() method. In addition to performing this familiar functionality, createCustomer() adds the Customer to the internal hash table for future lookup. Finally, the method enables parts of the user interface that might have been previously disabled. For example, it doesn't make sense to create an Account before a Customer is created to be associated with that Account. Therefore, the Account creation features are disabled until there is a Customer selected.

Creating an Account is more involved, as evidenced by the longer createAccount() method in lines 661-697. The Account creation consists only of calling the createAccount() method on the currently selected Bank, but there is a bit more work involved with associating the newly created Account with the currently selected Customer. This is because there is a two-level hierarchy of Hashtables that relates Customers to their Accounts. In addition, the Hashtable of Accounts is keyed on the concatenation of the issuing Bank name and the Account number, instead of just the Account number itself (because two different Banks can issue the same Account number, but the keys must be unique). Figure 14.3 illustrates the relationship between Customers and their Accounts. Finally, if an Account is selected, certain features can be enabled, such as the Account transaction features. This is performed by the enableAccountFeatures() method, discussed next.

Figure 14.3. Relationship between Customers and Accounts.

The enableAccountFeatures() method (lines 699-717) enables some Account-related user interface components if its parameter is true and disables them if the parameter is false. In addition, if the parameter is false, the text fields containing Account information are cleared.

The updateAccountInfo() method (lines 719-746) updates the display with the current information on the selected Account, such as issuing the Bank name, the account number, type, creation date, and current balance. Note in line 733 that the type of Account is determined by using the narrow() operation. In this case, CheckingAccountHelper.narrow() returns a CheckingAccount if the Account is indeed a CheckingAccount; otherwise, the operation returns null. (This is CORBA's version of what is commonly referred to as Runtime Type Information, or RTTI.)

The newCustomerButton_Action() method, which appears in lines 768-788, is called when the New Customer button is pressed. Basically, it creates a new CustomerDialog window (which you'll see later in the chapter) and calls createCustomer() with the information provided by that Dialog. The newAccountButton_Action() method operates in much the same manner.

The bankChoice_ItemStateChanged() method, which you can see in lines 828-835, is called when an item is selected in the Bank choice box. It looks up the Bank's name in the appropriate Hashtable to determine which Bank object corresponds to that name and then sets the currently selected Bank to this object. The atmChoice_ItemStateChanged() method behaves similarly. So do the customerChoice_ItemStateChanged() and accountChoice_ ItemStateChanged() methods, although the latter two methods perform additional tasks when a new item is selected, such as updating the display with new information. In the case of a Customer selection, that Customer's Accounts are displayed in the Account choice box. In the case of an Account selection, the Account information display is updated with the newly selected Account.

The remaining BankApplet methods are straightforward: autoUpdateButton_Action() calls the appropriate Bank's requestUpdateService() method for the selected Account, depositButton_Action() calls deposit() on the selected Account with the amount indicated in the transaction text field, withdrawButton_Action() calls withdraw(), and updateAccountButton_Action() calls updateAccountInfo().

BankApplet Dialogs

In addition to the main BankApplet window, there are two other dialog boxes used in the applet. The first is the CustomerDialog, for entering information about a new Customer. The second is the AccountDialog, for entering information about a new Account. The layout of the CustomerDialog appears in Figure 14.4, with its corresponding hierarchy of interface objects appearing in Figure 14.5.

Figure 14.5. CustomerDialog window hierarchy.

Like BankApplet.java, most of CustomerDialog.java is generated by the GUI builder. Listing 14.4 shows CustomerDialog.java in its entirety. In the section following the listing, you'll pick apart the real functionality behind it.

Listing 14.4. CustomerDialog.java.

  1: // CustomerDialog.java
  2: 
  3: import java.awt.*;
  4: 
  5: public class CustomerDialog extends Dialog {
  6: 
  7:     // Set to true if this dialog was completed by pressing OK.
  8:     public boolean myOKPressed = false;
  9: 
 10:     public CustomerDialog(Frame parent, boolean modal) {
 11: 
 12:         super(parent, modal);
 13: 
 14:         //{{INIT_CONTROLS
 15:         GridBagLayout gridBagLayout;
 16:         gridBagLayout = new GridBagLayout();
 17:         setLayout(gridBagLayout);
 18:         setVisible(false);
 19:         setSize(insets().left + insets().right + 435, insets().top
 20:                 + insets().bottom + 110);
 21:         setBackground(new Color(-4144944));
 22:         nameTextField = new java.awt.TextField();
 23:         nameTextField.setBounds(insets().left + 148, insets().top +
 24:                 3, 218, 23);
 25:         GridBagConstraints gbc;
 26:         gbc = new GridBagConstraints();
 27:         gbc.gridx = 1;
 28:         gbc.gridy = 0;
 29:         gbc.weightx = 1.0;
 30:         gbc.fill = GridBagConstraints.HORIZONTAL;
 31:         gbc.insets = new Insets(2, 2, 2, 2);
 32:         ((GridBagLayout)getLayout()).setConstraints(nameTextField,
 33:                 gbc);
 34:         add(nameTextField);
 35:         socialSecurityNumberTextField = new java.awt.TextField();
 36:         socialSecurityNumberTextField.setBounds(insets().left +
 37:                 148, insets().top + 30, 218, 23);
 38:         gbc = new GridBagConstraints();
 39:         gbc.gridx = 1;
 40:         gbc.gridy = 1;
 41:         gbc.weightx = 1.0;
 42:         gbc.fill = GridBagConstraints.HORIZONTAL;
 43:         gbc.insets = new Insets(2, 2, 2, 2);
 44:         ((GridBagLayout)getLayout()).
 45:                 setConstraints(socialSecurityNumberTextField, gbc);
 46:         add(socialSecurityNumberTextField);
 47:         addressTextField = new java.awt.TextField();
 48:         addressTextField.setBounds(insets().left + 148, insets().
 49:                 top + 57, 218, 23);
 50:         gbc = new GridBagConstraints();
 51:         gbc.gridx = 1;
 52:         gbc.gridy = 2;
 53:         gbc.weightx = 1.0;
 54:         gbc.fill = GridBagConstraints.HORIZONTAL;
 55:         gbc.insets = new Insets(2, 2, 2, 2);
 56:         ((GridBagLayout)getLayout()).
 57:                 setConstraints(addressTextField, gbc);
 58:         add(addressTextField);
 59:         mothersMaidenNameTextField = new java.awt.TextField();
 60:         mothersMaidenNameTextField.setBounds(insets().left + 148,
 61:                 insets().top + 84, 218, 23);
 62:         gbc = new GridBagConstraints();
 63:         gbc.gridx = 1;
 64:         gbc.gridy = 3;
 65:         gbc.weightx = 1.0;
 66:         gbc.fill = GridBagConstraints.HORIZONTAL;
 67:         gbc.insets = new Insets(2, 2, 2, 2);
 68:         ((GridBagLayout)getLayout()).
 69:                 setConstraints(mothersMaidenNameTextField, gbc);
 70:         add(mothersMaidenNameTextField);
 71:         okButton = new java.awt.Button();
 72:         okButton.setActionCommand("button");
 73:         okButton.setLabel("OK");
 74:         okButton.setBounds(insets().left + 370, insets().top + 3,
 75:                 63, 23);
 76:         gbc = new GridBagConstraints();
 77:         gbc.gridx = 2;
 78:         gbc.gridy = 0;
 79:         gbc.anchor = GridBagConstraints.NORTHEAST;
 80:         gbc.fill = GridBagConstraints.HORIZONTAL;
 81:         gbc.insets = new Insets(2, 2, 2, 2);
 82:         ((GridBagLayout)getLayout()).setConstraints(okButton, gbc);
 83:         add(okButton);
 84:         okButton.setEnabled(false);
 85:         cancelButton = new java.awt.Button();
 86:         cancelButton.setActionCommand("button");
 87:         cancelButton.setLabel("Cancel");
 88:         cancelButton.setBounds(insets().left + 370, insets().top +
 89:                 30, 63, 23);
 90:         gbc = new GridBagConstraints();
 91:         gbc.gridx = 2;
 92:         gbc.gridy = 1;
 93:         gbc.anchor = GridBagConstraints.NORTHEAST;
 94:         gbc.fill = GridBagConstraints.HORIZONTAL;
 95:         gbc.insets = new Insets(2, 2, 2, 2);
 96:         gbc.ipadx = 10;
 97:         ((GridBagLayout)getLayout()).setConstraints(cancelButton,
 98:                 gbc);
 99:         add(cancelButton);
100:         nameLabel = new java.awt.Label("Name");
101:         nameLabel.setBounds(insets().left + 2, insets().top + 3,
102:                 48, 23);
103:         gbc = new GridBagConstraints();
104:         gbc.gridx = 0;
105:         gbc.gridy = 0;
106:         gbc.anchor = GridBagConstraints.WEST;
107:         gbc.fill = GridBagConstraints.NONE;
108:         gbc.insets = new Insets(2, 2, 2, 2);
109:         ((GridBagLayout)getLayout()).setConstraints(nameLabel,
110:                 gbc);
111:         add(nameLabel);
112:         socialSecurityNumberLabel = new java.awt.
113:                 Label("Social Security Number");
114:         socialSecurityNumberLabel.setBounds(insets().left + 2,
115:                 insets().top + 30, 142, 23);
116:         gbc = new GridBagConstraints();
117:         gbc.gridx = 0;
118:         gbc.gridy = 1;
119:         gbc.anchor = GridBagConstraints.WEST;
120:         gbc.fill = GridBagConstraints.NONE;
121:         gbc.insets = new Insets(2, 2, 2, 2);
122:         ((GridBagLayout)getLayout()).
123:                 setConstraints(socialSecurityNumberLabel, gbc);
124:         add(socialSecurityNumberLabel);
125:         addressLabel = new java.awt.Label("Address");
126:         addressLabel.setBounds(insets().left + 2, insets().top +
127:                 57, 60, 23);
128:         gbc = new GridBagConstraints();
129:         gbc.gridx = 0;
130:         gbc.gridy = 2;
131:         gbc.anchor = GridBagConstraints.WEST;
132:         gbc.fill = GridBagConstraints.NONE;
133:         gbc.insets = new Insets(2, 2, 2, 2);
134:         ((GridBagLayout)getLayout()).setConstraints(addressLabel,
135:                 gbc);
136:         add(addressLabel);
137:         mothersMaidenNameLabel = new java.awt.
138:                 Label("Mother's Maiden Name");
139:         mothersMaidenNameLabel.setBounds(insets().left + 2,
140:                 insets().top + 84, 140, 23);
141:         gbc = new GridBagConstraints();
142:         gbc.gridx = 0;
143:         gbc.gridy = 3;
144:         gbc.anchor = GridBagConstraints.WEST;
145:         gbc.fill = GridBagConstraints.NONE;
146:         gbc.insets = new Insets(2, 2, 2, 2);
147:         ((GridBagLayout)getLayout()).
148:                 setConstraints(mothersMaidenNameLabel, gbc);
149:         add(mothersMaidenNameLabel);
150:         setTitle("New Customer Information");
151:         //}}
152: 
153:         //{{REGISTER_LISTENERS
154:         SymWindow aSymWindow = new SymWindow();
155:         this.addWindowListener(aSymWindow);
156:         SymAction lSymAction = new SymAction();
157:         okButton.addActionListener(lSymAction);
158:         cancelButton.addActionListener(lSymAction);
159:         SymText lSymText = new SymText();
160:         nameTextField.addTextListener(lSymText);
161:         socialSecurityNumberTextField.addTextListener(lSymText);
162:         addressTextField.addTextListener(lSymText);
163:         mothersMaidenNameTextField.addTextListener(lSymText);
164:         //}}
165:     }
166: 
167:     public void addNotify() {
168: 
169:         // Record the size of the window prior to calling parent's
170:         // addNotify.
171:         Dimension d = getSize();
172: 
173:         super.addNotify();
174: 
175:         if (fComponentsAdjusted)
176:             return;
177: 
178:         // Adjust components according to the insets
179:         setSize(insets().left + insets().right + d.width, insets().
180:                 top + insets().bottom + d.height);
181:         Component components[] = getComponents();
182:         for (int i = 0; i < components.length; i++)
183:         {
184:             Point p = components[i].getLocation();
185:             p.translate(insets().left, insets().top);
186:             components[i].setLocation(p);
187:         }
188:         fComponentsAdjusted = true;
189:     }
190: 
191:     // Used for addNotify check.
192:     boolean fComponentsAdjusted = false;
193: 
194:     public CustomerDialog(Frame parent, String title, boolean
195:             modal) {
196: 
197:         this(parent, modal);
198:         setTitle(title);
199:     }
200: 
201:     public synchronized void show() {
202: 
203:         Rectangle bounds = getParent().bounds();
204:         Rectangle abounds = bounds();
205: 
206:         move(bounds.x + (bounds.width - abounds.width) / 2,
207:              bounds.y + (bounds.height - abounds.height) /2);
208: 
209:         super.show();
210:     }
211: 
212:     //{{DECLARE_CONTROLS
213:     java.awt.TextField nameTextField;
214:     java.awt.TextField socialSecurityNumberTextField;
215:     java.awt.TextField addressTextField;
216:     java.awt.TextField mothersMaidenNameTextField;
217:     java.awt.Button okButton;
218:     java.awt.Button cancelButton;
219:     java.awt.Label nameLabel;
220:     java.awt.Label socialSecurityNumberLabel;
221:     java.awt.Label addressLabel;
222:     java.awt.Label mothersMaidenNameLabel;
223:     //}}
224: 
225:     class SymWindow extends java.awt.event.WindowAdapter {
226: 
227:         public void windowClosing(java.awt.event.WindowEvent event)
228:                 {
229:             Object object = event.getSource();
230:             if (object == CustomerDialog.this)
231:                 Dialog1_WindowClosing(event);
232:         }
233:     }
234: 
235:     void Dialog1_WindowClosing(java.awt.event.WindowEvent event) {
236: 
237:         hide();
238:     }
239: 
240:     class SymAction implements java.awt.event.ActionListener {
241: 
242:         public void actionPerformed(java.awt.event.ActionEvent
243:                 event) {
244: 
245:             Object object = event.getSource();
246:             if (object == okButton)
247:                 okButton_Action(event);
248:             else if (object == cancelButton)
249:                 cancelButton_Action(event);
250:         }
251:     }
252: 
253:     void okButton_Action(java.awt.event.ActionEvent event) {
254: 
255:         myOKPressed = true;
256:         setVisible(false);
257:     }
258: 
259:     void cancelButton_Action(java.awt.event.ActionEvent event) {
260: 
261:         setVisible(false);
262:     }
263: 
264:     class SymText implements java.awt.event.TextListener {
265: 
266:         public void textValueChanged(java.awt.event.TextEvent
267:                 event) {
268: 
269:             Object object = event.getSource();
270:             if (object == nameTextField)
271:                 nameTextField_TextValueChanged(event);
272:             else if (object == socialSecurityNumberTextField)
273:                 socialSecurityNumberTextField_TextValueChanged
274:                         (event);
275:             else if (object == addressTextField)
276:                 addressTextField_TextValueChanged(event);
277:             else if (object == mothersMaidenNameTextField)
278:                 mothersMaidenNameTextField_TextValueChanged(event);
279:         }
280:     }
281: 
282:     void nameTextField_TextValueChanged(java.awt.event.TextEvent
283:             event) {
284: 
285:         okButton.setEnabled((nameTextField.getText().length() > 0)
286:                 && (socialSecurityNumberTextField.getText().
287:                 length() > 0) && (addressTextField.getText().
288:                 length() > 0) && (mothersMaidenNameTextField.
289:                 getText().length() > 0));
290:     }
291: 
292:     void socialSecurityNumberTextField_TextValueChanged(java.awt.
293:             event.TextEvent event) {
294: 
295:         okButton.setEnabled((nameTextField.getText().length() > 0)
296:                 && (socialSecurityNumberTextField.getText().
297:                 length() > 0) && (addressTextField.getText().
298:                 length() > 0) && (mothersMaidenNameTextField.
299:                 getText().length() > 0));
300:     }
301: 
302:     void addressTextField_TextValueChanged(java.awt.event.TextEvent
303:             event) {
304: 
305:         okButton.setEnabled((nameTextField.getText().length() > 0)
306:                 && (socialSecurityNumberTextField.getText().
307:                 length() > 0) && (addressTextField.getText().
308:                 length() > 0) && (mothersMaidenNameTextField.
309:                 getText().length() > 0));
310:     }
311: 
312:     void mothersMaidenNameTextField_TextValueChanged(java.awt.
313:             event.TextEvent event) {
314: 
315:         okButton.setEnabled((nameTextField.getText().length() > 0)
316:                 && (socialSecurityNumberTextField.getText().
317:                 length() > 0) && (addressTextField.getText().
318:                 length() > 0) && (mothersMaidenNameTextField.
319:                 getText().length() > 0));
320:     }
321: } 

Now, let's inspect what is happening under the hood of CustomerDialog.java. When the OK button is pressed, okButton_Action() (lines 253-257) is called. This method hides the CustomerDialog and sets a flag to indicate that the dialog was closed by pressing the OK button (the BankApplet checks this flag to determine whether the CustomerDialog information should be processed). cancelButton_Action() (lines 259-262) behaves similarly but does not set this flag.

When the Customer name text field changes (in other words, the user presses a key in the field), the nameTextField_TextValueChanged() method (lines 282-290) is called. The method disables the OK button unless a value is entered into all the text fields (that is, the length of the text in each field is greater than zero), in which case the OK button is enabled. (The Cancel button is always enabled and, thus, can be pressed at any time.) Each text field has a method that behaves similarly: socialSecurityNumberTextField_TextValueChanged() (lines 292-300), addressTextField_TextValueChanged() (lines 302-310), and mothersMaidenName TextField_TextValueChanged() (lines 312-320) all duplicate this behavior.

The next component of the BankApplet is the AccountDialog, an illustration of which appears in Figure 14.6 and whose window hierarchy appears in Figure 14.7. AccountDialog.java, which (you guessed it) consists mostly of generated code, appears in Listing 14.5.

Figure 14.6. AccountDialog window.

Figure 14.7. AccountDialog window hierarchy.

Listing 14.5. AccountDialog.java.

  1: // AccountDialog.java
  2: 
  3: import java.awt.*;
  4: 
  5: public class AccountDialog extends Dialog {
  6: 
  7:     // Set to true if this dialog was completed by pressing OK.
  8:     public boolean myOKPressed = false;
  9: 
 10:     public AccountDialog(Frame parent, boolean modal) {
 11: 
 12:         super(parent, modal);
 13: 
 14:         //{{INIT_CONTROLS
 15:         GridBagLayout gridBagLayout;
 16:         gridBagLayout = new GridBagLayout();
 17:         setLayout(gridBagLayout);
 18:         setVisible(false);
 19:         setSize(insets().left + insets().right + 277, insets().top
 20:                 + insets().bottom + 124);
 21:         setBackground(new Color(-4144944));
 22:         Group1 = new CheckboxGroup();
 23:         checkingRadio = new java.awt.Checkbox("Checking", Group1,
 24:                 true);
 25:         checkingRadio.setBounds(insets().left + 2, insets().top +
 26:                 29, 82, 23);
 27:         GridBagConstraints gbc;
 28:         gbc = new GridBagConstraints();
 29:         gbc.gridx = 0;
 30:         gbc.gridy = 1;
 31:         gbc.anchor = GridBagConstraints.WEST;
 32:         gbc.fill = GridBagConstraints.NONE;
 33:         gbc.insets = new Insets(2, 2, 2, 2);
 34:         ((GridBagLayout)getLayout()).setConstraints(checkingRadio,
 35:                 gbc);
 36:         add(checkingRadio);
 37:         savingsRadio = new java.awt.Checkbox("Savings", Group1,
 38:                 false);
 39:         savingsRadio.setBounds(insets().left + 2, insets().top +
 40:                 56, 74, 23);
 41:         gbc = new GridBagConstraints();
 42:         gbc.gridx = 0;
 43:         gbc.gridy = 2;
 44:         gbc.anchor = GridBagConstraints.WEST;
 45:         gbc.fill = GridBagConstraints.NONE;
 46:         gbc.insets = new Insets(2, 2, 2, 2);
 47:         ((GridBagLayout)getLayout()).setConstraints(savingsRadio,
 48:                 gbc);
 49:         add(savingsRadio);
 50:         initialBalanceTextField = new java.awt.TextField();
 51:         initialBalanceTextField.setBounds(insets().left + 122,
 52:                 insets().top + 99, 86, 23);
 53:         gbc = new GridBagConstraints();
 54:         gbc.gridx = 2;
 55:         gbc.gridy = 3;
 56:         gbc.weightx = 1.0;
 57:         gbc.anchor = GridBagConstraints.SOUTH;
 58:         gbc.fill = GridBagConstraints.HORIZONTAL;
 59:         gbc.insets = new Insets(2, 2, 2, 2);
 60:         ((GridBagLayout)getLayout()).
 61:                 setConstraints(initialBalanceTextField, gbc);
 62:         add(initialBalanceTextField);
 63:         okButton = new java.awt.Button();
 64:         okButton.setActionCommand("button");
 65:         okButton.setLabel("OK");
 66:         okButton.setBounds(insets().left + 212, insets().top + 2,
 67:                 63, 23);
 68:         gbc = new GridBagConstraints();
 69:         gbc.gridx = 3;
 70:         gbc.gridy = 0;
 71:         gbc.anchor = GridBagConstraints.NORTHEAST;
 72:         gbc.fill = GridBagConstraints.HORIZONTAL;
 73:         gbc.insets = new Insets(2, 2, 2, 2);
 74:         ((GridBagLayout)getLayout()).setConstraints(okButton, gbc);
 75:         add(okButton);
 76:         cancelButton = new java.awt.Button();
 77:         cancelButton.setActionCommand("button");
 78:         cancelButton.setLabel("Cancel");
 79:         cancelButton.setBounds(insets().left + 212, insets().top +
 80:                 29, 63, 23);
 81:         gbc = new GridBagConstraints();
 82:         gbc.gridx = 3;
 83:         gbc.gridy = 1;
 84:         gbc.anchor = GridBagConstraints.NORTHEAST;
 85:         gbc.fill = GridBagConstraints.HORIZONTAL;
 86:         gbc.insets = new Insets(2, 2, 2, 2);
 87:         gbc.ipadx = 10;
 88:         ((GridBagLayout)getLayout()).setConstraints(cancelButton,
 89:                 gbc);
 90:         add(cancelButton);
 91:         accountTypeLabel = new java.awt.Label("Account Type");
 92:         accountTypeLabel.setBounds(insets().left + 2, insets().top
 93:                 + 2, 86, 23);
 94:         gbc = new GridBagConstraints();
 95:         gbc.gridx = 0;
 96:         gbc.gridy = 0;
 97:         gbc.anchor = GridBagConstraints.WEST;
 98:         gbc.fill = GridBagConstraints.NONE;
 99:         gbc.insets = new Insets(2, 2, 2, 2);
100:         ((GridBagLayout)getLayout()).
101:                 setConstraints(accountTypeLabel, gbc);
102:         add(accountTypeLabel);
103:         initialBalanceLabel = new java.awt.Label("Initial Balance");
104:         initialBalanceLabel.setBounds(insets().left + 2, insets().
105:                 top + 99, 91, 23);
106:         gbc = new GridBagConstraints();
107:         gbc.gridx = 0;
108:         gbc.gridy = 3;
109:         gbc.weighty = 1.0;
110:         gbc.anchor = GridBagConstraints.SOUTHWEST;
111:         gbc.fill = GridBagConstraints.NONE;
112:         gbc.insets = new Insets(2, 2, 2, 2);
113:         ((GridBagLayout)getLayout()).
114:                 setConstraints(initialBalanceLabel, gbc);
115:         add(initialBalanceLabel);
116:         dollarLabel = new java.awt.Label("$", Label.RIGHT);
117:         dollarLabel.setBounds(insets().left + 97, insets().top +
118:                 99, 21, 23);
119:         gbc = new GridBagConstraints();
120:         gbc.gridx = 1;
121:         gbc.gridy = 3;
122:         gbc.anchor = GridBagConstraints.SOUTHEAST;
123:         gbc.fill = GridBagConstraints.NONE;
124:         gbc.insets = new Insets(2, 2, 2, 2);
125:         ((GridBagLayout)getLayout()).setConstraints(dollarLabel,
126:                 gbc);
127:         add(dollarLabel);
128:         setTitle("New Account Information");
129:         //}}
130: 
131:         //{{REGISTER_LISTENERS
132:         SymWindow aSymWindow = new SymWindow();
133:         this.addWindowListener(aSymWindow);
134:         SymAction lSymAction = new SymAction();
135:         okButton.addActionListener(lSymAction);
136:         cancelButton.addActionListener(lSymAction);
137:         //}}
138:     }
139: 
140:     public void addNotify() {
141: 
142:         // Record the size of the window prior to calling parent's
143:         // addNotify.
144:         Dimension d = getSize();
145: 
146:         super.addNotify();
147: 
148:         if (fComponentsAdjusted)
149:             return;
150: 
151:         // Adjust components according to the insets
152:         setSize(insets().left + insets().right + d.width, insets().
153:                 top + insets().bottom + d.height);
154:         Component components[] = getComponents();
155:         for (int i = 0; i < components.length; i++) {
156:             Point p = components[i].getLocation();
157:             p.translate(insets().left, insets().top);
158:             components[i].setLocation(p);
159:         }
160:         fComponentsAdjusted = true;
161:     }
162: 
163:     // Used for addNotify check.
164:     boolean fComponentsAdjusted = false;
165: 
166:     public AccountDialog(Frame parent, String title, boolean modal)
167:             {
168: 
169:         this(parent, modal);
170:         setTitle(title);
171:     }
172: 
173:     public synchronized void show() {
174: 
175:         Rectangle bounds = getParent().bounds();
176:         Rectangle abounds = bounds();
177: 
178:         move(bounds.x + (bounds.width - abounds.width) / 2,
179:              bounds.y + (bounds.height - abounds.height) / 2);
180: 
181:         super.show();
182:     }
183: 
184:     //{{DECLARE_CONTROLS
185:     java.awt.Checkbox checkingRadio;
186:     CheckboxGroup Group1;
187:     java.awt.Checkbox savingsRadio;
188:     java.awt.TextField initialBalanceTextField;
189:     java.awt.Button okButton;
190:     java.awt.Button cancelButton;
191:     java.awt.Label accountTypeLabel;
192:     java.awt.Label initialBalanceLabel;
193:     java.awt.Label dollarLabel;
194:     //}}
195: 
196:     class SymWindow extends java.awt.event.WindowAdapter {
197: 
198:         public void windowClosing(java.awt.event.WindowEvent event)
199:                 {
200: 
201:             Object object = event.getSource();
202:             if (object == AccountDialog.this)
203:                 Dialog1_WindowClosing(event);
204:         }
205:     }
206: 
207:     void Dialog1_WindowClosing(java.awt.event.WindowEvent event) {
208: 
209:         hide();
210:     }
211: 
212:     class SymAction implements java.awt.event.ActionListener {
213: 
214:         public void actionPerformed(java.awt.event.ActionEvent
215:                 event) {
216: 
217:             Object object = event.getSource();
218:             if (object == okButton)
219:                 okButton_Action(event);
220:             else if (object == cancelButton)
221:                 cancelButton_Action(event);
222:         }
223:     }
224: 
225:     void okButton_Action(java.awt.event.ActionEvent event) {
226: 
227:         myOKPressed = true;
228:         setVisible(false);
229:     }
230: 
231:     void cancelButton_Action(java.awt.event.ActionEvent event) {
232: 
233:         setVisible(false);
234:     }
235: } 

Because the AccountDialog is even simpler than the CustomerDialog, it takes no time at all to review. The okButton_Action() (lines 225-229) and cancelButton_Action() (lines 231-234) methods behave identically to their counterparts in CustomerDialog; all other code is generated by the GUI builder.

The final component of the BankApplet (or any applet, for that matter) is an HTML file containing an <APPLET> tag. The HTML file should be placed in the same directory as the BankApplet.class file that is output from the Java compiler. In the case of the BankApplet, this can be a very simple HTML file, as in Listing 14.6.

Listing 14.6. BankApplet.html.

 1: <HTML>
 2: <HEAD>
 3: <TITLE>BankApplet, a sample CORBA applet</TITLE>
 4: </HEAD>
 5: <BODY>
 6: <APPLET CODE="BankApplet.class" WIDTH=404 HEIGHT=327>
 7: <PARAM NAME=org.omg.CORBA.ORBClass
 8: VALUE=com.visigenic.vbroker.orb.ORB>
 9: </APPLET>
10: </BODY>
11: </HTML> 

In particular, note three aspects of the <APPLET> tag in the BankApplet.html file. First, note the CODE="BankApplet.class" parameter in line 6. This indicates the file in which the main part of the applet resides (in other words, the class that derives from java.awt.applet.Applet). Next, note the WIDTH and HEIGHT parameters, also in line 6. These indicate the initial size of the applet window. Finally, notice the parameter <PARAM NAME=org.omg.CORBA.ORBClass VALUE=com.visigenic.vbroker.orb.ORB> in lines 7 and 8. This parameter, intended for Visigenic's VisiBroker for Java 3.0, tells the browser to use the supplied VisiBroker classes instead of the built-in classes (for browsers, such as Communicator, that have VisiBroker built in).

Running the Applet

As mentioned before, the server components used with the BankApplet are unchanged from those used with the Java version of the ATMClient. You can refer to Day 13 to review the process for starting up the BankServer, the Bank, and the ATM. To make things interesting, you might want to start more than one Bank and ATM so you can see how the choice boxes work when you run the BankApplet.

When the server components are up and running, you might be required to run other components as well, depending on the CORBA product you are using. To enable applets to connect to other hosts, for example, Visigenic's VisiBroker includes the GateKeeper, which serves as a gateway between applets and CORBA servers. If you're using VisiBroker, starting the GateKeeper is simple enough:

GateKeeper

The GateKeeper responds with output similar to the following:

VisiBroker Developer for Java [03.00.00.C3.05] (SEP 08 1997
16:55:51) IIOP GateKeeper started: Mon Nov 03 01:50:51 GMT+00:00
1997
Java: Version 1.1.4 from Sun Microsystems Inc.
OS:   Windows 95 version 4.0; CPU: x86
Adding search path: .
Adding search path: C:\Bin\Devel\Java\VCafe\BIN\COMPONENTS\
SYMBEANS.JAR
Adding search path: C:\Bin\Devel\Java\VCafe\JAVA\LIB
Adding search path: D:\Bin\Devel\VisiBroker\lib\vbj30.jar
Adding search path: .
Adding search path: D:\Bin\Devel\TeachYourselfCORBA\BankExample\
ch14
Adding search path: D:\Bin\Devel\TeachYourselfCORBA\BankExample\
ch14\Customer
Writing IOR to D:\Bin\Devel\TeachYourselfCORBA\BankExample\ch14\
BankApplet\gatekeeper.ior

The actual output depends on your CLASSPATH setting, but if you get something resembling the preceding, you are ready to run the BankApplet.

You have two options for running the BankApplet: using the appletviewer application provided with the Java Developer's Kit or using a Java-enabled Web browser such as Netscape Navigator, Netscape Communicator, Microsoft Internet Explorer, and so on. Now you'll learn how to run the applet in both environments.

Using appletviewer

As stated before, appletviewer is a utility that ships with Sun's Java Development Kit (JDK) and is included with Java development products. The appletviewer's purpose, which can be deduced from its name, is to run applets. To run the BankApplet in the appletviewer, first ensure that the appletviewer exists in your PATH. (If you have previously installed the JDK or another Java development tool, chances are that your PATH is already configured properly.) Next, as always, you want to be sure that your CLASSPATH is configured correctly. Finally, change to the directory that contains BankApplet.html, BankApplet.class, and so on, and start the appletviewer:

appletviewer BankApplet.html

If you're using VisiBroker, you will see something similar to the following within a few seconds:

VisiBroker Developer for Java [03.00.00.C3.05] (SEP 08 1997
16:55:51) started Mon Nov 03 12:55:19 GMT+00:00 1997
Visigenic Software: http://www.visigenic.com/
Locator: 153.36.240.254:-1
Local Environment:
        Java: Version 1.1.4 from Sun Microsystems Inc.
        OS:   Windows 95 version 4.0; CPU: x86
Remote Environment:
        Java: Version 1.1.4 from Sun Microsystems Inc.
        OS:   Windows 95 version 4.0; CPU: x86

After a few more seconds, the appletviewer window appears. Within a few more seconds, it initializes the BankApplet, resulting in a display that resembles Figure 14.8

Figure 14.8. BankApplet running in appletviewer.

If you see a Bank name and an ATM name in the appropriate choice boxes, then so far, so good. If you don't, make sure that at least one Bank and ATM server has been started, and then restart the appletviewer.

Now, press the New button next to the Customer choice box. A dialog box appears, like the one in Figure 14.9. Enter some information into the dialog, as in Figure 14.10. When you've entered something in every text box, you will see the OK button enabled. When you're satisfied with what you've entered, press OK.

Figure 14.9. Initial CustomerDialog display.

Figure 14.10. CustomerDialog display filled in.

When you press OK in the CustomerDialog, you are returned to the main BankApplet screen, with the message Creating new Customer... appearing in the status display. After a moment, the status returns to BankApplet ready and your new Customer's name appears in the Customer choice box.

Now, create a new Account for the Customer by pressing the New button next to the Account choice box. The AccountDialog window will appear, as shown in Figure 14.11.

Figure 14.11. Initial AccountDialog display.

In the AccountDialog, leave Checking selected for the Account type. Enter an initial balance into the appropriate text field, as demonstrated in Figure 14.12. Then press OK. (The applet accepts a blank initial balance; in this case, the Account is given an initial balance of zero.)

Figure 14.12. AccountDialog display filled in.

Now the main BankApplet screen reappears, displaying for a moment the message Creating new Account... in the status area. The status then returns to BankApplet ready, at which point the window displays the Account information, as shown in Figure 14.13.

Figure 14.13. BankApplet displaying Account information.

Try a few transactions. Enter an amount into the Transactions text box and press the Deposit or Withdraw button. See what happens when you try to withdraw too much money. When you're convinced that transactions work correctly, press the AutoUpdate button. After a minute at most, you will see the Account's balance increase by 5 percent (don't you wish your own bank balance would increase so quickly?)

Feel free to put the applet through its paces. Create a number of Customers and various Accounts for them in different Banks. Switch between Customers and Accounts and watch the information on the screen update accordingly.

Using a Web Browser

You can also run the applet inside a Java-enabled Web browser such as Netscape Communicator, although setting up the applet is more involved. First, you need access to a Web server (also called an HTTP server or an HTTP daemon). You then need to place the BankApplet.html file and the .class files for the BankApplet in a directory visible to the Web server (consult the documentation for the Web server if you're unsure how to do this). Run the server components (and GateKeeper, if necessary) as you did in the previous step.

When all the servers are running, start your Web browser and enter the appropriate URL for the page containing the BankApplet. (The correct URL depends on the configuration of your Web server and the location of the files you created.) The applet might take a moment or two to start, but when it does, your browser window will resemble the one appearing in Fig- ure 14.14.

Figure 14.14. BankApplet running in a Web browser.

Congratulations! You have successfully deployed a Web-based CORBA application. (You should appreciate that this is a much more significant achievement than writing a cute little animated applet.)

Summary

Today, a grand finale for the sample Bank application, you built a Java applet to replace the ATMClient from Day 13 with a graphical user interface. Due to limited space, many details of developing applets in Java were not discussed today, but nevertheless, you were able to run the applet using both the appletviewer utility from the JDK and a Java-enabled Web browser. You now recognize the potential that comes with the capability to deploy CORBA applications--even just the end-user interface of such applications--on the Web. In many cases, the capability to run an enterprise-wide application within a Web browser demonstrates sound benefits: Java's portability enables the application to be distributed to a wide range of platforms. Also, the delivery mechanism is simplified, compared to previous methods, making it a relatively trivial matter to distribute updates to users geographically dispersed throughout an enterprise.

Q&A

Q Why are the listings in this chapter, especially BankApplet.java, so much longer than in previous chapters?

A
Because the example in this chapter implements an application with a Graphical User Interface (GUI), it is understandably more complex than its simpler, console-based counterpart. Creating the various user interface components and handling the events generated by them adds a great deal of complexity to the application. Fortunately, most of the code required to implement GUI interfaces is generated by development tools.

Q I don't have Visual Café; can I still run the sample applet from this chapter?

A
Although Visual Café was used to produce the sample applet in this chapter, you don't need it--or any other Java development tool, for that matter, other than the freely available JDK--to run the sample applet. Having Visual Café enables easier modification of the applet, but you should be able to work with virtually any Java development tool.

Workshop

The following section will help you test your comprehension of the material presented in this chapter and put what you've learned into practice. You'll find the answers to the quiz in Appendix A.

Quiz

1. Why might it be advantageous to deploy a CORBA client as a Java applet?

2
. Why is it useful for browsers to include CORBA-related classes that are built in (for example, Netscape's Communicator includes Visigenic's VisiBroker for Java runtime)?

3
. What is a potential disadvantage to the bundling scheme described in question 2?

Exercise

Extend the BankApplet to do even more cool stuff. You could add tabbed panels to display the Accounts belonging to a particular Customer. Or you could extend the applet to allow multiple Customers to be associated with an Account and extend the Account information correspondingly to show all the Customers associated with a given Account. (Because this is an open-ended exercise, no answer is given.)


Previous chapterNext chapterContents


Macmillan Computer Publishing USA

© Copyright, Macmillan Computer Publishing. All rights reserved.