Spring -Mongodb storing/retrieving enums as int not string Spring -Mongodb storing/retrieving enums as int not string mongodb mongodb

Spring -Mongodb storing/retrieving enums as int not string


After a long digging in the spring-mongodb converter code,Ok i finished and now it's working :) here it is (if there is simpler solution i will be happy see as well, this is what i've done ) :

first define :

public interface IntEnumConvertable {      public int getValue();    }

and a simple enum that implements it :

public enum tester implements IntEnumConvertable{       vali(0),secondvali(1),thirdvali(5);    private final int val;    private tester(int num)    {        val = num;              }    public int getValue(){        return val;    }}

Ok, now you will now need 2 converters , one is simple , the other is more complex. the simple one (this simple baby is also handling the simple convert and returns a string when cast is not possible, that is great if you want to have enum stored as strings and for enum that are numbers to be stored as integers) :

public class IntegerEnumConverters {    @WritingConverter    public static class EnumToIntegerConverter implements Converter<Enum<?>, Object> {        @Override        public Object convert(Enum<?> source) {            if(source instanceof IntEnumConvertable)            {                return ((IntEnumConvertable)(source)).getValue();            }            else            {                return source.name();            }                       }    }    }

the more complex one , is actually a converter factory :

public class IntegerToEnumConverterFactory implements ConverterFactory<Integer, Enum> {        @Override        public <T extends Enum> Converter<Integer, T> getConverter(Class<T> targetType) {            Class<?> enumType = targetType;            while (enumType != null && !enumType.isEnum()) {                enumType = enumType.getSuperclass();            }            if (enumType == null) {                throw new IllegalArgumentException(                        "The target type " + targetType.getName() + " does not refer to an enum");            }            return new IntegerToEnum(enumType);        }        @ReadingConverter        public static class IntegerToEnum<T extends Enum>  implements Converter<Integer, Enum> {            private final Class<T> enumType;            public IntegerToEnum(Class<T> enumType) {                this.enumType = enumType;            }            @Override            public Enum convert(Integer source) {                  for(T t : enumType.getEnumConstants()) {                      if(t instanceof IntEnumConvertable)                      {                          if(((IntEnumConvertable)t).getValue() == source.intValue()) {                                return t;                            }                                               }                                         }                    return null;               }        }}

and now for the hack part , i personnaly didnt find any "programmitacly" way to register a converter factory within a mongoConverter , so i digged in the code and with a little casting , here it is (put this 2 babies functions in your @Configuration class)

      @Bean        public CustomConversions customConversions() {            List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();            converters.add(new IntegerEnumConverters.EnumToIntegerConverter());     // this is a dummy registration , actually it's a work-around because// spring-mongodb doesnt has the option to reg converter factory.// so we reg the converter that our factory uses. converters.add(new IntegerToEnumConverterFactory.IntegerToEnum(null));                  return new CustomConversions(converters);        }    @Bean    public MappingMongoConverter mappingMongoConverter() throws Exception {        MongoMappingContext mappingContext = new MongoMappingContext();        mappingContext.setApplicationContext(appContext);        DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory());        MappingMongoConverter mongoConverter = new MappingMongoConverter(dbRefResolver, mappingContext);                mongoConverter.setCustomConversions(customConversions());               ConversionService convService = mongoConverter.getConversionService();        ((GenericConversionService)convService).addConverterFactory(new IntegerToEnumConverterFactory());                          mongoConverter.afterPropertiesSet();        return mongoConverter;    }