Categories
java java-time spring spring-data spring-data-mongodb

Store Java 8 Instant as BSON date using SpringData-MongoDB

I have the following class that I want to store in MongoDB using Spring Data

@Document()
public class Tuple2<T extends Enum<T>> {
@Id
private String id;
@Indexed
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private final Instant timeCreated;
...
}

DateTimeFormat annotation javadoc states:

Declares that a field should be formatted as a date time.
Supports formatting by style pattern, ISO date time pattern, or custom format pattern string. Can be applied to java.util.Date, java.util.Calendar, java.long.Long, Joda-Time value types; and as of Spring 4 and JDK 8, to JSR-310 java.time types too.

I am using Spring 4.1.1 and JDK 8, so I’d expect that it applies to Instant. However, here’s what is actually stored:

"timeCreated" : {
"seconds" : NumberLong(1416757496),
"nanos" : 503000000
}

If I write and register custom convertor from Instant to Date like explained in this answer then it works, however I’d like to avoid that, as I am sure there must be a better way.

After further digging in Spring source code I’ve found the following class Jsr310DateTimeFormatAnnotationFormatterFactory which looks promising:

Formats fields annotated with the DateTimeFormat annotation using the JSR-310 java.time package in JDK 8.

Its’ source does not reference Instant, but it does reference OffsetTime and LocalTime. Even so, when I change Instant to be OffsetDateTime in my example, it is still stored as a composite object instead of ISODate.

What is missing?