views:

1092

answers:

4

I've got an RMI call defined as:

public void remoteGetCustomerNameNumbers(ArrayList<String> customerNumberList, ArrayList<String> customerNameList) throws java.rmi.RemoteException;

The function does a database lookup and populates the two ArrayLists. The calling function gets nothing. I believe this works with Vector types.

Do I need to use the Vector, or is there a way to get this to work without making two calls. I've got some other ideas that I'd probably use, like returning a key/value pair, but I'd like to know if I can get this to work.

Update:
I would accept all of the answers given so far if I could. I hadn't known the network cost, so It makes sense to rework the function to return a LinkedHashMap instead of the two ArrayLists.

+1  A: 

You lose your references when you make the remote call. You'll need to return the lists rather than expect them to be populated by the remote call.

ScArcher2
+1  A: 

Arguments in RMI calls a serialised. Deserialisation on the server creates a copy of the lists. If the lists remained on the client side, then the number of network calls would be quite high. You can pass remote objects, but beware of the performance implications.

Tom Hawtin - tackline
+1  A: 

As Tom mentions, you can pass remote objects. You'd have to create a class to hold your list that implements Remote. Anytime you pass something that implements Remote as an argument, whenever the receiving side uses it, it turns around and makes a remote call back to the caller to work with that object.

Scott Stanchfield
+1  A: 

As others have already mentioned, when passing objects as parameters to an RMI method, the object will get serialized, then deserialized on the other end inside the target object containing the RMI method. This breaks the reference from the original objects passed in, as you now have two distinct objects: one in the client code calling the method, and one on the remote side.

In this specific example, a better approach would be to break up your method calls (since you appear to be doing two things in one method: getting customer names and getting customer numbers) and instead have your results returned to the caller rather than passing in a collection...like this:

public ArrayList<String> getCustomerNames() throws java.rmi.RemoteException;

public ArrayList<String> getCustomerNumbers() throws java.rmi.RemoteException;

Since both ArrayList and String implement Serializable, the results in the collection will be serialized and sent over the wire to the client code calling the method, at which point you can work with the data however you need. If instead you need to use a custom object in the collection, as long as your class implements the java.io.Serializable interface, and follows the specification for that interface you should have no problems.

This would result in two separate calls over the wire, but is a much cleaner and simpler interaction, and avoids the reference breaking problem in your original example.

BCunningham