3

I have a weird behavior using SpringDataCouchbase maybe you can help me to understand.

Context

  • I'm using Spring-data-couchbase (v.3.1.9.RELEASE) with SpringBoot 2.
  • My application has an entity with a LocalDate field like
@Getter
@Setter
class MyEntity {
    private LocalDate fieldName;
    ... Other basic/primitive fields
}

I have configured the basic converters to deal with LocalDates in the CouchbaseConfig bean.

@Configuration
@EnableCouchbaseRepositories(basePackages = {"com.example.repository.model"})
public class CouchbaseConfig extends AbstractCouchbaseConfiguration {
    @Override
    public CustomConversions customConversions() {
        List<?> converters = Arrays.asList(
                LocalDateTimeToStringConverter.INSTANCE,
                StringToLocalDateTimeConverter.INSTANCE,
                LocalDateToStringConverter.INSTANCE,
                StringToLocalDateConverter.INSTANCE);
        return new CouchbaseCustomConversions(converters);
    }

    @WritingConverter
    public enum LocalDateToStringConverter implements Converter<LocalDate, String> {
        INSTANCE;
        
        @Override
        public String convert(LocalDate source) {
            return source.format(DateUtils.SHORT_DATE_FORMATTER);
        }
    }
    
    @ReadingConverter
    public enum StringToLocalDateConverter implements Converter<String, LocalDate> {
        INSTANCE;
        
        @Override
        public LocalDate convert(String source) {
            return LocalDate.parse(source, DateUtils.SHORT_DATE_FORMATTER);
        }
    }

The save and find operations work without problems using the CrudRepository but now I have to do a dynamic query using the CouchbaseTemplate in a CustomRepository.

The problem

I need to use template.findByN1QLProjection(queryWithParameters, MyProjection.class) to retrieve only those fields required from MyEntity but findByN1QLProjection method uses translationService.decodeFragment(json.toString(), entityClass) which is implemented by JacksonTranslationService like

  public <T> T decodeFragment(String source, Class<T> target) {
    try {
      return objectMapper.readValue(source, target);
    }
    catch (IOException e) {
      throw new RuntimeException("Cannot decode ad-hoc JSON", e);
    }
  }

The problem is: the ObjectMapper used by decodeFragment method is a new one created inside the class that doesn't use the converters from CouchbaseConfig class and as no JavaTimeModule is configured the exception com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of java.time.LocalDate is thrown.

After some time I figured out the problem and I configured a different translationService in the CouchBaseConfig with a custom object mapper which solved the error.

Question

Why entities in SpringDataCouchbase are handled in a different way when you use template findOperations than when you use CrudRepository? Am I doing something wrong?

Thanks for your time.

Community
  • 1
  • 1
Hernán Tenjo
  • 179
  • 2
  • 12

0 Answers0