If there is n banks, each bank has M ATM, each ATM can use Draw yourself (nonsense), you can also insert a bank of the bank's money, for example, Industrial and Commercial Bank of Bank. card. In short, there is a place called CCH (Central ... House, can't stand up :) to handle this type of withdrawal. In addition, the ATM also has a deposit function (true advanced, two machine integration), and the CCH is also responsible for processing other bank deposits. Of course, ATM can also only check it, how much is it in Account. In general, Account cannot be negative (do not consider issues such as decimal points, and the integersion is OK). Each bank in the CCH corresponds to a bank account, records how many deposits per bank (that is, all the BALANCE of this bank), whenever it is transaction to update. (Purely add trouble, this information is actually published to people outside of the bank). It is not necessary to maintain high transaction, that is, when using similar Transaction to half, the server of the target bank or CCH suddenly hangs. All Account Records are OK with a simple file operation.
Exception situation, what if the REQUEST target bank's server not available? It is usually a refusal to WITHDRAWAL. (For example, you use the boss to go to the ICBC machine to take money, the exchange server finds that the work of the ICBC is not connected, of course, I can't give you a lot of money. How to do the machine crazy overdraft, I will not admit it when I am on the payment, and I will not vomit blood. However, deposit operation is acceptable because there is no risk to the bank, and the CCH is to record such operations, and when the bank's server online is updated. (Still the previous example, if the Account is not there? Or that sentence, the risk is very low for the bank). Obviously, Query is affirmed when the target bank NOT AVAILABLE is affirmative.
The interface provided by Bank (Banki.java) is simple: 2 sets of 6, the bank is operated, taken, check, and remote access ("remote" here refers to the operation of the owner's bank).
CCH (cchi.java) The features to be achieved: Update the Bank's Account. Help the Bank Transfer necessary operation, (ie remote operation), CCH to manage Routing. When the target bank is not online, it is necessary to help record unfinished operations when the target bank is on the target, reminded it to update Account. (Usually remote operation, because the system structure is ATM-> Bank-> cch-> transote bank. Standing on the CCH point, it is to do is Routing Transaction and the necessary update. To provide an interface to the bank, when the bank is on the line, the CCH is required to provide a record that does not complete the operation to update your account.
ATM is just simply collecting the necessary information to the user, then call the corresponding RMI, because Account cannot be negative, so the error message is simply identified by a series of negative numbers. (If you don't think about it, don't think about it. If you want to try it, the local bank passed all the information to the CCH, cch View this Transaction Which bank, then pass the Transaction past (actual Up to TCP / IP, remote Banking occurs, contains the name of the target bank, this name is equivalent to a header for CCH, and the CCH peels off this Header to the target bank), standing in the point of Bank, this Request, whether it is from the CCH or from ATM, is the same, there is no difference.
There is a MAP (BankName, Map (Accno, Amount) container in the CCH, used to record unfinished operations, when the bank is online, first query your name in the container, if you find it, you explain that there is no operation Need to be updated synchronously, get the corresponding MAP (ACCNO, AMOUNT) to update one by one.
The whole project is like this, concrete species.
//ATM.javaimport java.io. *; Import java.rmi. *; Import java.util. *; Public class atm {string bankname; string accno; list banklist; public atm () {BankName = new string (); Accno = new string (); banlist = new vector (); banlist.add ("symonwealth"); BankList.Add ("hsbc");} public static void main (string [] args) throws exception {atm myatm = new ATM (); String str = new String (); // stream from stdin BufferedReader sin = new BufferedReader (new InputStreamReader (System.in)); System.out.println (myatm.banklist); System.out.print ( " Enter Your Bank Name (CommonWealth IS Default): "); myatm.bankname = sin.readline (); if (myatm.bankname.equals (")) MyATM.Bankname = (String) MyATM.BankList.Get (0) ; //System.Println; // check if the bank name is valid boolean found = false; iterator myit = myatm.banklist.iterator (); While (myit.hasnext ()) {if (MyATM.Bankname.equals (Myit.Next ())) {Found = true; break;}} f (! found) {system.out.println ("Bank is not exist ! Check Again! "); System.exit (0);} // Get Account Number: // A Flaw Here: Doesnt Check The Validity of Account // Until Transaction Happens. System.out.Print (" Enter your account Number : "); Myatm.accno = sin.readline (); // connnect to bank server Banki myTransaction = (Banki) Naming.lookup (" CommonWealth ");
While (true) {system.out.println ("Welcome! / R / N" "Press D: Deposit / R / N" "Press W: withdrawal / r / n" "Press Q: query / r / N " " press any other key to exit "); // get transaction type str = sin.readline (); system.out.println (" please wait ... "); if (str.equals (" D " )) {// Get Money System.out.println ("Input The Amount of Money Please:"); int Amount = Integer.Decode (Sin.Readline ()). IntValue (); // Decide Which Kind of RMI To Be called. if (MyATM.Bankname.equals ("CommonWealth")) Amount = MyTransaction.Deposit (MyATM.CCNO, Amount); Else Amount = MyTransaction.Deposit (MyATM.ACCNO, AMOUNT, MyATM.Bankname); // CHECK The return value. if (amount == -999) {System.out.println ("Account Not Exist!"); Break;} else if (Amount == -99) {System.out.println ("Your Transaction Has Finished./R/N" MyATM.Bankname "Is Not Available Now, You CAN" Deposit Only. " ); Continue;} else if (amount == -995) {system.out.println ("cch is not available now," "You cannot do any remote transactions." "Try Later!");
Break;} system.out .println ("==== Your new balance:" Amount "====");} elseiff (Str.Equals ("W")) {system.out.println "INPUT The Amount of Money Please:"); Int Amount = Integer.Decode (SIN.Readline ()). INTVALUE (); // Decide Which Kind of RMI To Be Called. IF (MyATM.Bankname.Equals ("Commonwealth ")) Amount = myTransaction.withdrawal (MyATM.ACCNO, Amount); Else Amount = MyTransaction.withdrawal (MyATM.ACCNO, Amount, MyATM.Bankname); if (Amount == -999) {System.Out.println (" Account not exist! "; break;} else if (amount == -998) {system.out.println (" insufficient funds! "); Continue;} else if (Amount == -997) {System.out. Println (MyATM.BANKNAME "Is Not Available Now! Try Later Please."); Break;} else if (Amount == -995) {System.out.Println ("cch is not available now," "you cannot do any remote Transactions. " " Try Later! "); Break;} system.out .println (" ==== Your new balance: " Amount " ==== ");
} else if (Str.Equals ("Q")) {Int Amount; // Decide Which Kind of RMI to Be Called. IF (MyATM.Bankname.equals ("CommonWealth")) Amount = MyTransaction.Query (MyATM.ACCNO Else Amount = MyTransaction.Query (MyATM.ACCNO, MyATM.Bankname); if (Amount == -999) {System.out.Println ("Account Not Exist!"); Break;} else if (Amount == -997) {system.out.println (MyATM.Bankname "is not available."); Break;} else if (Amount == -995) {system.out.println ("cch is not Available Now, " " You cannot do any remote transactions. " " try latter! "); break;} system.out.println (" ==== Your balance: " Amount ====") ; Else Break;
} // while loop}} // Banki.java/ Bank System Supplies: // 1. Two Sets of RMI To ATM, One for ITS OWN Banking, One For Remote // Banking. ~ DONE. / / 2. Accepting Connection from CCH, Which SHOULD PRETEND HANDLING THE ONE. ORDINARY ATM. ~ DONE. //3. IF CCH WAS DOWN, LOCAL Banking Should Be Still Working. in this // Case, Bank Server SHOULD HAVE A log system to record the change be used to update the bankbook in cch //hen it next logs on. ~ done .//th, assuming the atm belongs to cw (commonwealth). ~ done. import java.net.MalformedURLException; import java.rmi *; public interface BankI extends Remote {// local banking:. int withdrawal (String accno, int amount) throws RemoteException; int deposit (String accno, int amount) throws RemoteException; int Query (String Accno) THROWS RemoteException; // Remote Banking with an additional "BankName": int withdrawal (string accname ": String Bankname throws MalformedURLException, RemoteException; int deposit (String accno, int amount, String bankname) throws MalformedURLException, RemoteException; int query (String accno, String bankname) throws MalformedURLException, RemoteException;} ///: ~ // Bank.javaimport java.net . *; import java.rmi *;. import java.rmi.server *;. import java.util *;. import java.io *;. public class Bank extends UnicastRemoteObject implements BankI {static String datafile; // this variable is To log the fund of bankbook when cch is down. static int pending = 0; static map acc = collections.synchronizedmap (new hashmap ());
// two things to be done in the constructor:. // 1 read acc information into Map acc ~ Done // 2 check CCH if there are any transactions unfinished ~ Done public Bank (String bankname) throws MalformedURLException, RemoteException.... {try {datafile = bankname "accinfo.txt"; // open data file, read everything into a Map object BufferedReader readacc = new BufferedReader (new FileReader (datafile)); String tmpacc; while ((tmpacc = readacc.readLine ( ))))! = null) {acc.put (TMPACC, new integer (readacc.close ());} readacc.close ();} catch (exception e) {E.PrintStackTrace (); throw new runtimeException (e) } Try {cchi mycch = (cchi) Naming.lookup ("cchserver"); map mymsg = mycch.check (bankname); if (mymsg == null) System.out.Println ("No Pending Transaction."); Else { System.out.Print ("Handling the Pending Transactions ..."); item myit1 = mymsg.keyset (). Iterator (); iterator myit2 = mymsg.keyset (). Iterator (); item myit3 = mymsg.keyset ) .iterator (); while (myit1.hasnext ()) {ac.put (Myit1.next (), new integer ((Integer) acc.get (Myit2 // ====== ^ Key === =================================================================================================================================================================================
.next ())). INTVALUE () // ======= ^ Original value ============================ ===== (Integer) Mymsg.get (Myit3.Next ()))). INTVALUE ())); / / =================== ^ Pending value =======================} // Write back to the file synchronizedatafile ("finshed.");} } catch (notboundexception e) {// if cch is not available, just ignore this step; system.out.println ("cch doesn't work.");}} // ========== =============== local Banking ========================================================================================================================================================================================================================================= 999 means that the account is not exist // return -998 means that the amount is too large public int withdrawal (String accno, int amount) throws RemoteException {if return -999.. (acc.containsKey (accno)!); if ((Integer) acc.get (accno)). INTVALUE () // update bankbook in cch try {cchi myupdate = (cchi) Naming.lookup ("cchserver"); MyUpdate.Update ("CommonWealth", Pending - Amount); PENDING = 0;} catch (notboundexception e) {PENDING = -amount;} catch (Exception E) {system.err.println (e);} // Write Back to the file synchronizedatafile (ACC); Return (Integer). INTVALUE ();} PUBLIC INT Deposit (String Accno, Int Amount) THROWS RemoteException {IF (! Acc.containskey (ACCNO)) Return -999; Else {// Update Map Acc. ACC.PUT (Accno, New Integer ((Integer) ACC .GET ()). INTVALUE () AMOUNT); // Update BankBook IN CCH Try {cchi myupdate = (cchi) Naming.lookup ("cchserver"); MyUpdate.Update ("Commonwealth", Pending Amount) Pen Ding = 0;} catch (notboundexception e) {pending = amount;} catch (exception e) {system.err.println (e);} // Write Back to the file synchronizedatafile (ACC); RETURN (Integer) Acc.get (ACCNO)). INTVALUE ();}} public int query (String Accno) THROWS RemoteException {if (! Acc.containskey (ACCNO)) RETURN-999; Else Return (Integer) Acc.get (Accno) ) .intValue ();} // ========================= transote banking = =================================== // Return -999 Means That the account is not exist. // return -998 means That the Amount IS too large. // return -997 means that the target bank is not available. // return -996 means that the transaction is remote deposit. // return -995 means that the CCH is not working. public int withdrawal (String accno, int amount, String bankname) throws MalformedURLException, RemoteException {CCHI mywithdrawal; int tmp; try {mywithdrawal = (CCHI) Naming.lookup ( "CCHserver"); tmp = mywithdrawal.withdrawal (bankname, accno, amount);} catch (NotBoundException e) {return -995;} if (tmp! = -999 && tmp! = -998 && tmp! = -997) Mywithdrawal.Update ("Commonwealth", BankName, -AMount; Return TMP;} public int Deposit String Accno, Int Amount, String BankName) Throws Malformedurlexception, RemoteException {cchi mydeposit; in T TMP; try {myDeposit = (cchi) Naming.lookup ("cchserver"); TMP = mydeposit.Deposit (Bankname, Accno, Amount);} catch (notboundexcection e) {return -995;} if (TMP == 996) {MyDeposit.Update (BankName, Amount); Return -996;} IF (TMP! = -999) MyDeposit.Update ("Commonwealth", BankName, Amount; Return TMP; } Public int query (String accno, String bankname) throws MalformedURLException, RemoteException {CCHI myquery; try {myquery = (CCHI) Naming.lookup ( "CCHserver");} catch (NotBoundException e) {return -995;} return myquery. Query (banname, accno);} // =================================================================================================================================================================================================== ============== Private void synchronizedatafile (map ACC) {Try {PrintWriter PW = new brewritedwriter (new filterwriter)); SYNCHRONIZED (ACC) {Iterator IMAP = ACC Keyset (). Iterator (); iterator imapprev = acc.keyset (). Iterator (); situation (imap.hasnext ()) {PW.Println (IMap.next ()); // key PW.Println (ACC .get (imapprev.next ()))); // value}} PW.Close ();} catch (exception e) {system.err.println (E.GetMessage ));}} // ========================= main () ================ ===================== Public static void main (String [] args) throws exception {if (args.length <1) {Bank MyBank = New Bank (" Commonwealth "); Naming.rebind ("CommonWealth"; System.out.println;} else {bank mybank = new bank (args [0]); Naming.Rebind (Args [0], MyBank); System.out.println (Args [0] "Bank Ready to Go");} // stream from stdin bufferedreader sin = new buffredreader (NEW INPUTSTREAMREADER (System.IN)); system.out.println (" TYPE / "Exit /" To Shutdown The Server Properly. "); // EXPECTING" EXIT "while (! Sinretline (). Equals (" exit ")); system.out.print (" EXITING ... " ); If (args.length <1) naming.unbind ("CommonWealth"); else naming.unbind (args [0]); system.exit (0);}} // cchi.java// Central clearing house CCH) 's Job: // 1. Maintaining Account of Bank Which IS Amount of The Whole Funds In ///1 Bank. In Practice, // i. When Local Banking Occurs, Bank System Will Make Request // THROUGH RMI TO UPDATE Thi S Accounts Banking Occurs, Cch Will Update Both Both Bank Accounts // Involved. ~ Done .//2. Routing Transactions Between Banks. When Remote Banking Occurs, // Cch Will Call THE RMI methods which belongs to the target bank server.// in this case, CCH itself shoudl supply a set of RMI methods to be // called by the bank making request. ~ Done .// 3. maintaining a log system to record unfinished deposit Target Bank is not available. ~ DONE.IMPORT JAVA.NET. *; import java.rmi. *; import java.util. *; public interface CCHI extends Remote {// 1.i void update (String bankacc, int fund) throws RemoteException; // 1.ii void update (String srcbank, String dstbank, int fund) throws RemoteException; // 2. int withdrawal ( String bankname, String accno, int amount) throws MalformedURLException, RemoteException; int deposit (String bankname, String accno, int amount) throws MalformedURLException, RemoteException; int query (String bankname, String accno) throws MalformedURLException, RemoteException; // 3. Map Check (String Bankname) throws remoteException;} // cch.javaimport java.net. *; import java.rmi. *; import java.rmi.server. *; import java.util. *; import java.io. *; public class CCH extends UnicastRemoteObject implements CCHI {Map book = new HashMap (); Map bankmsg = new HashMap (); String datafile = "bankbook.txt"; public static void main (String [] args) throws Exception {CCH mycch = new CCH (); if (arg S.LENGTH <1) {Naming.Rebind ("cchserver", mycch; system.out.println ("cchserver ready to go");} else {naming.rebind (args [0], mycch); system.out .println (Args [0] "Ready to Go");} // stream from stdin bufferedreader sin = new buffredreader (system.in)); system.out.println ("type /" exit / "to Shutdown The Server Properly. "); // evECTING" exit "while (! sinretline (). Equals (" exit ")); system.out.print (" exiting ... "); if (args.length <1) Naming.unbind ("CCHServer"); Else naming.unbind (args [0]); system.exit (0);} // similar to the bank server constructor: // read bank information INTO MAP ACC. ~ DONE PUBLIC CCH () throws receexception {Try {// open data file, read everything into a Map object BufferedReader readacc = new BufferedReader (new FileReader (datafile)); String tmpacc; while (! (tmpacc = readacc.readLine ()) = null) {book.put (tmpacc, new Integer ());} readacc.close ();} catch (Exception E) {E.PrintStackTrace (); throw new runtimeException (e);}} public int Deposit (String Bankname, String Accno, Int Amount "Throws malformedurlexception, remoteException {Banki mydeposit; try {myDeposit = (Banki) Naming.lookup (BankName);} catch (notboundexception e) {// map (Bankname, Map (accno, amount)) System.err.println (Bankname "Doesn't Work. I'll Handle It.From Cch.Deposit"); if (! Bankmsg.containskey (Bankname)) {Map Msg = New HashMap (); msg.put Accno, New Integer (Amount); BankMsg.Put (BankName, MSG);} else {((HashMap) Bankmsg.get (BankName)). PUT (Accno, New Integer (Amount));} System.err.Println ("I'm returbosit"); return -996;} return mydeposit.Deposit (accno, amount); } // return -997 means that the target bank is not available public int query (String bankname, String accno) throws MalformedURLException, RemoteException. {BankI myquery; try {myquery = (BankI) Naming.lookup (bankname);} catch ( NOTBOUNDEXCEPTION E) {system.err.println ("I'm return"); return -997;} return myquery.query (acpen);} public void update (String BankAcc, Int Fund) Throws THROWS RemoteException {BOOK.PUT (BankAcc, New Integer). INTVALUE () FUND)); // Write Back to the file try {printwriter PW = New PrintWriter (New BufferedWriter (New BufferedWriter FileWriter (DataFile)); item iMap = book.keyset (). Iterator (); iterator imapprev = book.keyset (). Iterator (); while (imap.hasnext ()) {PW.Println (IMap.Next ))); // Key PW.Println (BOOK .get (imapprev.next ())); // value} PW.close ();} catch (exception e) {system.err.println (E.GetMessage ());}} public void update (String Srcbank, String dstbank, int fund) throws RemoteException {update (srcbank, -fund); update (dstbank, fund);} // return -997 means that the target bank is not available public int withdrawal (String bankname, String accno, int. Amount) THROWS MALFORMEDURLEXCEPTION, RemoteException {Banki MyWithdrawal; Try {mywithdrawal = (Banki) Naming.lookup (Bankname);} catch (notboundexception e) {system.err.println ("i ' . M returning -997 from CCH.withdrawal "); return -997;} return mywithdrawal.withdrawal (accno, amount);} public Map check (String bankname) throws RemoteException {return (Map) bankmsg.remove (bankname);} } // hsbcaccinfo.txt 006100000510000071000 // CommonwealthCincinfo.txt 006100000510000071000 // Bankbook.txt Commonwealth3000HSBC3000 // readme.txt The Are Five Source Files in The Assignment. Files with SUFFIX 'I' '' '' '' '' '' '' '' '' ' Compile Them Following Steps Below. Javac cchi.javajavac cch.javajavac bani.javajavac bank.javajavac atm.java 2. Create stubs and skeletons. RMIC CChrmic Bank 3. The set up the registry. Under 32-bit windows you say: Start RMIREGISTRY ON UNIX, The Command IS: RMIREGISTRY & 4. Start. Java Cchjava Bank (and 'Java Bank HSBC' to Start a Remote Bank) Java ATM 5. Here is some guidiness. a) Do not run same bank server or CCH server twice. Otherwise, the previous one will be replaced by the new server since they use bank name to bind to rmiregistry. b) ATM is assumed as CommonWealth's property. That is, When ATM Prompts you to input the bank name, you can just enter and don't need TOINECT CommonWealth. and you cannot log on to hsbc to do local banking. c) Basically, System Won't Accept Negative Balance, So You Cannot Withdraw Money More Than You Have in The Account. d) Only Two Banks (Commonwealth & HSBC) Are Supported in this System now. e) Both Commonwealth and HSBC have three accounts:. 005,006,007 And they all have 1000 balance intially So in CCH's bankbook, the intial balance of the two banks is 3000, respectively this blog can not upload attachments Mody, post codes more nausea.