Store Java 8 Instant as BSON date using SpringData-MongoDB

java, java-time, spring, spring-data, spring-data-mongodb

Solution

I think the problem is what you are trying to use `Instant` as a time. Conceptually it is a point of the timeline and it does not imply formatting.

As we know, Java 8 time API was developed with an eye at joda-time (and with partisipating of joda-time's developers). Here is comment from joda-time `Instant`:

An Instant should be used to represent a point in time irrespective of any other factor, such as chronology or time zone.

That's why there is no formatting possibilities for `org.joda.time.Instant` in `JodaDateTimeFormatAnnotationFormatterFactory` which appeared in Spring since version 3.0. And also it was not implemented in `Jsr310DateTimeFormatAnnotationFormatterFactory`

So, you should use custom converter or consider to use more suitable class.

Problem

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?

Original source

Related problems