quarkus: When using kotlin with mongo panache, the deserializer fails unless all the constructor parameters are declared as nullable or have a default value
The title is pretty much self explanatory. When using a kotlin class that extends PanacheMongoEntity unless the fields are declared as nullable or have default values the deserialization when doing any find operation (e.g. listAll()) fails with the following error:
Caused by: org.bson.codecs.configuration.CodecConfigurationException: Cannot find a public constructor for 'ChargingInterval'.
at org.bson.codecs.pojo.CreatorExecutable.checkHasAnExecutable(CreatorExecutable.java:140)
at org.bson.codecs.pojo.CreatorExecutable.getInstance(CreatorExecutable.java:107)
at org.bson.codecs.pojo.InstanceCreatorImpl.<init>(InstanceCreatorImpl.java:40)
at org.bson.codecs.pojo.InstanceCreatorFactoryImpl.create(InstanceCreatorFactoryImpl.java:28)
at org.bson.codecs.pojo.ClassModel.getInstanceCreator(ClassModel.java:71)
at org.bson.codecs.pojo.PojoCodecImpl.decode(PojoCodecImpl.java:120)
at org.bson.codecs.pojo.PojoCodecImpl.decode(PojoCodecImpl.java:125)
at org.bson.codecs.pojo.AutomaticPojoCodec.decode(AutomaticPojoCodec.java:37)
Sample failing class:
package io.biapower.services.chargingsessionservice.domain
import io.quarkus.mongodb.panache.PanacheMongoEntity
import java.time.Instant
data class SampleDataClass(
var start: Instant = Instant.now(),
var end: Instant,
var num: Int = 0f
): PanacheMongoEntity()
Sample working class:
package io.biapower.services.chargingsessionservice.domain
import io.quarkus.mongodb.panache.PanacheMongoEntity
import java.time.Instant
data class SampleDataClass(
var start: Instant = Instant.now(),
var end: Instant = Instant.now(),
var num: Int = 0
): PanacheMongoEntity()
or:
package io.biapower.services.chargingsessionservice.domain
import io.quarkus.mongodb.panache.PanacheMongoEntity
import java.time.Instant
data class SampleDataClass(
var start: Instant = Instant.now(),
var end: Instant? = null,
var num: Int = 0
): PanacheMongoEntity()
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 15 (10 by maintainers)
Commits related to this issue
- Document the usage of Kotlin data classes with MongoDB with Panache Fixes #6742 — committed to loicmathieu/quarkus by loicmathieu 4 years ago
@TheVidAllMayThe when writing the documentation part (#6877 ) two questions arises. If you can try the following and provide feedback this would be great :
@BsonCreator
approach works in native mode ?no-arg
compiler plugin instead of using the@BsonCreator
@gsmet @TheVidAllMayThe using the
no-arg
compiler plugin and the not mandatory@MongoEntity
annotation (as the compiler plugin needs an anotation to target classes that needs a no-arg constructor) it works.I tested native mode and it works for both approach.
I will update the guide acordingly and close this issue.
@TheVidAllMayThe this is not a Quarkus MongoDB with Panache issue but it’s a limitation of Kotlin dataclass with frameworks that needs an empty constructor. We use MongoDB automatic pojo codec to serialize to/from the database and it needs an empty constructor.
There is multiple way to fix the issue:
Create a BSON Codec, it will be automatically registered by Quarkus and will be used instead of the automatic pojo codec: https://quarkus.io/guides/mongodb#simplifying-mongodb-client-usage-using-bson-codec
Use the
@BsonCreator
annotation to tell the MongoDB automatic pojo codec to use the Kotlin dataclass default constructor, in this case all fields needs to be annotated with@BsonProperty
: https://mongodb.github.io/mongo-java-driver/3.12/bson/pojos/#supporting-pojos-without-no-args-constructorsUpdating the
SampleFailingDataClass
with the@BsonCreator
annotation make the sample application working.If it’s OK, I propose to add a section on the MongoDB with Panache guide explaining how to use Kotlin dataclass with the MongoDB automatic pojo codec.