/**
* BankClient is the main class for the client application.
* It is invoked by the command line:
* <PRE>java bank.client.BankClient APP_SERVER_ADDR</PRE>
* For example:
* <PRE>java bank.client.BankClient byzantium.imaginary.com</PRE>
* This class is a subclass of Frame. At the start of the
* application, it creates an instance of itself and shows
* itself, thus starting the application.
*/
package bank.client;
import bank.server.RemoteAccount;
import bank.server.RemoteAppServer;
import bank.server.RemoteCustomer;
import imaginary.persist.PersistenceException;
import imaginary.persist.RemoteLock;
import imaginary.persist.RemoteLockHolder;
import imaginary.persist.RemotePersistent;
import java.awt.Button;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class BankClient extends Frame implements RemoteLockHolder,
ActionListener, Runnable, WindowListener {
static private String host = null;
/**
* Sets the static host variable to the first command line
* argument. It then creates a new BankClient frame and
* shows it.
* @param args the command line arguments to the application
*/
static public void main(String args[]) {
try {
BankClient frame;
if( args.length != 1 ) {
System.out.println("Syntax: <java bank.client.BankClient " +
"APP_SERVER_HOST>");
return;
}
host = args[0];
frame = new BankClient();
frame.show();
}
catch( RemoteException e ) {
e.printStackTrace();
System.exit(-1);
}
}
private CustomerPanel customer_panel = null;
private Menu account_menu = null;
private Menu help_menu = null;
// The lock this RemoteLockHolder holds
private RemoteLock lock = null;
private MenuBar menu_bar = null;
// The remote application server
private RemoteAppServer server = null;
/**
* Creates a new instance of this frame object. Its first
* task is to export itself as a remote object. Before
* it starts to paint itself, it creates a thread
* in which it connects to the application server.
* This prevents any network lag from slowing the
* painting of the screen.
* @exception java.rmi.RemoteException thrown if the export fails
*/
public BankClient() throws RemoteException {
super();
UnicastRemoteObject.exportObject(this);
{ // Connect to the server in another thread
Thread t = new Thread(this);
t.start();
}
setTitle("First Imaginary Bank of Java");
addNotify();
resize(insets().left + insets().right + 450,insets().top +
insets().bottom + 256);
setBackground(new Color(12632256));
{ // Menus
MenuItem item;
menu_bar = new MenuBar();
account_menu = new Menu("Account");
item = new MenuItem("Open...");
item.addActionListener(this);
account_menu.add(item);
item = new MenuItem("Transfer...");
item.addActionListener(this);
account_menu.add(item);
account_menu.addSeparator();
item = new MenuItem("Exit");
item.addActionListener(this);
account_menu.add(item);
menu_bar.add(account_menu);
help_menu = new Menu("Help");
menu_bar.setHelpMenu(help_menu);
item = new MenuItem("About");
item.addActionListener(this);
help_menu.add(item);
menu_bar.add(help_menu);
setMenuBar(menu_bar);
}
customer_panel = new CustomerPanel(this);
add(customer_panel);
addWindowListener(this);
customer_panel.show();
}
/**
* This is called by the RemoteLock object when it first
* gets created.
* @param l the remote lock object for thie RemoteLockHolder
*/
public void setLock(RemoteLock l) {
lock = l;
}
/**
* This is called by the remote lock object from time to
* time just to check if the network is still up.
* @param p the Persistent this object holds a lock on
*/
public void monitorLock(RemotePersistent p) {
}
/**
* Move the frame to the proper place when it is shown.
*/
public synchronized void show() {
move(50, 50);
super.show();
}
/**
* JDK 1.1 AWT method for performing ActionListener
* related functionality. Specifically, this means responding
* to menu clicks and button clicks.
* @param event the triggered event
*/
public void actionPerformed(ActionEvent event) {
MenuItem m = (MenuItem)event.getSource();
String l = m.getLabel();
if( l.equalsIgnoreCase("Open...") ) {
// Opens a dialog box that prompts the user for a
// customer ID to open
OpenAccountDialog d = new OpenAccountDialog(this, true);
d.show();
}
else if( l.equalsIgnoreCase("Transfer...") ) {
// Opens a dialog box that allowed a user to
// specify an amount and target account for
// money transfers
RemoteAccount acct;
TransferDialog d;
acct = customer_panel.getSelectedAccount();
d = new TransferDialog(this, true, acct);
d.show();
}
else if( l.equalsIgnoreCase("About") ) {
// Shows a simple about dialog
AboutDialog d = new AboutDialog(this, true);
d.show();
}
else if( l.equalsIgnoreCase("Exit") ) {
// Confirms the quit for the user
QuitDialog d = new QuitDialog(this, true);
d.show();
}
}
/**
* The OpenAccountDialog calls this method once the
* user has entered a customer ID and clicked OK.
* This method then uses that ID to load a customer
* object from the application server.
* @param cust_id the customer ID to be loaded
*/
public void loadCustomer(int cust_id) {
RemoteCustomer c;
try {
c = server.getCustomer(this, cust_id);
customer_panel.cleanUp();
remove(customer_panel);
customer_panel = new CustomerPanel(this, c);
add(customer_panel);
validateTree();
customer_panel.show();
}
catch( PersistenceException e ) {
System.err.println("Error loading remote customer.");
e.printStackTrace();
}
catch( RemoteException e ) {
System.err.println("Failed to load remote customer.");
e.printStackTrace();
}
}
/**
* The TransferDialog box calls this method with the desired
* transfer amount, source account, and target account. The method
* in turn tells the source account to tranfer the specified
* amount to the specified target account.
* @param amount the amount of money to transfer
* @param source the source bank account from which to transfer the funds
* @param target the bank account to which the money to be transferred
*/
public synchronized void transfer(float amount, RemoteAccount source,
RemoteAccount target) {
try {
source.transfer(this, amount, target);
lock.save();
}
catch( Exception e ) {
e.printStackTrace();
}
}
// The following methods are required by the WindowListener
// interface from the JDK 1.1 AWT.
public void windowActivated(WindowEvent event) {
}
public void windowClosed(WindowEvent event) {
}
public void windowClosing(WindowEvent event) {
customer_panel.cleanUp();
dispose();
System.exit(0);
}
public void windowDeactivated(WindowEvent event) {
}
public void windowDeiconified(WindowEvent event) {
}
public void windowIconified(WindowEvent event) {
}
public void windowOpened(WindowEvent event) {
}
/**
* This method runs in a separate thread at the time the
* frame is created so that it can load the application
* server.
*/
public void run() {
try {
System.out.println("Connecting to app server at " + host + "...");
server = (RemoteAppServer)Naming.lookup("rmi://" + host +
"/AppServer");
System.out.println("Connected to server...");
}
catch( Exception e ) {
System.err.println("Failed to connect to application server.");
e.printStackTrace();
server = null;
}
}
}
|