Granny's Programming Pearls
"inside of every large program is a small program struggling to get out"
JavaRanch.com/granny.jsp
The moose likes Distributed Java and the fly likes Q: RMI-  send objects, multiple servers Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Java » Distributed Java
Bookmark "Q: RMI-  send objects, multiple servers" Watch "Q: RMI-  send objects, multiple servers" New topic
Author

Q: RMI- send objects, multiple servers

Marc Wrench
Greenhorn

Joined: Feb 02, 2004
Posts: 5
Lo folks,
A while ago I posted a question on sending objects over CORBA, and was advised to use RMI. I've eventually come around, and am now considering using RMI. So... I have a few questions:
1) How would I send an object (containnig sub-objects) across RMI to my server?
2) How can I keep track of multiple servers? At the moment I am using:
��myRMIInterface myServerObject = (myRMIInterface) Naming.lookup("rmi://"+serverName+"/myRMIImplInstance");
But that only allows 1 server per IP? How do I contact servers if I dont know their IP before hand? eg. is there an equivalent to the CORBA nameservice?
Thanks for any help,
M Wrench
Chris Shepherd
Ranch Hand

Joined: Jun 27, 2000
Posts: 286
1) How would I send an object (containnig sub-objects) across RMI to my server?

Once you have your RMI connection in place, that is almost as easy as passing an object reference into a method(and done exactly the same way). The only additional restriction is that you have to make the objects that are being passed serializable. You'll have to ask specific questions about the stuff you don't know how to do in RMI. To put it all in this post would get a little long. Go look at some of the past post about RMI. There has been enough info posted here that it shouldn't be too hard to pisk up. Plus you can always ask questions when you get stuck on something.
2) How can I keep track of multiple servers? At the moment I am using:
myRMIInterface myServerObject = (myRMIInterface) Naming.lookup("rmi://"+serverName+"/myRMIImplInstance");
But that only allows 1 server per IP? How do I contact servers if I dont know their IP before hand? eg. is there an equivalent to the CORBA nameservice?

Do you need multiple servers(machines running code) or multiple server interfaces(multiple interfaces that could all run on the same machine)?
You can have more than one interface running on a machine. They just all have to be created from unique interfaces. You can't run 2 myRMIInterface servers from the same machine(or even on different machines using the same registry) I don't think. The registry would get confused, or only pass the reference to the last one registered.
To answer the last part of your question, you can set up the registry on a known machine and have it point to RMI servers somewhere else(next room, next continent). It is based off of the servers calling in to the registry when they start up and declaring the interfaces they support.
The registry is like a simple DNS. You call it requesting a link to a certain interface. If it has registered one matching your request, it returns the location info and RMI trys to connect to that server directly. So yes, the RMI nameserver is the registry running at a known address.
hope this helps,
Chris
Marc Wrench
Greenhorn

Joined: Feb 02, 2004
Posts: 5
Hi,
Thanks for the reply! I can send objects from client to server now, thanks. When people said it was easy, I didnt believe it was this easy!
As for multiple servers - I require many machines running my server code. Ideally, I start a number of servers (each on a separate machine), and then plug that number into my client, which creates a link to each server (in a vector), and then iterates through the vector, sending data to be worked on (ie. a form of parallelism).
It looks possible by doing something like:
1) Starting each server with a name as an argument:
��java server aName
2) Using this code in the server:
��myRMIImpl implementation = new myRMIImpl(args[0]);
3) Starting the client with the number of servers as an argument:
��java client 3
4) Using this code in the client:
��sNum = args[0];
��for (i=0; i<sNum; i++) {��
����myRMIInterface sNumAsString = (myRMIInterface) Naming.lookup("rmi://"+serverName+"/"sNumAsInt);
��}
Is that along the right lines?
[EDIT] Yeah, that all seems to work, which leaves my final question, below. [/EDIT]
Does RMI play nice with threading? eg. for each server, could I make a thread (on the client), and therefore talk to the servers simultaneously?
[EDIT] That also seems to work fine. [/EDIT]
Thanks for any help,
M Wrench
[ February 02, 2004: Message edited by: Marc Wrench ]
[ February 02, 2004: Message edited by: Marc Wrench ]
Marc Wrench
Greenhorn

Joined: Feb 02, 2004
Posts: 5
Hi again,
Everything seems to be going great. I had some problems with sending a vector, but I've solved them, and everything works great.
Except.. (and this is really basic) when I go to do a real world test (ie. actually use other computers, rather than run everything on the development machine), how do I specify where the rmiregistry is running?
I can specifiy it for the client, and the contact the servers using
naming.lookup("rmi://"+specified_location+"/"+i).
However, each server seems to presume the rmiregistry is running on the same machine it is on, and since I have multiple servers (on multiple machines), this is a problem.
So... how do I tell each server where the rmiregistry is, so they can register with it?
Also, a repeat of my last post, how thread-safe is RMI?
Thanks for any help,
M Wrench
Chris Shepherd
Ranch Hand

