Thursday, March 1, 2012

Serialization and changing Java enumerations

In our latest release, we accidentally broke a web service we provide. Good thing is it's discovered by testers in the acceptance system. Lesson to learn: use better integration testing, on top of simple unit tests.

What went wrong? Well, in the initial version of the API, web service could return serialized Java objects via Spring HttpInvoker, including some enumeration constant. The definition of the enumeration type:

public enum Channel { phone, mail, e-mail };

Business wants to support a fancy mobile application for people having certain smartphones, so we extend the type:

public enum Channel { phone, mail, e-mail, mobileApp };

Well, since we forgot to pass the updated binary client to the calling application, the deserialization went wrong if the response contained the new "mobileApp" constant, which is rather logical.

But two other questions remained on the compatibility from the old client, what if:
  1. the server uses the extended type, but only return old constants?
  2. we swap the order of the constants in the enumeration type definition?
First, the old client works fine as long the response does NOT contain the new constant. Secondly, playing with the order is NO effect. Easy, not?

All this is due to the language specification, requiring some special, but simple handling for enumeration constants. Mainly the name of the constant is important, and you can ignore the position, and even the extra, optional fields from your enum "class" ...

More reading:

Java language on serializing enumerations

Blog warning NOT to use serialVersionUID for enums