So we decided the best way forward for Errai was to build our own annotation-driven marshalling framework based on code generation. My favourite part about this is that we got to design it from the ground up to support immutable types.
First, here's a basic mutable Bean that can be serialized and deserialized by Errai Marshalling:
Pretty easy, right? Just annotate it with @Portable, and OrientationSensorReading objects will be marshallable on both the client and the server. Notice that the java.util.Date instance didn't require any special treatment. In fact, all GWT-translatable types in the standard Java library (including Exceptions) are handled by Errai Marshalling out-of-the-box. Likewise, you can nest instances and collections of any Portable entity types you have declared in your project's codebase.
But wait! This type is a natural candidate for immutability. Once we've taken a sample from an accelerometer, this reading should never change. Here's an immutable variant of the above that works with Errai Marshalling:
Note the @MapsTo annotations on the constructor arguments. These specify the names of the Bean properties the arguments map to. This is necessary because–unfortunately–the names of method and constructor parameters are not preserved in Java class files. I believe the advantage of having truly immutable objects where they make sense in your code will more than make up for this inconvenience.
Errai marshalling also understands the factory method pattern recommended by Josh Bloch in Effective Java. This is also an Errai Marshalling compatible type:
In this case, because Errai Marshalling simply calls your static method when it needs a particular instance of a type, you can return whatever you want. For example, you can build in an instance cache and guarantee there are no duplicates floating around with the same values. Or you could obtain instances via GWT.create() and take advantage of code splitting in your marshallable types. This kind of flexibility is wonderful.
But what about JAXB? Errai brings Java EE 6 to the browser, and JAXB is part of Java EE 6, right? Well, we would like to implement JAXB on the client eventually, but Errai Marshalling was much quicker to implement and it offers a more compact API that's well-suited to the immediate needs of Errai:
- JAXB is a much larger API than Errai Marshalling needs. Much of the complexity of JAXB lies in the ability to control the XML representation of the object graph. This is essential if you are mapping Java objects to a predefined XML schema, but a lot of dead weight if you aren't.
- JAXB does not support marshalling instances of immutable types; Errai Marshalling does.
- JAXB is primarily intended for XML; Errai Marshalling is primarily intended for JSON.
Note also that Errai Marshalling and JAXB annotations can happily coexist. It's not an either/or choice. In most cases, it suffices to stick "@Portable" on an existing JAXB entity class, and you get the best of both worlds.