1

I have a simple pojo

import lombok.Data;

@Data
public class DataPojo {
   private LocalDateTime myDate;           
}

When I try to read the pojo from mongo + mongojack

MongoCredential credential = MongoCredential.createCredential(userName, "aDb", password.toCharArray());
MongoClient mongoClient = new MongoClient(new ServerAddress(mongoServer), Arrays.asList(credential));
DB db = mongoClient.getDB("aDb");
DBCollection aCollection = db.getCollection("aCollection");

JacksonDBCollection<DataPojo, String> jDbCol = JacksonDBCollection.wrap(aCollection, DataPojo.class, String.class);
DataPojo d = jDbCol.findOne();

I get the following error

java.lang.RuntimeException: IOException encountered while reading from a byte array input stream
at org.mongojack.internal.stream.JacksonDBDecoder.decode(JacksonDBDecoder.java:67)
...
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Problem deserializing property 'myDate' (expected type: [simple type, class java.time.LocalDateTime]; actual type: java.util.Date), problem: argument type mismatch (through reference chain: DataPojo["myDate"])

I have read things about @JsonDeserialize(using = LocalDateTimeDeserializer.class) and that just leads to other errors.

Caused by: com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (VALUE_EMBEDDED_OBJECT), expected START_ARRAY: Expected array or string.

I am using mongo-java-driver version 3.1.0-rc0, mongojack version 2.5.1. The mongodb that I am running against is 2.6.9. The field that I am trying to read is an ISODate.

It seems like my problem is at the driver level. Is there a way to tell mongo driver to represent dates as java.time.LocalDateTime instead of java.util.Date?

Jeff Benton
  • 146
  • 1
  • 8
  • Hey there. I've never worked with MongoDB before or Jackson annotations, but I've always wanted too. I took a second to see if I could solve you question as is, and I haven't been able to. Just in case no one answers, would you be willing to use a codec if the annotations don't suffice? I'm just not sure what your end goal is: getting annotations to work or getting the application to work. I've been looking at the following resource on [Codecs and CodecRegistries](http://matteosilvestri.blogspot.ca/2015/03/overview-of-pluggable-codecs-in-mongodb.html). Maybe it will do what you need. – Mike Dec 11 '15 at 11:29
  • Interesting. My main goal was to see what it would take to deserialize into LocalDateTime object. I prefer to stick whatever the best practice would be for getting this to work. – Jeff Benton Dec 11 '15 at 16:20
  • As far as best practices go, I have no idea for MongoDB. All I've come to realize is that while annotations can be beneficial, I find that they can be overly magical. Stick to the simplest understandable solution, and you'll find yourself better off for it. – Mike Dec 11 '15 at 17:13

1 Answers1

0

Your problem is not at the driver level; MongoDB has no knowledge at all of java.util.Date. But the BSON Date type is nearly identical to java.util.Date in internal representation. Thankfully in the MongoDB shell it's always printed using timezone Z, so it's not too confusing to just ignore the timezone and treat it as a java.time.LocalDateTime instead, but there's no built-in way to make that explicit at the BSON level.

At the mapper level, there are several different ways you can specify the mapping you want here. From your question it's not clear which LocalDateTimeDeserializer you tried using; but you want to make sure first of all that you're using one that targets java.time.LocalDateTime, not org.joda.time.LocalDateTime. If you've checked that and still are having trouble, then you might consider writing your own Converter instead of a Deserializer, which you'd invoke with a nearly identical annotation:

@JsonDeserialize(converter = LocalDateTimeConverter.class)

The difference being that you'd just need to implement a convert method from a java.util.Date to a org.joda.time.LocalDateTime, rather than dealing with JSON streams at all.

kdkeck
  • 2,097
  • 1
  • 14
  • 10