Message Passing

Hi, everybody.

I'm new to RMI and I fear I may be thinking too much in an MPI paradigm but I'm looking for a way for a more "live" communication between my client and server applications.

I wrote a little toy application to prove a couple of concepts before I built something more important and it's a good thing I did because I've met with incomplete success.

The toy-app is some producer/consumer code where the producer posts Strings to a (self-defined) Buffer object at random time-intervals (0-10 seconds) and the consumer gets them out each String as soon as it is available.

The Producer has a method called start that takes a Buffer object. When I put the producer in the rmiregistry, it takes the Buffer from the client (the consumer) and pushes strings into it but they never become available in the client.

When I pass an object reference over RMI is it still the same object, or is it just a snapshot of the one I passed?

Producer.java:

import java.io.Serializable;

import java.net.InetAddress;

import java.rmi.Naming;

import java.rmi.RemoteException;

import java.rmi.server.UnicastRemoteObject;

import java.util.Random;

publicclass Producerextends UnicastRemoteObjectimplements iProducer{

class runnerextends Thread{

Buffer buffer;

int num;

public runner(Buffer buffer,int num){

this.buffer = buffer;

this.num = num;

}

publicvoid run(){

Random generator =new Random();

for(int i = 0; i < num; i++){

buffer.push("This is string " + i);

System.out.println("pushing \"This is string " + i +"\"");

int r = Math.abs(generator.nextInt() % 10);//between 0 and 10

try{

Thread.sleep(r * 1000);

}catch(InterruptedException e){

System.err.println(e);

}

}

System.out.println("closing buffer");

buffer.close();

}

};

Thread r;

public Producer()throws RemoteException{

super();

}

publicvoid start(Buffer buffer,int num)throws RemoteException{

System.out.println("recvd start");

r =new runner(buffer, num);

r.start();

}

publicstaticvoid main(String[] args)throws Exception{

String hostname = InetAddress.getLocalHost().getHostName();

String servicename ="//" + hostname +"/Producer";

Producer producer =new Producer();

Naming.rebind(servicename, producer);

System.out.println("Producer bound");

}

}

iProducer.java:

import java.rmi.Remote;

import java.rmi.RemoteException;

publicinterface iProducerextends Remote{

publicvoid start(Buffer buffer,int num)throws RemoteException;

}

Consumer.java:

import java.rmi.Naming;

publicclass Consumer{

publicstaticvoid main(String[] args)throws Exception{

String host =null;

if(args.length != 1)

host ="localhost";

else

host = args[0];

String serviceName ="//" + host +"/Producer";

iProducer producer = (iProducer) Naming.lookup(serviceName);

//iProducer producer = new Producer();

Buffer buffer =new Buffer();

if(producer ==null)

thrownew Exception("Null remote object");

producer.start(buffer, 1);

String ln;

while((ln = (String)buffer.pop()) !=null){

System.out.println(ln);

}

}

}

[6605 byte] By [daniel.t.milesa] at [2007-10-2 11:10:59]
# 1
I suggest you back and read the tutorial.
cooper6a at 2007-7-13 3:53:28 > top of Java-index,Core,Core APIs...
# 2
I have read several tutorials and none have answered my question. Can you reccomend a tutorial that does?
daniel.t.milesa at 2007-7-13 3:53:28 > top of Java-index,Core,Core APIs...
# 3

OK

It appears you are trying to implement the standard producer/consumer logic using threads in RMI.

RMI multi-threads methods on the RMIServer so you do not need threads.

You have an inner class, runner that is the thread.

Somehow it looks like you are trying to start the server inner class, runner, from the client.

Truthfully, I'm lost in your code.

You're missing some basic building block of RMI inplementation, which is why I suggested going back to the tutorial. It's the concept you seem to be missing. The server and all its objects are not visable to the client except through the remote proceedure call (rmi.)

cooper6a at 2007-7-13 3:53:28 > top of Java-index,Core,Core APIs...
# 4

Your basic problem is that you have misread RMI. When you pass an object as a parameter to a remote method call, then it is a copy, and the client will not know about any changes made by the server.

If you want client notification, then you need to annotate the passed object (class) as a UnicastRemote object. In that case, the server receives just a reference to the client on the object computer, and will make "callbacks" when inserting stuff into the "passed object".

I don't know how far you are going with this design, but strongly advise you to either confine it to a LAN, or find another technology.

bschauwejavaa at 2007-7-13 3:53:28 > top of Java-index,Core,Core APIs...