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

Reply via email to