Skip to content

Marshalling error when using JodaModule with Jongo #366

Description

@JamesERi

I have an issue where I get a marshalling error when using the JodaModule to serialise/deserialise LocalDateTime.

The problem appears to be inside FongoDBCollection. The JodaModule serialises a year/month/day as an list of [year,month,day]. The replaceListAndMap method in FongoDBCollection replaces the list with a BasicDBObject with a 0, 1 and 2 property. However, when retrieving the object from the collection there doesn't appear to be a routine to map the BasicDBObject back to a list. This means that the jackson deserialisation fails.

I have a test that recreates the issue in this repository:
https://github.com/JamesTPF/fongo-collection-issue

The repository code works fine when running against a real mongo instance.

Build versions

compile 'org.jongo:jongo:1.3.0'
compile 'org.mongodb:mongo-java-driver:2.13.3'
compile 'de.undercouch:bson4jackson:2.7.0'
compile 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.9.4'
testCompile 'com.github.fakemongo:fongo:1.6.8'

Exception

org.jongo.marshall.MarshallingException: Unable to unmarshall result to class persistance.nosql.ExampleTest$TestDocument from content { "_id" : "anyId" , "testLocalDate" : { "0" : 2018 , "1" : 12 , "2" : 5}}

	at org.jongo.marshall.jackson.JacksonEngine.unmarshall(JacksonEngine.java:50)
	at org.jongo.ResultHandlerFactory$UnmarshallingResultHandler.map(ResultHandlerFactory.java:43)
	at org.jongo.FindOne.map(FindOne.java:51)
	at org.jongo.FindOne.as(FindOne.java:46)
	at persistance.nosql.ExampleTest.storeAndRetrieveObject(ExampleTest.java:30)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: expected String, Number or JSON Array
 at [Source: de.undercouch.bson4jackson.io.LittleEndianInputStream@7cc0cdad; pos: 30] (through reference chain: persistance.nosql.ExampleTest$TestDocument["testLocalDate"])
	at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
	at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1342)
	at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1138)
	at com.fasterxml.jackson.datatype.joda.deser.LocalDateDeserializer.deserialize(LocalDateDeserializer.java:66)
	at com.fasterxml.jackson.datatype.joda.deser.LocalDateDeserializer.deserialize(LocalDateDeserializer.java:16)
	at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:136)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
	at com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1611)
	at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1250)
	at org.jongo.marshall.jackson.JacksonEngine.unmarshall(JacksonEngine.java:47)
	... 27 more

Example test

package persistence.nosql;

import com.fasterxml.jackson.datatype.joda.JodaModule;
import com.github.fakemongo.Fongo;
import com.mongodb.WriteResult;
import org.joda.time.LocalDate;
import org.jongo.Jongo;
import org.jongo.MongoCollection;
import org.jongo.marshall.jackson.JacksonMapper;
import org.jongo.marshall.jackson.oid.MongoId;
import org.junit.Before;
import org.junit.Test;

public class ExampleTest {
    private Fongo fongo = new Fongo("someDatabase");
    private Jongo jongo;


    @Before
    public void createJongo() {
        jongo = new Jongo(fongo.getDB("exampleDatabase"), new JacksonMapper.Builder()
                .registerModule(new JodaModule())
                .build());
    }

    @Test
    public void storeAndRetrieveObject() {
        final MongoCollection myCollection = jongo.getCollection("myCollection");
        final TestDocument document = new TestDocument("anyId");
        myCollection.update("{'_id': #}", document.getId()).upsert().with(document);
        myCollection.findOne("{'_id': #}", document.getId()).as(TestDocument.class);
    }

    private static class TestDocument {

        @MongoId
        private String id;
        private LocalDate testLocalDate;

        TestDocument() {
        }

        public TestDocument(final String id) {
            this.id = id;
            this.testLocalDate = new LocalDate();
        }

        public String getId() {
            return id;
        }

        public void setId(final String id) {
            this.id = id;
        }

        public LocalDate getTestLocalDate() {
            return testLocalDate;
        }

        public void setTestLocalDate(LocalDate testLocalDate) {
            this.testLocalDate = testLocalDate;
        }
    }
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions