I'm in the process of taking an existing MongoDB collection and wrapping it in a Repository in a Spring Boot application. Documents can be very large, so in many cases we only want to pull back a subset of the fields contained in it. When I try to do a projection that involves nested objects, I get a MappingInstantiationException.
I have an object structure like this:
@Document
data class OuterDocument(
@Id
val id: String,
val bar: String,
val nested: NestedDocument
)
data class NestedDocument(
val nestedFoo: String
)
// This is the class I want to project into
data class OuterDto(
val id: String,
val nested: NestedDocument
)
My repository looks like this:
interface OuterRepository: MongoRepository<OuterDocument, String> {
@Query("{id: ?0}")
fun getDto(id: String): OuterDto?
}
When calling this, I get this exception:
org.springframework.data.mapping.model.MappingInstantiationException: Failed to instantiate org.springframework.data.mapping.model.MappingInstantiationException: Failed to instantiate OuterDto using constructor fun <init>(kotlin.String, NestedDocument): OuterDto with arguments null,null
at app//org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator$EntityInstantiatorAdapter.createInstance(ClassGeneratingEntityInstantiator.java:290)
at app//org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:102)
at app//org.springframework.data.mongodb.core.convert.MappingMongoConverter.doReadProjection(MappingMongoConverter.java:374)
...
I am unsure if this approach is supposed to work, but tracing through the code, it seems to be trying really hard to do it, and it does work when there are no nested objects (so, eg. if I replaced nested with bar in my DTO, it would be fine).
This seems similar to this question, but I'm not nesting my type declarations, which seemed to be the root issue there.
Is the form shown by getDto supposed to work? Is there some modification I need to make to my classes or function?