Aled, Thanks for the great summary.
As things can be even trickier than the examples you descibed (i.e. HA with different Brooklyn versions around) I'd be inclined towards option 2 where an informed operator runs the tool and migrate from a versione to the other with consciousness. Best, Andrea Il 22/ago/2014 13:40 "Aled Sage" <[email protected]> ha scritto: > Hi all, > > I've been thinking about backwards compatibility of our persisted brooklyn > state, in the face of us moving classes around and/or deprecating. > > --- > USE CASES > Let's take two use-cases: > > 1. `MathPredicates.greaterThan` returns a (static) anonymous inner > class, so is serialized by xstream as `MathPredicates$1`. > We want to move that class to a fixed class name (e.g. `private > static class GreaterThan {...}`) suitable for xstream. > (It's a *really bad* idea to be using `MathPredicates$1`; if someone > in a future release adds some code above it then the class name > would change!) > 2. I want to move PortRanges from package `brooklyn.location.basic` to > `brooklyn.util.net.PortRanges`. > However, this contains inner classes such as `SinglePort`. > If it was just code compatibility, we'd have the old `PortRanges > extends brooklyn.util.net.PortRanges`, and do some fancy stuff to > wrap the returned objects so they implement > `brooklyn.location.PortRange`. > > --- > THE PROBLEM > xstream tries to deserialize MathPredicates$1 but that class no longer > exists. Even if we did leave it around (yuck!), nothing changes it to the > new class name so we could never delete it! > > --- > THE PROPOSED SOLUTION > I propose we have a lookup file in brooklyn that contains all the renamed > classes. > We register a converter with xstream that, when deserializing, looks up > this (cached) lookup file. If it contains the classname that xstream has > encountered, we switch it for the new one and then let xstream continue > with its deserialization. > > See brooklyn.entity.rebind.persister.XmlMementoSerializer for where this > code would go. > > (Note that for the `PortRange` example, we'd require that the calling code > had been updated to expect the new `brooklyn.util.net.PortRange` rather > than the old `brooklyn.location.PortRange`. i.e. the returned instance > would not implement all the same interfaces as the original class! We could > perhaps work around that with some extra converter logic and wrapping > classes.) > > --- > ALTERNATIVE SOLUTION > We could have a separate tool that is run manually once when someone is > upgrading. It would walk through the persisted state, changing the old > class names to the new ones. > > Thoughts? > > Aled > >
