} import java.rmi.Remote; import java.rmi.RemoteException; public interface Account extends Remote {
public String getName() throws RemoteException;
public float getBalance() throws RemoteException;
public void withdraw(float amt) throws RemoteException;
public void deposit(float amt) throws RemoteException;
public void transfer(float amt, Account src) throws RemoteException;
import java.rmi.server.UnicastRemoteObject; import java.rmi.RemoteException; public class AccountImpl extends UnicastRemoteObject implements Account {
private float balance = 0;
private String name = "";
// Constructor creates a new account with the given name
public AccountImpl(String aName) throws RemoteException {
name = aName;
}
public String getName() throws RemoteException {
return name;
}
public float getBalance() throws RemoteException {
return balance;
}
//Withdraw some funds
public void withdraw(float amt) throws RemoteException {
balance -= amt;
//Ensure balance never drops below zero
balance = Math.max(balance, 0);
}
//Deposit some funds
public void deposit(float amt) throws RemoteException {
balance += amt;
}
//Transfer some funds from another (remote) account into this one
public void transfer(float amt, Account src) throws
RemoteException {
src.withdraw(amt);
this.deposit(amt);
}
}
//Utility class, RegAccount, creates an AccountImpl object and then
//binds it to a name in the local registry using the java.rmi.Naming
//interface. After it's done registering the object, the class goes
//into a wait(), which allows remote clients to connect to the remote
//object. import java.rmi.Naming; import java.rmi.RMISecurityManager; public class RegAccount {
public static void main(String argv[]) {
try {
//install a security manager
System.setSecurityManager(new
RMISecurityManager());
//make an Account with the given name
AccountImpl acct = new AccountImpl("JohnAdams");
//register it with the local naming registry
Naming.rebind("JohnAdams", acct);
System.out.println("Registered account");
}
catch (Exception e) {
e.printStackTrace();
}
}
}
//The client first looks up the remote Account object using the
//java.rmi.Naming interface and then calls the deposit method on the
//Account object. import java.rmi.Naming; import java.rmi.RMISecurityManager; public class AccountClient {
public static void main(String argv[]) {
// set the RMI Security Manager, in case we need to load remote
// classes
System.setSecurityManager(new RMISecurityManager());
String url = "rmi://osprey.unf.edu/"; // server
try {
// Lookup account object
Account johnAcct =
(Account)Naming.lookup(url + "JohnAdams");
//Make a deposit
johnAcct.deposit(10000);
//Report results and balance
System.out.println("Deposited $10000 into account owned by " +
}
johnAcct.getName());
System.out.println("Current balance now is: $" +
johnAcct.getBalance());
}
catch (Exception e) {
System.out.println("Error looking up account");
e.printStackTrace();
}
System.exit(0);
}
// The default Java security policy does not allow all the network
// operations needed to dynamically load remote classes (e.g. dynamically
// load the stub required by the client). This policy grants the network
// permissions needed.
// It gives the RMI object server machine (in this case osprey.unf.edu)
// permission to open connections to the local machine
// (i.e. to the client machine).
// To run the client:
// java -Djava.security.policy=rmipolicy.txt AccountClient grant {
permission java.net.SocketPermission "osprey.unf.edu", "accept,connect";
};
// The default Java security policy does not allow all the network
// operations needed to dynamically load remote classes.
//This policy grants the network permissions needed.
// It gives any client machines permission
// to open connections to the RMI Server machine using port numbers
// 1024-65535.
// This would be necessary if the client were to dynamically load classes
// to the server, hence invoking the RMISecurityManager. If the client is
// not going to load classes to the RMI server, then the RMI server need
// not implement the RMISecurityManager. In that case, this security
// policy file is not needed.
// To run the server
// java -Djava.rmi.server.codebase=http://osprey.unf.edu/~sahuja/rmi/
// -Djava.security.policy=rmipolicy1.txt RegAccount grant {
permission java.net.SocketPermission "*:1024-65535", "accept,connect";
};
The commands are: javac Account.java javac AccountImpl.java javac RegAccount.java javac AccountClient.java
The command to do this is: rmic AccountImpl
If you want the stub and skeleton to reside in the dir /usr/local/classes, you can run the command using the –d option: rmic –d /usr/local/classes AccountImpl
The command to do this is: rmiregistry 5000 &
Without the port argument, the RMI registry listens on port 1099. Once the RMI registry is running on a host, you can register remote objects with it.
The command to run the server is: java -Djava.server.rmi.codebase=http://osprey.unf.edu/~sahuja/rmi/
-Djava.security.policy=rmipolicy1.txt RegAccount
In this example the URL is http://osprey.unf.edu/ and so we have to ensure that an HTTP server is running on osprey.unf.edu and that the necessary class files are in the rmi subdir. Also make sure that the necessary class file (e.g. the AccountImpl stub class) is in the rmi sub-dir. The RMIClassLoader uses the codebase property to determine the URL to the specified host where the needed classes are.
If the server does not need a RMISecurityManager then the command to run the server is: java -Djava.server.rmi.codebase=http://osprey.unf.edu/~sahuja/rmi/ RegAccount
The command to run the client is: java -Djava.security.policy=rmipolicy.txt AccountClient