views:

29

answers:

1

I am developping a CORBA like inter object protocol that would support object aggregate transmission.

When objects of an aggregate are serialized, they may have references to objets serialized later. These are forward references. A simple example is a circular list. If each object has a reference to the previously serialized object, the first object will have a reference to the last serialized object to close the loop.

When deserializing and instantiating an object containing such a forward reference, its value is not known. It is only when the corresponding object is deserialized and instantiated that the reference value is known and could be set.

In C or C++ I use the reference (pointer) itself to hold the list of references to the same object to set when it is instantiated. In Java this is not possible.

How could I implement such delayed reference setting in Java ?

+1  A: 

If the objects are immutable, then you build a temporary structure which will create them in an appropriate order ( obviously, this doesn't apply to circular lists, unless you use the setting final field reflective serialisation support ).

If not, either record the actions needed in an external list later, or use an interface with a resolve method for each member: public interface IBar { IBar resolve ( );

    static IBar EMPTY = new IBar() { 
        public IBar resolve () { 
            throw new RuntimeException(); 
        }
    }
}

public interface IFoo {
    IFoo resolve ( );
    ...
}

public class Foo implements IFoo {
    private IBar bar = IBar.EMPTY;

    public Foo ( IBar bar ) { this.bar = bar; }

    public Bar getBar () {
        return bar.resolve();
    }

    public String getId () { ... }

    public IFoo resolve () {
        bar = bar.resolve();
        return this;
    }
}

public class Loader {
    private HashMap<String,IFoo> fooRefs = new ...
    private HashMap<String,IBar> barRefs = new ...

    private IBar barRef ( String id ) {
        IFoo foo = fooRefs.get(id);

        if (foo==null) {
            foo = new ForwardFooRef(id);
            fooRefs.put(id,foo);
        }

        return foo;
    }

    private IFoo created ( IFoo foo ) {
        IFoo extant = fooRefs.get(foo.getId());

        if (extant != null) 
            if ( extant instanceof ForwardFooRef) 
                ((ForwardFooRef)extant).setReferent(foo);
            else
                throw new RuntimeException("more than one object with the same id ");

        return foo;
    }

    public void load () {
        create each object
        register it using created
        if a ref is found, use the maps to look it up
        if the ref is in teh map, use it
        if ref is forward, it's created with a temp

        walk object tree resolving anything 
Pete Kirkham
Your example is interesting because it uses the trick to store a reference to a dummy object holding the information needed to resolve the forward reference. This dummy object could also hold the intrusive chaining. In my system all serializable class inherit from the base class Serializable which can have a method to resolve the forward reference. The implementation could go through all references and if they reference a dummy Serializable object, use its contained information to resolve the link. Was that the idea ? Anyway it's excellent.
chmike