Updating server object with deserialized object through RMI - java

I have an object on a server which clients can retrieve in a distributed system. This all happens on a local machine and the clients call the server object through RMI lookup. The point is that the server object is supposed to be one single object which clients can modify. However after it's deserialized at the clients, they all have a different object ID. That is, they seem to get a new object, even though they are all supposed to retrieve the same object from the server. This makes sense, considering the objects are supposed to be on separate machines (per client).
I have tried to implement the hashcode and equals methods on the server object, but the clients still get a different object id. When the clients perform actions on the deserialized server object, the original server object does not receive the changes. I know this because any subsequent lookups retrieve the server object in its original state.
Basically my question is: How can I let my clients update the original server object by performing client operations on the respective deserialized objects? When another client looks at the getters of its deserialized object, it must see all the changes performed by other clients. To clarify further, despite that the objects are deserialized over different machines, I want them to behave as if they were one and the same object on the same machine.

The point is that the server object is supposed to be one single object which clients can modify. However after it's deserialized at the clients, they all have a different object ID
The point is that this isn't a remote object, so it gets serialized, which you don't want.
I want them to behave as if they were one and the same object on the same machine.
Exactly. You need to:
Have it implement a remote interface
Export it, either by having it extend UnicastRemoteObject (preferred) or calling UnicastRemoteObject.exportObject() on construction.

Related

Multiple clients for multiple purposes in TCP socket?

After seeing some examples at my class, I know that if I want to send a "TypeA" object to server and receive a "ProcessedA" object as a result, I only need one client class.
But if I want to send "TypeA", "TypeB", and "TypeC" objects (not at the same time) to server, do I need to make 3 different client classes, each one of which sends objects of one of those data types, or I only need to make one client class and write 3 different "send" methods?
You can have only one method if the objects you send inherits from one unique class or interface, and the same logic is applied to the result class.
It's a bit hard to understand what you need if you don't include a sample code of what you are trying (as is noticed in another post related to your request).
If this condition can be met by your needs, you can use the instanceof operator inside the server method to detect the type of the received object and cast it to the known child type. And apply the same logic to proccess the response in the client.

How do I treat objects when having both RMI and Socket connections?

I am in the process of creating a game using Java. It is requested of me that the player of the game can choose to connect either through a RMI connection or a Socket one. Until now I have created all the necessary components for the game, but when it comes to creating the RMI connection, i'm having a bit of problem. From what I have read in regards of RMI all the objects used to create the connection need to be declared Remote (for example implement the Serializable interface). Seeing that I have to create both types of connections, I don't see it reasonable to serialize all the objects created so far. At this point I can think of two possible solutions:
Create a remote version of the necessary objects for the connection(for example by creating a class that extends said object and implements Serializable interface to make the object remote). After doing that, I can define the methods applicable to the remote objects that can be invoked by the clients.
Create this new type of remote objects that are just messages that take the requests from the client and "translate" them to the non remote objects and then proceed to do what was requested.
I am new to Java and I would appreciate your time and patience on this question.
From what I have read in regards of RMI all the objects used to create the connection need to be declared Remote (for example implement the Serializable interface).
You didn't read that anywhere. It doesn't even makes sense. Implementing Remote doesn't make an object Serializable. You have to
Design a remote interface that extends Remote.
Ensure that every object that will be passed or returned via this interface implements Serializable or, in rare cases, a remote interface.
Write an implementation of the interface, that typically extends UnicastRemoteObject.
If you have any remote objects at (2), repeat.
Seeing that I have to create both types of connections, I don't see it reasonable to serialize all the objects created so far.
You don't have any choice about (2), although that is unlikely to include all the objects created so far. In any case you would already have had to do it for objects you were planning to send over a socket.
At this point I can think of two possible solutions:
Create a remote version of the necessary objects for the connection(for example by creating a class that extends said object and implements Serializable interface to make the object remote).
Again this is just nonsense.
After doing that, I can define the methods applicable to the remote objects that can be invoked by the clients.
That corresponds to my step 1.
Create this new type of remote objects that are just messages that take the requests from the client and "translate" them to the non remote objects and then proceed to do what was requested.
This also is nonsense.

How to move objects by RMI?

Is there an easy, elegant and clever way to move objects between different RMI instances?
At the moment I would perform this task by cloning the object in the receiving RMI server and then destroying the original in the sending RMI client (or other way around when moving from RMI server A to RMI server B).
I guess, I will also have to clone and destroy all objects of the object?
If your object implements "Remote" interface, it is passed by reference.
If your object doesn't implements "Remote" interface, it is passed by value.
You have to take a decision depending on type of the object.
Java documentation
Passing Objects in RMI
Arguments to or return values from remote methods can be of almost any type, including local objects, remote objects, and primitive data types.
The rules governing how arguments and return values are passed are as follows:
Remote objects are essentially passed by reference. A remote object reference is a stub, which is a client-side proxy that implements the complete set of remote interfaces that the remote object implements.
Local objects are passed by copy, using object serialization. By default, all fields are copied except fields that are marked static or transient. Default serialization behavior can be overridden on a class-by-class basis.
It is not necessary to clone the received object.
It is enough to create a reference to it.
The received object is already a copy (in the server b) of the original object used in the rmi call (in the server a).