Joined: Jun 27, 2000
Posts: 286
I believe that the actual process of transmitting the data back and forth from the server is thread safe, but I don't know if it blocks your port while waiting for the return value or if it allows other threads to use the port while it waits for a return. My guess is that it blocks other RMI transactions until it gets its reply. That is a total guess tho. It should be easy to test.
Grrr. I seem to have mislead you a bit. I mentioned before that you could keep a remote RMI server to point to different machines that were running your server software. This doesn't appear to be true. However, the same effect can be had if you are running a nameserver on your network.
If you are running a nameserver, then each of your servers just needs to be registered with it so that when you use the network name in your Naming.lookup() instead of the IP, it will be resolved into the ip you need for each server. From there, everything runs as normal.
If you do not have a name server, I think you could still make it work if you set up an "RMI server" server that lived at a known ip. your servers all connect to it momentarily when they start up and declare their IP and what they are serving. You store that away. Then they disconnect and start up their own registry to await the calls from your client. Your client(s) connect to the server server and ask it about a specific service. You cross reference it and return the IP that has been registered. Your client takes the IP and uses it to make a direct call to the real server for the service you need.
I apologize for misleading you a bit. Just goes to show you that even when you think you know how something works, its still possible to be wrong.
I'm glad it seems to be going well for you so far. I hope this little wrinkle in the process won't set you back too far.
Chris
Marc Wrench
Greenhorn

Joined: Feb 02, 2004
Posts: 5
Originally posted by Chris Shepherd:
I believe that the actual process of transmitting the data back and forth from the server is thread safe, but I don't know if it blocks your port while waiting for the return value or if it allows other threads to use the port while it waits for a return. My guess is that it blocks other RMI transactions until it gets its reply. That is a total guess tho. It should be easy to test.

Oh. Thats bad. What is an easy way to test this assumption? Is there a way to get around if, perhaps by using a different port for ach connection?
[EDIT] Ok, I set up 2 servers on the local machine, each set to count to some high number in a for loop, and output the current number, then return a string. I set the client to create 2 threads, 1 to talk to each server. I set it all going. Both servers output their incrementing numbers at the same time (so they are both running simultaneously?). Both servers returned their string when they finished.[/EDIT]

If you are running a nameserver,
...
If you do not have a name server,

Is there one I can use, or would I have to write it myself?

If you do not have a name server, I think you could still make it work if you set up an "RMI server" server that lived at a known ip. your servers all connect to it momentarily when they start up and declare their IP and what they are serving. You store that away. Then they disconnect and start up their own registry to await the calls from your client. Your client(s) connect to the server server and ask it about a specific service. You cross reference it and return the IP that has been registered. Your client takes the IP and uses it to make a direct call to the real server for the service you need.

So I use a known server to create a sort of server-name -> IP mapping table? Would this have to be done every time a connection is made?

I'll explain my problem, so you have an idea of whats going on.
I have 1 'client', which reads in a load of data. The client then makes a thread for each server, and gets some of the data allocated. Each thread then takes to its associated server (over rmi, corba or whatever), and sends some of the data to the server. The server does some calculation, and resturns a result to its associated thread. The thread stores the result, and then sends the next data chunk.
So, I really need to be able to contact different server locations, in parallel.
Can I do this with java/rmi, or am I just attempting the impossible?
[ February 04, 2004: Message edited by: Marc Wrench ]
Chris Shepherd
Ranch Hand

Joined: Jun 27, 2000
Posts: 286
I think there is a dns server that comes with most linux distributions. BIND is what it is called I believe.
I had a thought tho, why worry about about that for now. Make your app work in a test environment where you know all the server IPs. Later you can get/buy a nameserver.
Are you trying to do something like SETI@home? If thats the case, why not turn your process on its head and have the multiple machiens all acces your single machine with data. Then when they get done, they reconnect, transmit their results and get more data. That seems more efficient than the way you propose. With the way RMI works, you'd either have to have a rmi server on your main data machine waiting for data callbacks, or you would have to continually poll the data crunchers to see if they were done yet. Since you have to start up the java program on each data cruncher anyways, why not make the data crunchers the clients and the main data storage the server. The program is started and accesses your data storage. when finished with its assignment, it calls back and gets more.
Do you have some kind of operating constraint you didn't mention that would keep my proposal from working?
Chris
Marc Wrench
Greenhorn

Joined: Feb 02, 2004
Posts: 5
Yes, your suggestion is exactly what I have done, and it works a lot better. I suppose I should have built it that way to start with. Ah well, I never was any good at design.
Anyway, it seems to be working now, and I am relatively happy with it. Thanks for all your help(!).
M Wrench
Chris Shepherd
Ranch Hand

Joined: Jun 27, 2000
Posts: 286
Glad we got you going.
Chris
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
 
subject: Q: RMI- send objects, multiple servers
 
Similar Threads
Question about the RMI factory pattern
Re: Java RMI
B&S question on compilation of client
How RMI DiffersCORBA
Protocols