3

I'm trying to grasp the basics of Java RMI.

The idea is to have two separate processes running, each primed by a separate main in one of two classes:

  • Client running as a client
  • Server running as a server

A third class Document acts as the shared object (it being a simple collector of Strings), with its method addTimestamp() saving the current Timestamp for further printing in the console. This method is also one available as a remote method, as defined in DocumentInterface.

Executing the two mains on two different cmd windows yields a perfectly functioning system:

  • Server: java -cp rmi.jar Server

  • Client: java -cp rmi.jar Client

As expected the client's output is:

CLIENT - Viewed on: 2016.09.30 01.53.01

SERVER - Viewed on: 2016.09.30 01.53.01

When I start the server under a different timezone though:

  • Server: java -Duser.timezone=PST -cp rmi.jar Server

  • Client: java -cp rmi.jar Client

I still get the original client output:

CLIENT - Viewed on: 2016.09.30 01.53.01

SERVER - Viewed on: 2016.09.30 01.53.01

I would expect the second line to have the server's PST-based Timestamp. I checked the flag was set correctly by having it printed directly by the server's main, and it is indeed different:

2016.09.29 16.55.57

From what I've understood so far, when calling the addTimestamp() method remotely on the remote object:

  • the current Document is passed by copy to the server
  • the Timezone is appended by the server, using its instance of the Document class
  • the returned Document is passed by copy back to the client
  • the Document is displayed by the client

In this case I would thus expect that Timezone to be based on the server's settings, not the client's. Why is this not the case?

Here are some code snippets from the four classes:

Document.java:

public Document addTimestamp(Document document) throws RemoteException
    {
    String timestamp = new SimpleDateFormat("yyyy.MM.dd HH.mm.ss").format(new Date());

    document.strings.add("Viewed on: "+timestamp);

    return document;
    }

DocumentInterface.java:

public interface DocumentInterface extends Remote
    {
    public Document addTimestamp(Document document) throws RemoteException;
    }

Server.java - main:

Registry registry = LocateRegistry.createRegistry(1099);
Document document = new Document();
Naming.bind("rmi:///Document", document);

Client.java - main:

Document document = new Document();
DocumentInterface remoteDocument;
try
    {
    remoteDocument = (DocumentInterface) Naming.lookup("rmi:///Document");

    document.addString("USER - ");
    document.addTimestamp(document);
    document.addString("\n");
    document.addString("SERVER - ");
    document = remoteDocument.addTimestamp(document);

    System.out.println(document.toString());
    }
catch (Exception except)
    {
    }
Community
  • 1
  • 1
Gliptal
  • 350
  • 1
  • 10

1 Answers1

1

Because Document is an exported remote object, it is running as a callback at the client. Not by copy at the server.

Remove the remote interface and extends UnicastRemoteObject, and make it serializable.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Thanks, this explains it. If I remove the `Remote` interface, I cannot bind it to the rmi registry anymore though (the binded object must be of type `Remote`). How can I have a `Document` binded by the server so that it can be called by the client, and also not have it behave like a callback? – Gliptal Oct 01 '16 at 09:17
  • 1
    You need to make up your mind as to whether you're creating a new Document at the client or looking it up in the Registry. At present you're doing both. Normally this wouldn't be possible, as you wouldn't have the `Document` remote object class even present at the client. – user207421 Oct 01 '16 at 09:24
  • What I'd like to do is have the client look in the registry for a binded `Document`, and have the server execute the remote method so that it displays the server's time. I'd then use the client `Document` to display everything, and that that same method ran locally gives a different timestamp. – Gliptal Oct 01 '16 at 09:50
  • 1
    So if you use the client's Document it will execute at the client. You have a serious mixup here. Only you can resolve it. – user207421 Oct 01 '16 at 10:52
  • Bear with me, I'm rusty in Java. Am I not calling the method on the server here: `document = remoteDocument.addTimestamp(document);`? The way I see it, I'm passing the client's `document` to the server's rmi binded `remoteDocument`, and that instance then runs `addTimestamp`. Being on the server, I'd expect the returned `document` to have the server's timestamp. What is happening instead is that the method is called on the client instead of on the server. – Gliptal Oct 01 '16 at 11:06
  • 1
    Step back a moment. Why does the `addTimestamp()` method take a `Document` parameter? instead of a timestamp? Which document are you adding a timestamp to? Clarify your thinking. – user207421 Oct 01 '16 at 11:09
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/124707/discussion-between-gliptal-and-ejp). – Gliptal Oct 01 '16 at 11:26
  • Forget it. I'm going away for a week tomorrow. You need to answer the questions I asked, *to yourself.* What you have at the moment is a totally confused API design. Rationalize it. – user207421 Oct 01 '16 at 11:52