BankAccountClient
Home ] Up ] BankAccount ] BankAccountImpl ] BankAccountServer ] [ BankAccountClient ] Running the Example ]

 

 

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).
 
The page was last updated February 19, 2008