Solved

RMI Serialization and Collections

Posted on 2002-05-09
10
287 Views
Last Modified: 2013-12-29
    Hello,

     since serialization creates new instances of an object, making sense
     of a serialized Collection seems difficult.  i have a need to put
     things in Sets or Lists and later, "across the wire", compare them
     against other Sets, Lists, or Objects.  anyone have advice on a
     (hopefully simple) way to do this in general?  for specifics, consider
     the following two classes (simplified and abbreviated) and output:
     --------------------------------------------------------------------------
     public class TestServerImpl extends UnicastRemoteObject implements
     TestServer, Serializable {

       // only used because Object doesn't implement Serializable...
       class SerialObject implements Serializable {}

       private SerialObject theObject;
       private Collection theSet;

       static public void main() {

         TestServer ts = new TestServerImpl()
         Naming.rebind("//host:port/testServer",testServer);
       
       }
       private TestServer() {
         theObject = new SerialObject();
         theSet = new HashSet();
         theSet.add(theObject);
       }
       // methods promised in TestServer interface
       public Object getObject() { return theObject; }
       public Collection getSet() { return theSet; }
     }
     ------------------------------------------------------------------
     public class Test {
       public static void main() {
         TestServer ts = (TestServer)
     Naming.lookup("//host:port/testServer");
         Object aThing = ts.getObject();
         Collection aSet = ts.getSet();
         System.out.println("thing is :"+aThing);
         System.out.println("set is :"+aSet);
         System.out.println("set contains thing? "+aSet.contains(aThing));
       }
     }
     ----------------------------------------------------------------------
     the output is what you'd expect, but not what you'd want.  something
     like:

     thing is :SerialObject@743399
     set is :[SerialObject@67b241]
     set contains thing? false

     i know readResolve() can be used to return an existing object instead
     of a new object from the deserialization process, but this seems an
     awfully bulky solution in general.  am i just way off base in my
     approach?

     thoughts?

     -don.
0
Comment
Question by:dddexter
  • 4
  • 3
  • 2
  • +1
10 Comments
 
LVL 4

Expert Comment

by:pellep
ID: 6999889
Classes implementing Collection (and List) implements (or should implement, according the the spec)
Collection.contains(Object obj)
by iterating over the collection, calling
object.equals(obj) where object is the current object returned by the iterator.

So, by overriding equals(Object obj) from class Object, you can specify your own comparison routine
ie
class Bla {
private int iVal = 5;
public int getIVal() {
return iVal;
}
public boolean equals(Object o) {
if (obj intanceof Bla && ((Bla) obj).getIVal() == this.getIVal()) {
return true;
} else {
return false;
}
}
0
 
LVL 4

Expert Comment

by:pellep
ID: 6999893
class Bla {
private int iVal = 5;
public int getIVal() {
return iVal;
}
public boolean equals(Object obj) {
if (obj intanceof Bla && ((Bla) obj).getIVal() == this.getIVal()) {
return true;
} else {
return false;
}
}
}

anyway
0
 
LVL 92

Expert Comment

by:objects
ID: 7000161
The default implementation of equals() provided by Object simply returns true of the tow objects are the same instance. ie. a==b.
Which in this case they aren't.
If theObject was a String or an Integer for example you would get the desired result.
0
 

Author Comment

by:dddexter
ID: 7000526

i'm not convinced that implementing equals() (and hashCode()) is the way to go.  i received a similar response to the question on google, so perhaps i'm
just being beligerent....

BUT, suppose (as is the case in my app) that the objects
are mutable:
Mutable a = new Mutable(propertySetA);
Mutable b = new Mutable(propertySetB);
aSet.add(a);
// a==b false.  a.equals(b) false.  aSet.contains(b) false.
b.setProperties(a.getProperties())
// a==b false.  a.equals(b) true?  aSet.contains(b) true?
a.setProperties(propertySetB);
// a==b false.  a.equals(b) false? aSet.contains(a) false?


further, if there are no obvious fields that clearly
define equals(), one would need to do something like add
a uniqueId field as sort of a "key" to *every* class that
is to be serialized. this seems bulky and non-intuitive.
what do we do for classes provided by sun which may not
override equals()?  subclass or wrap each one in order
to serialize it?  seems messy.

Summary:
on the server-side we can easily share references for any object w/o any extra coding...just assign a variable.
is there no way to, in general, deserialize the *same* object (a single reference)to two variables and compare
them as equal?  i'm beginning to doubt it, but it seems suspect.

thanks for your input,

-don.
0
 

Author Comment

by:dddexter
ID: 7009238
Ok, I give.

guess my unfamiliarity w/ serialization was really the underlying problem.
i just couldn't get it through my thick skull that a single object serialized and
deserialized twice to two different references would appear as two new and
distinct objects.  period.  

options are to a)  implement equals() to make them "appear" to be the same
object (sort of) or b) implement readResolve().  readResolve() is probably
closer to what i was after, but to use it in a simple manner requires some
of the same hooks as implementing equals() (either an immutable object
or some sort of unique id field).  

