Skip to content

New values make Enums backward incompatible #728

@avadhoot

Description

@avadhoot

Problem: If I add a new value to an existing Enum and start returning it from my service any client who has not upgraded to the latest version of the JAR containing the new Enum will start getting exceptions during deserialization even if the DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL has been set to enabled.

Here is a sample Enum being returned from the service:

public enum MyEnum {

    VALUE1("VALUE1"),
    VALUE2("VALUE2"),
    VALUE3("VALUE3");

    private final String value;
    private static Map<String, MyEnum> constants = new HashMap();

    private MyEnum(String value) {
        this.value = value;
    }

    @JsonValue
    public String toString() {
        return this.value;
    }

    @JsonCreator
    public static MyEnum fromValue(String value) {
        MyEnum constant = (MyEnum)constants.get(value);
        if(constant == null) {
            throw new IllegalArgumentException(value);
        } else {
            return constant;
        }
    }

    static {
        MyEnum[] arr$ = values();
        int len$ = arr$.length;

        for(int i$ = 0; i$ < len$; ++i$) {
            MyEnum c = arr$[i$];
            constants.put(c.value, c);
        }
    }
}

This is the Enum on the client side:

public enum MyEnum {

    VALUE1("VALUE1"),
    VALUE2("VALUE2");

    private final String value;
    private static Map<String, MyEnum> constants = new HashMap();

    private MyEnum(String value) {
        this.value = value;
    }

    @JsonValue
    public String toString() {
        return this.value;
    }

    @JsonCreator
    public static MyEnum fromValue(String value) {
        MyEnum constant = (MyEnum)constants.get(value);
        if(constant == null) {
            throw new IllegalArgumentException(value);
        } else {
            return constant;
        }
    }

    static {
        MyEnum[] arr$ = values();
        int len$ = arr$.length;

        for(int i$ = 0; i$ < len$; ++i$) {
            MyEnum c = arr$[i$];
            constants.put(c.value, c);
        }
    }
}

Now if the service returns 'VALUE3' then the client's deserialization will fail even if DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL is enabled.
The reason for this is that the ObjectMapper's deserialization method will always call fromValue as it is annotated with @JsonCreator. If this annotation is removed the toString method gets called which won't throw the exception but return NULL which can then be handled by the client.

My requirement is for the Enums to be backward compatible to support clients which integrate with older versions of my service response.

What is the best way to handle this problem?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions