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

Thursday, January 26, 2012

Yet another small Scala collection trick

Once again, my colleague Danny popped up a Java collection question. Given a data map with small lists as values, what is the shortest or best way to create a new, big list containing all individual elements from the small lists?

Best thing that we found in a few minutes, using car manufacturers and models as example data:

// setup
Map < String, List > carModels =
        new HashMap < String, List < String > > ();
carModels.put("Mazda",  Arrays.asList("MX-5", "RX-8"));
carModels.put("Audi",  Arrays.asList("A1", "A4", "A8"));

// actual work in 4 lines
List < String > allModels = new LinkedList < String > ();
for (List < String > brandModels: carModels.values()) {
        allModels.addAll(brandModels);
}

Now in Scala, back home ..

I took me a little research online, because I never used Scala on a daily basis, and miss a lot of knowledge on the collections API. Luckily it's not too hard to find good pointers online, and the Scala interpreter offers code completion help.

// setup
val carModels = Map("Mazda" -> List("MX-5", "RX-8"),
        "Audi" -> List("A1", "A4", "A8"))

// actual work, one liner
val allModels = carModels.values.reduce(_ ++ _)

The end result is actually not terribly hard to understand, but let me break it into pieces before I forget it myself:

carModels.values  // easy, similar as in Java

Now we have a collection of lists, and need to put all individual model names into one big list. Explicit looping is one way, but not very elegant. Another way of operating on a list, is using the "reduce" function. In general, you simply need to supply it a function which acts on two arguments, producing a single element.

For example, sum all numbers:

def add(x: Int, y: Int): x + y  // define simple 'add' function
List(1, 3, 5).reduce(add)   // evaluates to 9

So, this could lead to the following construction (with ++ for joining):

carModels.values.reduce( (models1, models2) => models1 ++ models2)

And thanks to implicit naming using underscores, we can end with:

carModels.values.reduce( _ ++ _ ) 

I still have to figure out what the difference is between the "++" and ":::" operators to join lists, and have many (!) other things to learn on Scala.

Feedback or corrections are very welcome!