I have a large collection of documents in my db, which has not been maintained very well. Most of the time the createdOn is stored as "yyyy-dd-MM HH:mm:ssZ"
pattern, but there's several records in which this same field is somehow stored using an epoch format.
Below are samples extracted using MongoDB Compass as Default Extended JSON
Document with no issue
"createdOn": {
"$date": "2019-05-08T07:41:23.312Z"
}
Document with issues
"createdOn": {
"$numberLong": "1678864933943"
}
When querying the documents, Spring (or Jackson, or the Java Mongo driver) retrieves this value as a Double, then attempts to convert it back to my entity which is a Date object.
@Data
public class BaseModel {
@Id
@JsonSerialize(using= ObjectIdSerializer.class)
protected ObjectId _id;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-dd-MM HH:mm:ssZ")
@JsonProperty("createdAt")
Date createdOn;
This results in the following error being thrown
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.Double] to type [java.util.Date]
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:321)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:194)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.getPotentiallyConvertedSimpleRead(MappingMongoConverter.java:1032)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readValue(MappingMongoConverter.java:1584)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$MongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1478)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readProperties(MappingMongoConverter.java:450)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.populateProperties(MappingMongoConverter.java:367)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:347)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:317)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:250)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:246)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:98)
at org.springframework.data.mongodb.core.MongoTemplate$ReadDocumentCallback.doWith(MongoTemplate.java:3141)
at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:2788)
at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:2518)
at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:2500)
at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:856)
at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:842)
... <omitted further lines, will post if requested>
Is there a simple solution that will cater for the 2 (or more) possible date formats that is stored in the db to be retrieved gracefully?
I've tried registering a converter to Spring (using @Component
with a class implementing Converter<Double, Date>
) but that didn't work.
I've also tried using @JsonDeserialize(using= DateDeserializers.DateDeserializer.class)
to no avail either.
Limitations :
LocalDate
or Instant
as I am concerned of potential side effects as this project is rather huge and the modification for this field is on the BaseModel
which is the base entity that all other entities extends from.Additional information (versions and stuff):
Footnote : I realised the question title may be misleading but I really have no idea how else to describe this problem in a single sentence.
The issue is that the converter required is on the Mongo repository side. To solve the issue, I had to register a converter to the MongoCustomConversions
@ReadingConverter
public class MyCustomConverter implements Converter<Double, Date> {
@Override
public Date convert(Double source) {
//handle here
return handledValue;
}
}
@Configuration
public class ConverterConfig {
@Bean
public MongoCustomConversions mongoCustomConversions() {
List<Converter> list = new ArrayList<>();
list.add(new MyCustomConverter());
return new MongoCustomConversions(list);
}
}