I have a problem (maybe a fundamental understanding problem), with Java RMI. I have a "server" object and man "clients". Both are RMI objects (they implement to different Remote interfaces). The clients register themself at the server, and are stored in a list. The server will later distribute some work to the clients and fetch the result.
The problem is, that the list, where the clients are stored, seems to be not shared (I have no better description). I.e. if one client calls the server interface and registers itself, it will be added into the list, but the call seems to be only locally.
Following is an minimal example of the code:
IRemote.java
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface IRemote extends Remote {
public void remoteCall() throws RemoteException;
}
RemoteImple.java
import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.ArrayList;
public class RemoteImpl implements IRemote, Serializable {
public ArrayList<Integer> list = new ArrayList<Integer>();
@Override
public void remoteCall() throws RemoteException {
list.add(23);
System.out.println("In remote call: "+list.size());
}
}
RegAndServer.java
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RegAndServer {
public static void main(String[] args) throws RemoteException, InterruptedException {
Registry reg = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
RemoteImpl impl = new RemoteImpl();
reg.rebind("server", impl);
while(true) {
Thread.sleep(2000);
System.out.println("Server sees: "+impl.list.size());
}
}
}
Client.java
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
public class Client {
public static void main(String[] args) throws MalformedURLException, RemoteException, NotBoundException {
IRemote remote = (IRemote) Naming.lookup("//localhost/server");
remote.remoteCall();
}
}
If I start the server java RegAndServer
it will output "Server sees: 0" in a loop. If I now start the client java Client
in a different shell I get "In remote call: 1". However the server process still outputs "Server sees: 0".
Why is this? What am I doing wrong? I actually thought I had understood Java RMI :(
Your RemoteImpl
should not be Serializable
(you don't want to send a copy of it over the network, just the stub, and the runtime does that for you), and must extend UnicastRemoteObject
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
public class RemoteImpl extends UnicastRemoteObject implements IRemote {
public ArrayList<Integer> list = new ArrayList<Integer>();
public RemoteImpl() throws RemoteException {
}
@Override
public void remoteCall() throws RemoteException {
list.add(23);
System.out.println("In remote call: "+list.size());
}
}
Keep in mind that the code is executed in the sever side, even though the call is made from the client, so the message "In remote call" will appear in the server log.