I have used RMI (in Java 6) successfully before in a number of projects, where there was a well-defined client/server relationship. When I have been using it in previous projects, I have created a well-defined interface JAR which is deployed to both client and server, and start the RMI Server with the "-Djava.rmi.server.codebase=... -Djava.rmi.server.hostname=localhost -Djava.security.policy=...\server.policy"
I am trying to now use RMI to perform bi-directional communication, in order to build a basic cluster. Specifically, I want B (worker "client") to register with A (central "server"). However, I want B to implement the java.rmi.Remote interface and pass a reference of himself back to A. The main motivations of this are: * A doesn't need to know where all the instances of B reside (they can be anywhere on the internet, if need be!) * Once an instance of B has registered with A, then A can control B (ie, perform tasks on B at A's discression).
My issue is that whenever I try to pass this Remote interface (B) as a parameter back to A, I get the following exception on B (but the remote call will occur successfully if I pass null instead, which makes this explanation unlikely: http://download.oracle.com/javase/1.4.2/docs/guide/rmi/codebase.html#section6 ):
ERROR com.mycompany.server.dao.ServerInterfaceImpl - RMI registerWorker() failed: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: com.mycompany.worker.MyWorker (no security manager: RMI class loader disabled)
Where: * A (implementation) = com.mycompany.server.dao.ServerInterfaceImpl * B = com.mycompany.worker.MyWorker
(Q1) Is it possible to do what I am describing? Would someone be able to write a super-basic version of what I am describing (ie, client B registers with server A, and then passes a reference to B's Remote interface to A so that A can control B)? I originally assumed I had some obscure typo/config issue, but I am starting to this this task is not possible...
(Q2) If what I am trying to do is not possible, another idea is to turn each instance of B into an RMI Server, and to get A to connect to B after B has connected to A. The main reason I do not want to do this is that I would expect A and (each instance of) B will separated by the internet, and only A would have a public internet address (each instance of B would not have a public IP address, and could be stuck behind various firewall(s), such that it is easier for B to connect to A than vice-versa) ... at the end of the day, once B has connected to A, I just want to facilitate bi-directional communication!
(Q3) I was considering having heartbeating between A and B. One possibility could be to use these heartbeats for each B to poll A with any outstanding work... I would prefer for A to asynchronously control B, however...