I'm using Kotlin with Jongo to access MongoDB. Jongo uses Jackson to serialize/deserialize objects in order to save and read them from MongoDB. I use Jackson-Kotlin module to help serialize Kotlin data classes using constructors.
Here's an example of a dataclass that serializes just fine:
data class Workflow (
@field:[MongoId MongoObjectId] @param:MongoId
var id: String? = null,
val name: String,
val states: Map<String, State>
)
Here's an example of a similar class that fails to deserialize:
data class Session (
@field:[MongoObjectId MongoId] @param:MongoId
var id: String? = null,
var status: CallStatus,
var currentState: String,
var context: MutableMap<String, Any?>,
val events: MutableMap<String, Event>
)
Following exception is thrown by Jongo because Jackson deserialization fails:
org.jongo.marshall.MarshallingException: Unable to unmarshall result to class example.model.Session from content { "_id" : { "$oid" : "56c4976aceb2503bf3cd92c2"} , "status" : "Ongoing" , "currentState" : "Start" , "context" : { } , "events" : { }}
... bunch of stack trace entries ...
Caused by: java.lang.IllegalArgumentException: Argument #1 of constructor [constructor for example.model.Session, annotations: [null]] has no property name annotation; must have name when multiple-parameter constructor annotated as Creator
It does work if I fully annotate the Session data class like this:
data class Session (
@field:[MongoObjectId MongoId] @param:MongoId
var id: String? = null,
@JsonProperty("status")
var status: CallStatus,
@JsonProperty("currentState")
var currentState: String,
@JsonProperty("context")
var context: MutableMap<String, Any?>,
@JsonProperty("events")
val events: MutableMap<String, Event>
}
My question is, why does it work for Workflow? What's the subtle difference that makes unmarshalling fail for Session data class, when it's not fully annotated?
EDIT
Difference was that I tested Workflow test case running it from Gradle, which used different version of Kotlin then the Session test case that I run from IDEA IDE. Update of IDEA's Kotlin plugin also updated Kotlin version that IDEA uses to run test cases, which I didn't notice. This resulted in mismatched versions of Kotlin and Jackson-Kotlin library. Accepted answer below pointed out what needs to be configured in order get things working again.
You would get this error if MongoDB is using an ObjectMapper
that does not have the Jackson-Kotlin module registered into it. Your JsonProperty
annotations are basically doing the same as what the module does implicitly. But if it is not present, you would receive about the same error message.
Things to look at:
You have compatible version of Jackson-Kotlin module that matches your version of the Kotlin code. For RC 1050 or newer, you need the latest releases of Jackson module mentioned in the README.MD file on GitHub.
Older versions of the Jackson-Kotlin module are not compatible with Kotlin 1.0.0. You must update or you will have silent failures (the module cannot recognize a Kotlin class, so ignores it). Releases for Kotlin 1.0.0 will be available on Maven Central shortly. In the meantime use the EAP repository:
maven { url "http://dl.bintray.com/jaysonminard/kohesive" }
For Kotlin 1.0.0, use one of:
- release
2.7.1-1
(for Jackson2.7.x
)- release
2.6.5-2
(for Jackson2.6.x
)- release
2.5.5-2
(for Jackson2.5.x
)Later this will move back to Maven Central.
what is the actual JSON being sent to Jackson