Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java socket/serialization, object won't update

I am writing a little socket based program. I am using a class ModelEvent to pass information through the socket. inside ModelEvent, there's a variable obect of type (Object).

The object itself is a 2D-array with some values.

object[1][2] = 2;
ModelEvent event = new ModelEvent("allo", object);
dispatchEvent(event);

object[2][3] = 2;
ModelEvent event2 = new ModelEvent("you", object);
dispatchEvent(event2);

Let's say that the array object is filled with the value 1. The first event (event) is received by the client, and the data is right. The second event sent though data is not right. Its data is the same as in the first dispatch. the "allo" and "you" is to see if I'm not reading the same event two times and the answer it's not. The string is right, but the object is not, event if it has been updated. I iterate through the array before sending the second event to see if it is updated on the server side, and it is. But on the client side, it still remain the same as in the first dispatch, even if the event itself is changed.

like image 607
maniak Avatar asked Sep 09 '12 17:09

maniak


1 Answers

See ObjectOutputStream.reset.

Reset will disregard the state of any objects already written to the stream. The state is reset to be the same as a new ObjectOutputStream. The current point in the stream is marked as reset so the corresponding ObjectInputStream will be reset at the same point. Objects previously written to the stream will not be refered to as already being in the stream. They will be written to the stream again.

/* prevent using back references */
output.reset();
output.writeObject(...);

Call reset before writing the same object to ensure its updated state is serialized. Otherwise, it will merely use a back reference to the previously written object with its out-dated state.

Or, you could alternatively use ObjectOutputStream.writeUnshared as follows.

Writes an "unshared" object to the ObjectOutputStream. This method is identical to writeObject, except that it always writes the given object as a new, unique object in the stream (as opposed to a back-reference pointing to a previously serialized instance).

Specifically:

  • An object written via writeUnshared is always serialized in the same manner as a newly appearing object (an object that has not been written to the stream yet), regardless of whether or not the object has been written previously.

  • If writeObject is used to write an object that has been previously written with writeUnshared, the previous writeUnshared operation is treated as if it were a write of a separate object. In other words, ObjectOutputStream will never generate back-references to object data written by calls to writeUnshared.

While writing an object via writeUnshared does not in itself guarantee a unique reference to the object when it is deserialized, it allows a single object to be defined multiple times in a stream, so that multiple calls to readUnshared by the receiver will not conflict. Note that the rules described above only apply to the base-level object written with writeUnshared, and not to any transitively referenced sub-objects in the object graph to be serialized.

output.writeUnshared(...);

Note it's good practice to couple this with ObjectInputStream.readUnshared.

Reads an "unshared" object from the ObjectInputStream. This method is identical to readObject, except that it prevents subsequent calls to readObject and readUnshared from returning additional references to the deserialized instance obtained via this call.

Specifically:

  • If readUnshared is called to deserialize a back-reference (the stream representation of an object which has been written previously to the stream), an ObjectStreamException will be thrown
  • If readUnshared returns successfully, then any subsequent attempts to deserialize back-references to the stream handle deserialized by readUnshared will cause an ObjectStreamException to be thrown.

Deserializing an object via readUnshared invalidates the stream handle associated with the returned object. Note that this in itself does not always guarantee that the reference returned by readUnshared is unique; the deserialized object may define a readResolve method which returns an object visible to other parties, or readUnshared may return a Class object or enum constant obtainable elsewhere in the stream or through external means. If the deserialized object defines a readResolve method and the invocation of that method returns an array, then readUnshared returns a shallow clone of that array; this guarantees that the returned array object is unique and cannot be obtained a second time from an invocation of readObject or readUnshared on the ObjectInputStream, even if the underlying data stream has been manipulated.

obj = input.readUnshared();
like image 107
obataku Avatar answered Sep 21 '22 14:09

obataku