Search code examples
javarmi

Java RMI has different values in same instance


We implemented a little application where clients make call a method on the server. The idea is that the server keeps a list of variables to be called, we stripe off a value once it has been called.

In our instance we need to have the client call first with "m1" and then with "m2". the method justReceived (over RMI).

public class Server implements TestService, Serializable {
  private HashMap<String, List<String>> assertQueue = new HashMap<String, List<String>>();

  @Override
  public synchronized void justReceived(Message m, String from, String to) {
    if (!assertQueue.containsKey(to) || !(m instanceof TestMessage))
      return;

    TestMessage message = (TestMessage) m;

    if (assertQueue.get(to).get(0).equals(message.message)) {
      assertQueue.get(to).remove(0);
      System.out.println(assertQueue);//p1
    } else {
      testErrors.add(new AssertionError("Expected " + to + " to receive message " + assertQueue.get(to).get(0) + " but got " + message.message));
    }
  }
}

We have a separate thread monitoring the assertQueue, but there is no change observed, while we are sure the assertQueue has been altered over RMI.

The other thread keeps printing

{c3=[m1, m2]}

While at p1 is printed:

{c3=[m2]}

The other thread keeps printing the same, even after at point p1 the smaller assertQueue has been printed.


Solution

  • There is no RMI here. This is a Serializable object which is transmitted to the client and executes there. Which is the problem. You have a copy of the data structure per client, instead of a single one at the server.

    You've forgotten to export it. You need to either:

    1. Make it extend UnicastRemoteObject(), which in turn will force you to provide a constructor that throws RemoteException, or
    2. Export it 'manually', with UnicastRemoteObject.exportObject(), before you call bind().

    You can remove implements Serializable.