0
votes

I'm not able to create custom conversions in order to use Currency and Locale as data types.

I'm using a @Configuration annotated class which will be auto-configured with META-INF/spring.factories:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.acme.autoconfigure.ConverterAutoConfiguration

I tried registering the converters directly as beans and also tried to create CassandraCustomConversions bean without success:

@Configuration
public class ConverterAutoConfiguration {
    /*
    @Bean
    public Converter<String, Currency> currencyReadConverter() {
        return new Converter<String, Currency>() {
            @Override
            public Currency convert(String source) {
                return Currency.getInstance(source);
            }
        };
    }

    @Bean
    public Converter<Currency, String> currencyWriteConverter() {
        return new Converter<Currency, String>() {
            @Override
            public String convert(Currency source) {
                return source.toString();
            }
        };
    }

    @Bean
    public Converter<String, Locale> localeReadConverter() {
        return new Converter<String, Locale>() {
            @Override
            public Locale convert(String source) {
                return StringUtils.parseLocaleString(source);
            }
        };
    }

    @Bean
    public Converter<Locale, String> localeWriteConverter() {
        return new Converter<Locale, String>() {
            @Override
            public String convert(Locale source) {
                return source.toString();
            }
        };
    }
    */

    @Bean
    public CassandraCustomConversions cassandraCustomConversions() {
        List<Converter<?, ?>> converters = new ArrayList<>();
        converters.add(CurrencyReadConverter.INSTANCE);
        converters.add(CurrencyWriteConverter.INSTANCE);
        converters.add(LocaleReadConverter.INSTANCE);
        converters.add(LocaleWriteConverter.INSTANCE);

        return new CassandraCustomConversions(converters);
    }

    enum CurrencyReadConverter implements Converter<String, Currency> {
        INSTANCE;

        @Override
        public Currency convert(String source) {
            return Currency.getInstance(source);
        }
    }

    enum CurrencyWriteConverter implements Converter<Currency, String> {
        INSTANCE;

        @Override
        public String convert(Currency source) {
            return source.toString();
        }
    }

    enum LocaleReadConverter implements Converter<String, Locale> {
        INSTANCE;

        @Override
        public Locale convert(String source) {
            return StringUtils.parseLocaleString(source);
        }
    }

    enum LocaleWriteConverter implements Converter<Locale, String> {
        INSTANCE;

        @Override
        public String convert(Locale source) {
            return source.toString();
        }
    }
}

With the CassandraCustomConversions bean I'm getting an exception directly at startup:

Caused by: org.springframework.data.mapping.MappingException: Cannot resolve DataType for type [class java.lang.String] for property [categoryId] in entity [com.acme.model.Category]; Consider registering a Converter or annotating the property with @CassandraType.

It seems its loosing all the default mappings.

When using the converter beans directly I'm getting the following exception:

org.springframework.data.repository.query.QueryCreationException: Could not create query for public abstract reactor.core.publisher.Flux com.acme.repository.CategoryLocaleReactiveRepository.findByUriNameInAndKeyLocale(java.util.Collection,java.util.Locale)! Reason: Could not inline literal of type java.util.Locale. This happens because the driver doesn't know how to map it to a CQL type. Try passing a TypeCodec or CodecRegistry to literal().

Based on this issue this should be possible somehow: https://github.com/spring-projects/spring-boot/issues/8411

1

1 Answers

1
votes

Try adding @WritingConverter and @ReadingConverter to your converters. I believe spring struggles a bit in deciding which converter to use with non custom types.

I created a local project and managed to get the conversion of Locale and Currency working once those 2 annotations were added to the appropriate converter.

I can push my test project to Github and share if you are still having issues.

Reference: https://docs.spring.io/spring-data/cassandra/docs/current/reference/html/#customconversions.java

Example Project: https://github.com/michaelmcfadyen/spring-data-cassandra-custom-converter-example