in the end, i've resolved the problem by only passing objects once (which
is probably better) and doing the logic on the client side.

i *think* a solution for what i was after (although an overly complex one)
would be to :
1) implement writeObject() and readObject for every object to be sent
to the client.  they would perform default operation with the addition of
writing/reading the object's hashCode.  since the writeObject() is server
side, the hashCode would be that of the server-side object.
2) build a hashMap on the client that contains every object recieved
indexed by its *server-side* hashCode.
3) implement readResolve() for every object to be passed.  have it
check the local hasMap to see if the object has already been passed
and return that copy if so - otherwise add it.

still wouldn't work for a mutable object modified on the server between
serializations....but i'm not sure it should...

thoughts?

-don.
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 92

Accepted Solution

by:
objects earned 200 total points
ID: 7009855
Doesn't that solution assume that hash code of evey object is unique?
0
 

Author Comment

by:dddexter
ID: 7010011
check that,  you clearly can't use hashCode
because these aren't guarenteed to be unique.
you'd have to develop a good unique id for each
object.

-don.
0
 
LVL 2

Expert Comment

by:nir2002
ID: 7050632
I think the solution is to supply stable hashCode and equals for your own types.
You can build equals and hashCode according to the member class they have.

In your example you have to supply it to the SerialObject
for example:

public int hashCode() {
   //assuming HashSet suplly stable and good hash code even it  recreated
   return theSet.hashCode();
}

public boolean equals(Object obj) {
  if(obj instanceOf SerialObject) {
       //assuming the collection provide good equals method.
       return theSet.equals(((SerialObject)obj).getSet());
  } else {
       return false;
  }
}
0
 

Author Comment

by:dddexter
ID: 7051567
evidently, this has run its course for new ideas.  i think the idea of using something
like "an interface defining a good uniqeObjectId (as distinct from a hashCode)
to build a client object map which readResolve uses to ensure that objects are
only built on the client side a single time" is interesting, but i ain't pursuing it.

points are yours "objects".  by default i suppose.

-don.
0
 
LVL 92

Expert Comment

by:objects
ID: 7052378
Ta :)
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Suggested Solutions

For customizing the look of your lightweight component and making it look opaque like it was made of plastic.  This tip assumes your component to be of rectangular shape and completely opaque.   (CODE)
Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis. Java Flight Recorder is a profiling and event collectio…
Video by: Michael
Viewers learn about how to reduce the potential repetitiveness of coding in main by developing methods to perform specific tasks for their program. Additionally, objects are introduced for the purpose of learning how to call methods in Java. Define …
This tutorial explains how to use the VisualVM tool for the Java platform application. This video goes into detail on the Threads, Sampler, and Profiler tabs.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now