Serializing DateTime for mongodb: Can't find a codec for class org.joda.time.DateTime

Hi,

we have a plugin that’s storing information in the MongoDB. When we try to store a document/class with org.joda.time.DateTime it fails with following exception:

org.bson.codecs.configuration.CodecConfigurationException: Can’t find a codec for class org.joda.time.DateTime.

The MongoDB is the interface setup as followed:

    PluginClass(MongoConnection mongoConnection, MongoJackObjectMapperProvider mapperProvider,[...]) throws IOException {
        final DBCollection dbCollection = mongoConnection.getDatabase().getCollection(collectionName);
        this.set_collection = JacksonDBCollection.wrap(dbCollection, Information.class, String.class, mapperProvider.get());
       [...]
    }

The mapper is indeed of the type org.graylog2.bindings.providers.MongoJackObjectMapperProvider.
Which, as far as my understanding goes, is the needed mapper for this, because it brings additional support for de/serialising classes such as yoda.DateTime.

main/java/org/graylog2/bindings/providers/MongoJackObjectMapperProvider.java:

import org.joda.time.DateTime;
[...]
@Singleton
public class MongoJackObjectMapperProvider implements Provider<ObjectMapper> {
    private final ObjectMapper objectMapper;

    @Inject
    public MongoJackObjectMapperProvider(ObjectMapper objectMapper) {
        // add the mongojack specific stuff on a copy of the original ObjectMapper to avoid changing the singleton instance
        this.objectMapper = objectMapper.copy()
                .addHandler(new ReplaceUnknownSubtypesWithFallbackHandler())
                .setPropertyNamingStrategy(new PreserveLeadingUnderscoreStrategy())
                .registerModule(new SimpleModule("JSR-310-MongoJack")
                        .addSerializer(ZonedDateTime.class, new MongoZonedDateTimeSerializer())
                        .addDeserializer(ZonedDateTime.class, new MongoZonedDateTimeDeserializer())
                        .addSerializer(DateTime.class, new MongoJodaDateTimeSerializer())
                        .addDeserializer(DateTime.class, new MongoJodaDateTimeDeserializer()));

        MongoJackModule.configure(this.objectMapper);
        EncryptedValueMapperConfig.enableDatabase(this.objectMapper);
    }

The .configure() is also mentioned in the documentation:
http://javadox.com/org.mongojack/mongojack/2.0.0-RC5/org/mongojack/JacksonDBCollection.html#wrap(com.mongodb.DBCollection,%20java.lang.Class,%20java.lang.Class,%20com.fasterxml.jackson.databind.ObjectMapper)

I’m pretty much at a loss here. I looked at how other components inside Graylog handle this (e.g. OutputServiceImpl.java, ClusterConfigServiceImpl) and then modeled my code in likeness.

I appreciate any input and ideas. Thanks.

Hello,

I might be able to help, but I have some question for you to understand what happened.

Where did you get this plugin? And what does this Plugin do for Graylog?
Judging from the title of this post have you seen these ?

Hi @gsmith,

the plugin was written by me. I’m the master of my own hell so to speak. We us it to aggregate information over multiple log entries.

The PluginClass is an excerpt from the plugin, the second quote from the Graylog source. There is very little documentation for plugin developer, so I basically oriented my self by looking how other components interacted with the MongoDB. I did come across the first link you posted. From the libaries documentation I would say the MongoJackObjectMapperProvider is the thing to use, as it does the things you need to set up.

I’d rather like to avoid bascially “reinventing” the same functionally inside the plugin. Using one consistent mapper across everything seems like the sane choice. So I’m very open to suggestions what I’m missing here…

Thanks!