Wire Versioning at the Application-level Needed
joe.marques Sep 15, 2006 1:22 AMI feel that wire versioning (http://labs.jboss.com/portal/jbossremoting/docs/guide/ch12.html) is a very important feature, because if people are using JBoss Remoting as the framework on which they are building distributed applications, then it will be of the utmost importance for many to be able to upgrade one node at a time to ensure zero downtime when upgrading an entire enterprise.
However, I think it's only solving half of the problem right now. Wire versioning in 2.0.0 only addresses the infrastructure, but there will still be issues at the application-level. More precisely, regardless of whether the remoting capabilities on the cooperating nodes' can be upgraded independently, if the application code running on top of that infrastructure can't be updated in a similar "rolling" fashion, then much of the potential utility for wire versioning is restrained.
That being said, let's take a look at some use cases that this application-level scheme needs to handle.
If I have two participants sending and receiving the following definition for Person:
public class Person { private String name; // version 1 only has a name }
And then one of the participants gets upgraded with a new definition, say:
public class Person { private String name; private int age; // version 2 also has age }
Then there needs to be a mechanism to handle the graceful conversion of this one class definition to the other, so that enterprises can upgrade each node's application definition in a "rolling" fashion. The semantics of specifically what happens should perhaps be flexible within each remoting node's configuration, but something needs to be defined that will intercept the call and handle the graceful transformation.
For instance, maybe extra attributes from a newer class definition are simply dropped. In the reverse scenario, missing attributes might get simply get type-defined default values.
The above example assumed that the change in the newer version of the class was a simple addition. But what happens in more complex cases? Let's say from v2 to v3, Person had changes that looked like:
public class Person { private String fullName; // refactored name to fullName private Date birthday; // changed type and name }
Is it possible to design this application-level wire versioning in a way so that it executes an arbitrarily compelx translation when the object is being unmarshalled on the receiving end, so that names can be converted to fullNames (and vice versa), birthdates into ages, and ages into (albeit not perfectly accurate) birthdates?
One solution might be to use a modified version of Java serialization. For instance, if some extra metadata is pushed out in front of each serialized attribute and inspected on the receiving end, it should be possible to have the unmarshaller make the transformation intelligently.
Another approach that might work was something I saw while reading through the source code for some of the unmarshallers. It appears it's currently possible to use a remote class loader to instantiate a serialized object when the class definition doesn't exist on the receiving end. So maybe this could be adapted slightly to instantiate the object when the class definitions differ, and then use some clever tricks with reflection to "copy and paste" the data from the remote object type to the local one, e.g. something along the lines of: loop(local attrs) { local.setAttr(remote.getAttr) }