Is there a good alternative to serializing enumerations in Java?
The Java language benefits a lot from adding enumerations; Unfortunately, they don't work when sending serialized objects between systems with different code levels
Example: suppose you have two systems a and B. they both start at the same code level, but at some point they start to view code updates at different points in time Now suppose there are some
public enum Whatever { FIRST; }
There are other objects that can reference the constants of the enumeration These objects are serialized and sent from a to B, and vice versa Now consider that B has an updated version of whatever
public enum Whatever { FIRST; SECOND }
then:
class SomethingElse implements Serializable { ... private final Whatever theWhatever; SomethingElse(Whatever theWhatever) { this.theWhatever = theWhatever; ..
Get instantiation
SomethingElse somethin = new SomethingElse(Whatever.SECOND)
It is then serialized and sent to a (for example, as a result of some RMI calls) This is bad, because now there will be an error when deserializing on a: a knows the whatever enumeration class, but in the version without second
We think it's hard; Now I am very eager to use enumeration in the case of actually "perfect enumeration"; Just because I know I can't easily extend the existing enumeration in the future
Now I want to know: is there a (good) strategy to avoid compatibility with enumerations? Or I really want to go back to the "pre enum" era; And don't use enumerations, but must rely on my solution of using ordinary strings throughout the place?
Update: Please note that using serialVersionUID does not help That can only help you make the incompatible change "more obvious" But the point is: I don't care why deserialization fails - because I have to avoid it And I can't change the way I serialize objects We are doing RMI; We are serializing to binary; I can't change it
Solution
As @ Jesper mentioned in his comments, I will recommend something like JSON for your inter service communication This gives you better control over how unknown enum values are handled
For example, with Jackson, which is always great, you can use deserialization features read_ UNKNowN_ ENUM_ VALUES_ AS_ Null or read_ UNKNowN_ ENUM_ VALUES_ USING_ DEFAULT_ VALUE. Both allow your application logic to handle unknown enumeration values according to your needs
Example (directly from Jackson DOC)
enum MyEnum { A,B,@JsonEnumDefaultValue UNKNowN } ... final ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.READ_UNKNowN_ENUM_VALUES_USING_DEFAULT_VALUE); MyEnum value = mapper.readValue("\"foo\"",MyEnum.class); assertSame(MyEnum.UNKNowN,value);