views:

1756

answers:

8

I'm currently working on a project which needs to persist any kind of objects (of which implementation we don't have any control) so these objects could be recovered afterwards.

We can't implement a ORM because we can't restrict the users of our library at development time.

Our first alternative was to serialize it with the Java default serialization but we had a lot of trouble recovering the objects when the users started to pass different versions of the same object (attributes changed types, names, ...).

We have tried with the XMLEncoder class (transforms an object into a XML), but we have found that there is a lack of functionality (doesn't support Enums for example).

Finally, we also tried JAXB but this impose our users to annotate their classes.

Any good alternative?

+11  A: 

http://xstream.codehaus.org/ is nice.

krosenvold
+1  A: 

Try serializing to json with Gson for example.

Bno
A: 

Possibly Castor?

toolkit
JiBX is a binding tool, as opposed to a serialisation tool.
johnstok
+3  A: 

The easiest thing for you to do is still to use serialization, IMO, but put more thought into the serialized form of the classes (which you really ought to do anyway). For instance:

  1. Explicitly define the SerialUID.
  2. Define your own serialized form where appropriate.

The serialized form is part of the class' API and careful thought should be put into its design.

I won't go into a lot of details, since pretty much everything I have said comes from Effective Java. I'll instead, refer you to it, specifically the chapters about Serialization. It warns you about all the problems you're running into, and provides proper solutions to the problem:

http://www.amazon.com/Effective-Java-2nd-Joshua-Bloch/dp/0321356683


With that said, if you're still considering a non-serialization approach, here are a couple:

XML marshalling

As many has pointed out is an option, but I think you'll still run into the same problems with backward compatibility. However, with XML marshalling, you'll hopefully catch these right away, since some frameworks may do some checks for you during initialization.

Conversion to/from YAML

This is an idea I have been toying with, but I really liked the YAML format (at least as a custom toString() format). But really, the only difference for you is that you'd be marshalling to YAML instead of XML. The only benefit is that that YAML is slightly more human readable than XML. The same restrictions apply.

Jack Leow
+7  A: 

of which implementation we don't have any control

The solution is don't do this. If you don't have control of a type's implementation you shouldn't be serialising it. End of story. Java serialisation provides serialVersionUID specifically for managing serialisation incompatibilities between different versions of a type. If you don't control the implementation you cannot be sure that IDs are being changed correctly when a developer changes a class.

Take a simple example of a 'Point'. It can be represented by either a cartesian or a polar coordinate system. It would be cost prohibitive for you to build a system that could cope dynamically with these sorts of corrections - it really has to be the developer of the class who designs the serialisation.

In short it's your design that's wrong - not the technology.

johnstok
I don't dought that this isn't the perfect solution but anyway it's a requirement imposed to me externaly. We are developing a library and there is a necesity to register the calls through this library.
Alotor
A: 

Personally, I use Fame a lot, since it features interoperability with Smalltalk (both VW and Squeak) and Python. (Disclaimer, I am the main contributor of the Fame project.)

Adrian
A: 

Betwixt is a good library for serializing objects - but it's not going to be an automatic kind of thing. If the number of objects you have to serialize is relatively fixed, this may be a good option for you, but if your 'customer' is going to be throwing new classes at you all the time, it may be more effort than it's worth (Definitely easier than XMLEncoder for all the special cases, though).

Another approach is to require your customer to provide the appropriate .betwixt files for any objects they throw at you (that effectively offloads the responsibility to them).

Long and short - serialization is hard - there is no completely brain dead approach to it. Java serialization is as close to a brain dead solution as I've ever seen, but as you've found, incorrect use of the version uid value can break it. Java serialization also requires use of the marker 'Serializable' interface, so if you can't control your source, you are kind of out of luck on that one.

If the requirement is truly as arduous as you describe, you may have to resort to some sort of BCE (Byte code modification) on the objects / aspects / whatever. This is getting way outside the realm of a small development project, and into the realm of Hibernate, Casper or an ORM....

Kevin Day
+1  A: 

google came up with a binary protocol -- http://code.google.com/apis/protocolbuffers/ is faster, has a smaller payload compared to XML -- which others have suggested as alternate.

One of the advanteages of protocol buffers is that it can exchange info with C, C++, python and java.

anjanb