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.