I am developing a project using Kotlin and the Quarkus framework (version 3.20 LTS), that connects to a MongoDB database, which has already been populated previously with some documents using the mongosh tool. To simplify CRUD operations, I am using Panache.
All the documents in the database follow the same structure, with the exception of a property from that document, let’s call it “a”, which can have two versions, like so:
{
“a”: {
“version”: “1”,
“name”: “ABC”
}
}
{
“a”: {
“version”: “2”,
“number”: “20”
}
}
As you can notice, version “1” has a property called “name”, however, version “2” doesn’t have this property, instead it has a property called “number”.
I've created the POJOs to represent the documents like so:
@MongoEntity(collection = "dto")
data class DTO (
@JsonDeserialize(using = ADeserializer::class)
@JsonProperty("a")
var a: A? = null,
) : PanacheMongoEntity()
@BsonDiscriminator(key = "version")
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY,
property = "version",
visible = true,
defaultImpl = A1::class
)
@JsonSubTypes(
JsonSubTypes.Type(value = A1::class, name = "1"),
JsonSubTypes.Type(value = A2::class, name = "2")
)
@JsonDeserialize(using = ADeserializer::class)
interface A {
var version: String?
}
@BsonDiscriminator("1")
@JsonTypeName("1")
data class A1(
override var version : String? = "2",
var name: String? = null
) : A
@BsonDiscriminator("2")
@JsonTypeName("2")
data class A2(
override var version : String? = "2",
var number: String? = null
) : A
Now, the tricky part is that there is a chance that some documents might not have a version associated with it. When this is the case, I want to user A1 as a default.
I am getting the following error when I try to retrieve a document that has no version:
org.bson.codecs.configuration.CodecConfigurationException: An exception occurred when decoding using the AutomaticPojoCodec.
Decoding into a 'DTO' failed with the following exception:
Failed to decode 'DTO'. Decoding 'a' errored with: Cannot find a public constructor for 'A'. Please ensure the class has a public, empty constructor with no arguments, or else a constructor with a BsonCreator annotation
A custom Codec or PojoCodec may need to be explicitly configured and registered to handle this type.
From what I understand, since A is an interface, it cannot create an instance of it. I've tried converting the interface to an open class that other classes can inherit from, but the version is populated with null.
I've tried to implement a custom deserializer, but no luck.
version
have a default value in the definition?