java - Backwards Compatibility of Enum Additions for Objectify/Appengine -


we using objectify google app engine java. persisting variety of enum constants in datastore using supplied enumtranslatorfactory stores/loads constant using enum#name(). works well.

when release new versions of our app gae, new version lives next old version(s) both serving requests simultaneously clients. explained google's traffic splitting docs.

upgrades system introduce new enum constants cause errors during loading. example:

version 1 has following enum:

enum meal{breakfast,lunch,dinner} 

version 2 has additional constant added enum support british meals:

enum meal{breakfast,lunch,tea,dinner} 

while testing version 2 of app, tea persisted entity. subsequently version 1 load entity, objectify attempt convert tea enum using enum#valueof(...) throws runtime exception.

objectify docs explain data migration enums, doesn't satisfy above situation.

i'm interested in suggestions how best handle situation.

first, provide interface provide default value if enum not known.

public interface enumwithdefault<e extends enum<e>> {     e getdefault(); } 

an enum may have future additions should implement interface:

public enum myenum implements enumwithdefault<myenum>{   enum_in_version_1, future;    public myenum getdefault(){ return future; } } 

register translatorfactory provide default if implemented:

       return new valuetranslator<enum<?>, string>(path, string.class) {     @override     public enum<?> loadvalue(string value, loadcontext ctx) {         try{            return enum.valueof((class<enum>)type, value.tostring());         }catch(exception e){            if (enumwithdefault.class.isassignablefrom(enumtype)) {                 enumwithdefault<e> = (enumwithdefault<e>) enumtype.getenumconstants()[0];                 result = any.getdefault();            }else{               throw e;            }          }     } 

version 2 deployed new enum:

public enum myenum implements enumwithdefault<myenum>{   enum_in_version_1, enum_in_version_2, future;    public myenum getdefault(){ return future; } } 

when version 2 of app deployed , enum_in_version_2 stored in datastore related entity, response differs when hitting endpoints of 2 versions.

hitting first version returns value future allowing client present appropriate message:

http://1.myapi.appspot.com/entities 

returns:

<myentity id='xyz' category='future' /> 

hitting version 2 provides new enum:

http://2.myapi.appspot.com/entities 

returns:

<myentity id='xyz' category='enum_in_version_2' /> 

this solution allows additional enumerations added , used in later release while older versions present value client per contract "future" possible.


Comments