[ Team LiB ] |
![]() ![]() |
21.1 Remote BankingExample 21-1 shows a class, Bank, that contains inner classes and interfaces for a remote bank client/server example. In this example, the RemoteBank interface defines remote methods to open and close accounts, deposit and withdraw money, check the account balance, and obtain the transaction history for an account. The Bank class contains all of the classes and interfaces required for the example, except for the server class, which is the class that actually implements the RemoteBank interface. This server class is shown in Example 21-2. Example 21-1 defines the following inner classes and interfaces:
A session using the Bank.Client class might look as follows (note that the command-line argument "david" is the account name and "javanut" is the password that protects the account): % java je3.rmi.Bank\$Client open david javanut Account opened. % java je3.rmi.Bank\$Client deposit david javanut 1000 Deposited 1000 wooden nickels. % java je3.rmi.Bank\$Client withdraw david javanut 100 Withdrew 100 wooden nickels. % java je3.rmi.Bank\$Client balance david javanut You have 900 wooden nickels in the bank. % java je3.rmi.Bank\$Client history david javanut Account opened at Wed Jul 12 15:30:12 PDT 2000 Deposited 1000 on Wed Jul 12 15:30:31 PDT 2000 Withdrew 100 on Wed Jul 12 15:30:39 PDT 2000 % java je3.rmi.Bank\$Client close david javanut 900 wooden nickels returned to you. Thanks for banking with us. In this example session, the bank client is running on the same host as the server. This need not be the case; the Client class looks for a system property named bank to determine which bank server to connect to. So you could invoke the client program like this (one long command line that has been broken into two lines): % java -Dbank=rmi://bank.trustme.com/TrustyBank \ je3.rmi.Bank\$Client open david javanut Example 21-1. Bank.javapackage je3.rmi; import java.rmi.*; import java.util.List; /** * This class is a placeholder that simply contains other classes and * interfaces for remote banking. **/ public class Bank { /** * This is the interface that defines the exported methods of the * bank server. **/ public interface RemoteBank extends Remote { /** Open a new account, with the specified name and password */ public void openAccount(String name, String password) throws RemoteException, BankingException; /** Close the named account */ public FunnyMoney closeAccount(String name, String password) throws RemoteException, BankingException; /** Deposit money into the named account */ public void deposit(String name, String password, FunnyMoney money) throws RemoteException, BankingException; /** Withdraw the specified amount of money from the named account */ public FunnyMoney withdraw(String name, String password, int amount) throws RemoteException, BankingException; /** Return the amount of money in the named account */ public int getBalance(String name, String password) throws RemoteException, BankingException; /** * Return a List of Strings that list the transaction history * of the named account **/ public List getTransactionHistory(String name, String password) throws RemoteException, BankingException; } /** * This simple class represents a monetary amount. This implementation * is really nothing more than a wrapper around an integer. It is useful * to demonstrate that RMI can accept arbitrary non-String objects as * arguments and return them as values, as long as they are Serializable. * A more complete implementation of this FunnyMoney class might bear * a serial number, a digital signature, and other security features to * ensure that it is unique and non-forgeable. **/ public static class FunnyMoney implements java.io.Serializable { public int amount; public FunnyMoney(int amount) { this.amount = amount; } } /** * This is a type of exception used to represent exceptional conditions * related to banking, such as "Insufficient Funds" and "Invalid Password" **/ public static class BankingException extends Exception { public BankingException(String msg) { super(msg); } } /** * This class is a simple stand-alone client program that interacts * with a RemoteBank server. It invokes different RemoteBank methods * depending on its command-line arguments, and demonstrates just how * simple it is to interact with a server using RMI. **/ public static class Client { public static void main(String[ ] args) { try { // Figure out what RemoteBank to connect to by reading a system // property (specified on the command line with a -D option to // java) or, if it is not defined, use a default URL. Note // that by default this client tries to connect to a server on // the local machine String url = System.getProperty("bank", "rmi:///FirstRemote"); // Now look up that RemoteBank server using the Naming object, // which contacts the rmiregistry server. Given the url, this // call returns a RemoteBank object whose methods may be // invoked remotely RemoteBank bank = (RemoteBank) Naming.lookup(url); // Convert the user's command to lower case String cmd = args[0].toLowerCase( ); // Now, go test the command against a bunch of possible options if (cmd.equals("open")) { // Open an account bank.openAccount(args[1], args[2]); System.out.println("Account opened."); } else if (cmd.equals("close")) { // Close an account FunnyMoney money = bank.closeAccount(args[1], args[2]); // Note: our currency is denominated in wooden nickels System.out.println(money.amount + " wooden nickels returned to you."); System.out.println("Thanks for banking with us."); } else if (cmd.equals("deposit")) { // Deposit money FunnyMoney money=new FunnyMoney(Integer.parseInt(args[3])); bank.deposit(args[1], args[2], money); System.out.println("Deposited " + money.amount + " wooden nickels."); } else if (cmd.equals("withdraw")) { // Withdraw money FunnyMoney money = bank.withdraw(args[1], args[2], Integer.parseInt(args[3])); System.out.println("Withdrew " + money.amount + " wooden nickels."); } else if (cmd.equals("balance")) { // Check account balance int amt = bank.getBalance(args[1], args[2]); System.out.println("You have " + amt + " wooden nickels in the bank."); } else if (cmd.equals("history")) { // Get transaction history List transactions = bank.getTransactionHistory(args[1], args[2]); for(int i = 0; i < transactions.size( ); i++) System.out.println(transactions.get(i)); } else System.out.println("Unknown command"); } // Catch and display RMI exceptions catch (RemoteException e) { System.err.println(e); } // Catch and display Banking related exceptions catch (BankingException e) { System.err.println(e.getMessage( )); } // Other exceptions are probably user syntax errors, so show usage. catch (Exception e) { System.err.println(e); System.err.println("Usage: java [-Dbank=<url>] Bank$Client " + "<cmd> <name> <password> [<amount>]"); System.err.println("where cmd is: open, close, deposit, " + "withdraw, balance, history"); } } } } |
[ Team LiB ] |
![]() ![]() |