You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@river.apache.org by Peter <ji...@zeus.net.au> on 2013/02/26 08:29:42 UTC

Serialisation and Immutability

This problem has been allowed to fester for a long time.

Serialisation creates all sorts of issues because it doesn't utilise constructors or static factory methods.

I've had enough, I'm doing something about it.

As you may be aware, ObjectInputstream and  ObjectOutputStream are extensible and allow subclasses to substitute any object.

I'm considering creating an interface:

Interface DistributedObject {

    SerialFactory substitute();

}

// Pseudo code; methods and constructors omitted.
public final class SerialFactory implements Externalizable {

    private final Class clazz; // factory class or constructors class
    private final String methodName;  // constructor if null.
    private final Class [] parameterTypes;
    private final Object [] parameters;

}

It's straightforward to create object streams that substitute DistributedObject's in the stream with SerialFactory and replace them using reflection to call a constructor or static method during deserialisation.

This retains compatibility with existing Serialisation and Marshalling, it preserves the object graph and allows distribution and construction of non serializable final immutable objects.  It doesn't suffer from readResolve's circular reference issue either.

It allows object class evolution, migration of data, serial form is separate, flexible and based on static method or constructor parameters, even a completely different implementation can be used simply, by changing factory method implementations (provided all references to an object being deserialised refer to a compatible superclass or interface).

It prevents package classes from being published; eg a private class can utilise a public class static factory method and extend a non serializable class lacking a public no arg constructor (Serializable methods can't do that).

It also allows a transition period to migrate serializable objects to utilise DistributedObject only, if necessary at some later point, removing lock in to currently published serial form for much greater flexibility in future.

It would also allow heavyweight objects to be linked locally from persistant storage or databases (which may be obtained via Services), only requiring serialisation of a small amount of data to obtain a reference, allowing a factory to perform the heavy lifting or construction required to obtain the correct object to be linked into the object graph.

Yes, I'm aware that you can use reflection during deserialization to set final fields to ensure immutability and invarients, unfortunately programmers seldom use this trick, I want something simpler that gets rid of boilerplate code, where most of the hard work is done for you, all the developer needs to do is implement one method to construct a SerialFactory which utilises constructors and factory methods

Sorry, I'm just getting fed up with legacy code making life hard.

Peter.