Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 556
Vic Avatar asked Nov 23 '14 16:11

Vic


1 Answers

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.

like image 122
retroq Avatar answered Oct 08 '22 16:10

retroq