XMLEncoder/XMLDecoder and mutable arguments to getters/setters

G

George Armhold

Hi,

I have a conundrum concerning XMLDecoder and serialization in general.
I wrote a fairly simple bean that happens to contain a couple of
ArrayLists internally, and exposes them like this:


public class MyBean implements Serializable {
private List foo = new ArrayList();

public MyBean() {}

public List getFoo() {
return foo;
}

public void setFoo(final List foo) {
this.foo = foo;
}
}


I can serialize and de-serialize blissfully using XMLEncoder and
XMLDecoder. This worked fine as an initial implementation, code was
put into production, and now we have some business data stored in this
format.

Some time later I decided that giving access to the underlying List
data was probably not such a good thing (I actually had a bug that
modified the lists behind my back.) So I set out to change the
implementation to make defensive copies of all the data passed in and
out with the getters and setters. Of course I should have done this
from the start. So now we have something like this:

public List getFoo() {
final List copy = new ArrayList();
copy.addAll(foo);
return copy;
}

public void setFoo(final List foo) {
this.foo.clear();
this.foo.addAll(foo);
}


Then to my surprise, the old business data does not get read correctly
with the defensive copying. I examined the serialized output from the
old and new versions, and the difference seems to be that with
defensive copying, the serialized ArrayLists have entries with "id"
attributes, e.g.:

<void id="ArrayList0" property="foo">

The old format, created without defensive copying does not. What's
going on here? Does XML{De,En}coder somehow "know" when data has been
copied, and behave differently?

Thanks for your time.
 
C

Chris Riesbeck

The old format, created without defensive copying does not. What's
going on here? Does XML{De,En}coder somehow "know" when data has been
copied, and behave differently?

XMLEncoder uses a "redundancy elimination" algorithm to avoid
writing default values. To encode a bean X, it creates a new bean Y,
then compares each property of Y with X. When they differ, it copys
the value of that property from X to Y, and records what it had to do.
Then at the end it writes out what it had to do to make Y = X.

Furthermore, to avoid writing collections (in the generic
sense, including arrays, lists, and so on), that differ only
slightly, it checks them element by element and only writes
the differing values. You can see this by creating a toy bean
that has an array of A and B by default, make an instance
that has A and C, and look at what XMLEncoder generates.

Hence, if you make things non-equal through copying, you can
trigger odd effects. I'm not sure why you should be getting
incorrect data stored though.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,989
Messages
2,570,207
Members
46,782
Latest member
ThomasGex

Latest Threads

Top