Example: RMI Program
Download
Report
Transcript Example: RMI Program
Example: RMI Program
How to write it
Program an ATM Machine
•
•
•
•
•
Allow the client to withdraw, deposit, transfer
money to or from their account
Also allow to obtain the current balance
Some other stuff
ATM machine is the client
Bank with Account is the server
Write the code
4.
Write the Remote Interface, call it
Account
Write the implementation: AccountImpl
Write the server: RegAccount
Write the client: AccountImpl
5.
Stubs and skeletons will be generated
1.
2.
3.
Account.java
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.List;
/**
* Account: A simple RMI interface that represents a banking account
*
of some kind.
*
* Example 3-1, Java Enterprise in a Nutshell, 1st ed.
* Author: Jim Farley
*/
public interface Account extends java.rmi.Remote {
// Get the name on the account
public String getName() throws RemoteException;
// Get current balance
public float getBalance() throws RemoteException;
// Take some money away
public void withdraw(float amt) throws RemoteException;
// Put some money in
public void deposit(float amt) throws RemoteException;
// Move some money from one account into this one
public void transfer(float amt, Account src) throws RemoteException;
// Make a number of transfers from other accounts into this one
public void transfer(List amts, List srcs) throws RemoteException;
}
Remarks
•
Note that Account extends Remote
•
Every remote method in the interface throws
a RemoteException
•
This interface is present on the server and
on the client
AccountImpl.java
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RemoteException;
import java.util.List;
import java.util.ListIterator;
public class AccountImpl extends UnicastRemoteObject implements Account {
// Our current balance
private float mBalance = 0;
// Name on account
private String mName = "";
// Create a new account with the given name
public AccountImpl(String name) throws RemoteException {
mName = name;
}
AccountImpl.java (ctd)
public String getName() throws RemoteException {
return mName;
}
public float getBalance() throws RemoteException {
return mBalance;
}
// Withdraw so me funds
public void withdraw(float amt) throws RemoteException {
mBalance -= amt;
// Make sure balance never drops below zero
mBalance = Math.max(mBalance, 0);
}
// Deposit some funds
public void deposit(float amt) throws RemoteException {
mBalance += amt;
}
// Move some funds from another (remote) account into this one
public void transfer(float amt, Account src) throws RemoteException {
src.withdraw(amt);
this.deposit(amt);
}
Remarks
•
Since this class is remote it must implement
the UnicastRemote interface
•
The concrete methods from the remote
interface all must throw a
RemoteException
•
The rest is just POJ (Plain old Java)
Define the Server
•
•
•
•
Make an instance whose methods will be
called by the client
Register this object with the registry
Note that it contains the main{} that
defines the server
No remote exceptions here
RegAccount.java
import java.rmi.*;
public class RegAccount {
public static void main(String argv[]) {
try {
// Make an Account with a given name
AccountImpl acct = new AccountImpl("JimF");
// Register it with the local naming registry
Naming.rebind("JimF", acct);
System.out.println("Registered account.");
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Write the Client: AccountClient.java
•
•
•
•
•
Need a Security Manager (later)
Get a stub from the server by
Naming.lookup()
Make the remote calls--here getName()
and getBalance()
The URL parameter to the lookup routine
returns the remote object it references
main(){} here is the client.
AccountClient.java
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
public class AccountClient {
public static void main(String argv[]) {
try {
// Lookup account object
// A ccount jimAcct = (Account)Naming.lookup("JimF");
A ccount jimAcct = (Account)Naming.lookup("rmi://thecity.sfsu.edu/JimF");
// Make deposit
jimAcct.deposit(12000);
// Report results and balan ce.
System.out.println("Deposited 12,000 into account owned by " +
jimAcct.getName());
System.out.println("Balance now totals: " + jimAcct.getBalance());
}
catch (Exception e) {
System.out.println("Error while looking up a ccount:");
e.printStackTrace();
}
}
}
Running the Example ATM
•
Compile the java files: javac
Account*.java
•
Create stub from AccountImpl:
rmic AccountImpl
Start the registry: rmiregistry
Start the server: java RegAccount
Start the client: java AccountClient
•
•
•
What is Missing
•
•
•
•
•
A Security Manager
A Security Policy
A Codebase
Compile and Execution commands that
incorporate these
An appropriate deployment strategy
Security Manager
•
•
•
•
•
If your application only runs locally (sandbox) then
there is no need for security
But RMI is designed to run on networks and the
Internet
Hence the need for security
The Security Manager is a Java class that checks
whether certain operations are permitted
Is available under
java.lang.SecurityManager
Security Manager (ctd)
•
•
•
•
Checks permissions according to a security
policy
Infractions of permissions cause a
SecurityException
Set up by issuing:
System.setSecurityManager (new
RMISecurityManager());
Enclose critical code in try block
Permissions
Set by a security policy as written by the
programmer
• For purposes of testing a blanket granting of
permissions can be issued:
•
permission java.security.AllPermission;
Then after deploying be a bit more restrictive:
grant{
•
permission java.net.SocketPermission “*:1024-65535”,
“connect, accept, resolve”;
permission java.net.SocketPermission “*:80”,
“connect”;
};
Codebase
When starting the server indicate the
download directory by means of a
codebase property: For example
java -D ... Djava.rmi.server.codebase=http:/
/localhost/download/ xxxServ
This represents the URL location from which
the stubs can be downloaded
Note the final slash “/” on the URL
•
Running the Client
•
•
Need to include security with -D
Start the Client:
•
java -Dsecurity.policy=sec.policy
xxxClient
•
sec.policy needs a path
•
Do this for both server and client