Patterns for propagating changes to nested objects

I am implementing a game/application where the player's account/state is synced to the server. I am contemplating a general framework communicating modifications of nested objects of an entity (the entity being the users's account). Let us assume for discussions of computation/reflection that both the client and server are written in Java (in reality client is in Actionscript which can modify properties dynamically)
Take for instance Firebase. Modifications to any object of the root object (a Firebase object) are propagated with a request that probably looks something like:
Service: PersistenceService
Action: modifiedObjects
Body:
Objects [{"/full/Path/To/Object/1","newValue"},{"/full/Path/to/Object/2","newValue"}]
My request for your input is the following:
1) Please correct and/or augment the following thoughts on implementing this general framework for propagating modifications to a tree of objects.
On the sending side, it would appear that every object either:
1) Needs to store it's full path from the root entity
2) Changes to properties of all nested objects need to be done reflectively
OR
A sync needs to forced, comparing the entity's saved object tree from the last request to the current object tree for modifications.
On the server side, one can analyze the paths of the objects to cache objects that are accessed multiple times in one request so as not to access the tree by reference/search collections multiple times.
The answer I have come up with is actually very obvious the obviously the best way to do it. The answer is to mirror a database of tables. Assign each object an id, and store every object in an ArrayList (or assign each object a unique ID based on type and store the object in its type's ArrayList which is itself stored in a HashMap).
I call my interfaces ServiceObject and ServiceContainer.
Now the only thing I have to see that works is how json and protostuff serialize dual references to objects. Are they serialized as seperate objects? If so, than I any nested ServiceObject's need to deserialized as references to the objects in the ArrayList.
Generally observer pattern is answer to kind of requirement you have (from wiki)
The observer pattern (aka. Dependents, publish/subscribe) is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. It is mainly used to implement distributed event handling systems.
You need implementation on the client server hence example given on the wiki is not applicable you might want to check this :
http://deepintojee.wordpress.com/2011/03/18/observer-pattern-applied-at-remote-level/

Java RMI, making an object serializeable AND remote

You might be thinking why would you want to have an object both Remote AND serializeable. Well let me give you some context.
I'm building an air traffic control system (school project), it's distributed so that each control zone runs on it's own server and communicates with other control zones. Each control zone keeps track of its own aiplanes.
When an airplane (flying in controlzone A) is 100km near its border, it is passed as a remote object to the controlzone (controlzone B) it's near to. This way controlzone B can see where the aiplane is (by periodical asking its position) while it's still controlled by controlzone A.
But when an airplane crosses the border between controlzone A and B, controlzone B should keep track of the airplane instead of controlzone A. So we we want to serialize the airplane and pass it to controlZone B. This is where our problem lies.
Can I make the airplane remote AND serializeable?
EDIT: Also, I could use remote methods to copy the needed fields for the airplane, but I prefer serializing it.
If a remote object isn't exported at the time it is sent as a remote method parameter or result, it is serialized instead of being passed as a remote reference, provided that it implements Serializable as well as Remote. It is then exported at the receiver. UnicastRemoteObject does this for example, and therefore so does any remote object derived from it. This can be used for mobile remote agents.
You don't have to make your object subclass UnicastRemoteObject.
Take your class, define it to implement Serializable and your RMI api interface, which itself should implement Remote. It doesn't need to subclass anything other than java.lang.Object.
When you are ready for your object to be called remotely, call the static UnicastRemoteObject.exportObject() method on it. From that point on, any reference you return over RMI to that object will be remotely callable.
When you want to pass the object off to another server, call UnicastRemoteObject.unexportObject() on your object. Then when you pass it over an RMI call, you'll be passing the serialized representation of that object.
The downside to this is once you pass it off, the object on your server will no longer accept RMI calls. unexportObject() turns it off completely as an RMI call recipient.
If you want to be able to maintain an object as an RMI target and concurrently pass it around over RMI as a serializable object, you'll need to make it serializable and interpose a proxy object that exports the Remote interface and which can talk to the non-exported, serializable object on the caller's behalf.
When you want to pass the underlying object with serialization, you pass it directly. When you want to pass a remotely callable reference to it, you pass the proxy.
Take a look at UnicastRemoteObject class. It is normally used for callback driven programming in RMI and hence implements both Remote and Serializable. Though you might want to revisit your logic since you now have an entity (airplane) which acts like a "remote server".
Turns out this solution was not correct. See #EJP's answer below for the only way to do this with a single instance.

Categories

Resources