|
| |
Here's the BankAccountClient class:
package rmiClient;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.rmi.RemoteException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import rmi.BankAccount;
import rmiServer.BankAccountImpl;
/**
* A BankAccount RMI client
*
* @author Bryan Higgs
* @version 1.0
*/
public class BankAccountClient extends JFrame
{
/**
* Creates a new instance of BankAccountClient
*/
public BankAccountClient()
{
super("Bank Account Client");
JPanel contentPanel = new JPanel();
setContentPane(contentPanel);
contentPanel.add( new JLabel("Enter Account name: ") );
contentPanel.add(m_name);
contentPanel.add(m_button);
m_button.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
findAccount();
}
}
);
pack();
}
/**
* Finds the account, using the name specified
*/
private void findAccount()
{
String name = m_name.getText().trim();
BankAccount account;
try
{
account = (BankAccount) m_namingContext.lookup(m_baseURL + name);
JOptionPane.showOptionDialog(
this,
new BankAccountClientPanel(account),
"Bank Account Client Display",
JOptionPane.DEFAULT_OPTION,
JOptionPane.PLAIN_MESSAGE,
null, null, null
);
}
catch (NamingException ex)
{
JOptionPane.showMessageDialog(this, "Could not find account",
"Error", JOptionPane.ERROR_MESSAGE);
ex.printStackTrace();
}
}
////// Private instance data //////
private JTextField m_name = new JTextField(10);
private JButton m_button = new JButton("Find Account");
/**
* Main entry point for client
* @param args the command line arguments
* args[0] contains the server hostname
* args[1] contains the port number for the registry
*/
public static void main(String[] args)
{
// Determine server hostname
String host = null;
if (args.length > 0)
host = args[0];
// Determine the port number
int port = 1099; // the default port number for the registry
if (args.length > 1)
{
try
{
port = Integer.parseInt(args[1]);
}
catch (NumberFormatException nfe)
{
System.err.println("Port number " + args[1] + " invalid");
return;
}
}
// Construct the base URL for the lookups.
m_baseURL = "rmi://" + host + ":" + port + "/";
// Obtain the initial naming context for later...
try
{
m_namingContext = new InitialContext();
}
catch (NamingException ne)
{
ne.printStackTrace();
return;
}
// Now construct the GUI
JFrame frame = new BankAccountClient();
frame.setVisible(true);
}
///// Private data /////
private static Context m_namingContext;
private static String m_baseURL;
}
|
Note that it:
- Sets up the initial naming context and a base RMI URL in the main method,
and then fires up a BankAccountClient JFrame.
- When the "Find Account" button is clicked, the findAccount
method does a look up in the naming context, based on the name specified in
the JTextField. It does this by first constructing an RMI URL from the
base URL and the supplied name.
- If it succeeds in this look up, it then constructs a
BankAccountClientPanel, passing in the BankAccount stub found in the look
up, and then uses this panel in a JOptionPane options dialog to display the
account details.
- If the look up fails, then a JOptionPane error message dialog to tell the
user.
Here is the BankAccountClientPanel class:
package rmiClient;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.rmi.RemoteException;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import rmi.BankAccount;
import rmiServer.BankAccountImpl;
/**
* The GUI frame for the Bank Account client
*
* @author Bryan Higgs
* @version 1.0
*/
public class BankAccountClientPanel extends JPanel
{
/**
* Creates a new instance of BankAccountClientPanel
*/
public BankAccountClientPanel(BankAccount account)
{
m_account = account;
setLayout( new BorderLayout() );
try
{
JPanel northPanel = new JPanel();
add( northPanel, BorderLayout.NORTH );
northPanel.add( new JLabel("Bank Account #: ") );
northPanel.add( m_id );
m_id.setEditable(false);
m_id.setText( "" + m_account.getAccountId() );
JPanel centerPanel = new JPanel( new BorderLayout() );
add( centerPanel, BorderLayout.CENTER );
JPanel holderPanel = new JPanel();
centerPanel.add( holderPanel, BorderLayout.NORTH );
holderPanel.add( new JLabel("Holder: ") );
holderPanel.add( m_holder );
m_holder.setEditable(false);
m_holder.setText( m_account.getHolder() );
JPanel middlePanel = new JPanel( new BorderLayout() );
centerPanel.add( middlePanel, BorderLayout.SOUTH );
JPanel depositPanel = new JPanel();
middlePanel.add( depositPanel, BorderLayout.NORTH );
depositPanel.add( m_depositButton );
m_depositButton.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
depositMoney();
}
}
);
depositPanel.add( new JLabel("$") );
depositPanel.add( m_depositAmount );
JPanel withdrawPanel = new JPanel();
middlePanel.add( withdrawPanel, BorderLayout.SOUTH );
withdrawPanel.add( m_withdrawButton );
m_withdrawButton.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
withdrawMoney();
}
}
);
withdrawPanel.add( new JLabel("$") );
withdrawPanel.add( m_withdrawAmount );
JPanel southPanel = new JPanel();
add( southPanel, BorderLayout.SOUTH );
southPanel.add( new JLabel("Balance: ") );
southPanel.add( new JLabel("$") );
southPanel.add( m_balance );
m_balance.setEditable(false);
setBalance( m_account.getBalance() );
}
catch (RemoteException ex)
{
ex.printStackTrace();
}
}
/**
* Sets the balance in the JTextField
* and sets its color appropriately
*/
private void setBalance(double balance)
{
m_balance.setText( "" + balance );
if (balance < 0)
m_balance.setForeground(Color.RED);
else
m_balance.setForeground(Color.BLACK);
}
/**
* Deposits money into the account
*/
private void depositMoney()
{
Double amount = getAmount(m_depositAmount);
if (amount != null)
{
double balance = 0.0;
try
{
balance = m_account.deposit(amount);
}
catch (RemoteException ex)
{
ex.printStackTrace();
}
setBalance(balance);
}
else
{
showErrorMessage();
}
}
/**
* Withdraws money from the account
*/
private void withdrawMoney()
{
Double amount = getAmount(m_withdrawAmount);
if (amount != null)
{
double balance = 0.0;
try
{
balance = m_account.withdraw(amount);
}
catch (RemoteException ex)
{
ex.printStackTrace();
}
setBalance(balance);
}
else
{
showErrorMessage();
}
}
/**
* Check that the amount is valid for deposit or withdrawal
*/
private Double getAmount(JTextField amountField)
{
double amount = 0.0;
String amountString = amountField.getText();
amountString = amountString.trim();
if (amountString == null || amountString.equals(""))
amountString = null;
else
{
try
{
amount = Double.parseDouble(amountString);
}
catch (NumberFormatException nfe)
{
amountString = null;
}
}
if (amountString != null)
return amount;
else
return null;
}
/**
* Show error message dialog
*/
private void showErrorMessage()
{
JOptionPane.showMessageDialog(this, "Amount improperly specified",
"Error", JOptionPane.ERROR_MESSAGE);
}
///// Private data /////
private BankAccount m_account;
private JTextField m_id = new JTextField(4);
private JTextField m_holder = new JTextField(15);
private JTextField m_depositAmount = new JTextField(10);
private JButton m_depositButton = new JButton("Deposit this amount");
private JTextField m_withdrawAmount = new JTextField(10);
private JButton m_withdrawButton = new JButton("Withdraw this amount");
private JTextField m_balance = new JTextField(15);
/**
* Main entry point (for testing)
*/
public static void main(String[] args)
{
try
{
JOptionPane.showOptionDialog(
null,
new BankAccountClientPanel(
new BankAccountImpl(53, "Darth Vader", 10000.00)),
"Bank Account Client Display",
JOptionPane.DEFAULT_OPTION,
JOptionPane.PLAIN_MESSAGE,
null, null, null
);
}
catch (RemoteException re)
{
re.printStackTrace();
}
}
}
|
Note that it:
- Has a main method which uses a local BankAccountImpl instance to test the
class without relying on remote objects.
- Has a constructor that accepts a BankAccount; this allows for either
a local or remote (i.e. stub) instance.
- Uses calls to the BankAccount to obtain:
- The account ID
- The holder name
- The current balance (which it displays in red if the balance is
negative)
- Is basically ignorant of whether the BankAccount it is using is local or
remote (aside from the testing code in the main method).
|