I'm having some difficulty configuring object mapping for MongoDB in Micronaut with Kotlin. I'm getting errors like:
Decoding into a 'Asset' failed with the following exception:
Cannot find a public constructor for 'Asset'.
A custom Codec or PojoCodec may need to be explicitly configured and registered to handle this type. org.bson.codecs.configuration.CodecConfigurationException: An exception occurred when decoding using the AutomaticPojoCodec. Decoding into a 'Asset' failed with the following exception:
Cannot find a public constructor for 'Asset'.
A custom Codec or PojoCodec may need to be explicitly configured and registered to handle this type.
With KMongo, this is easy. However the MongoClient injected by Micronaut doesn't have KMongo's codec registry.
I can get it working as follows:
val db: MongoDatabase by lazy {
val codecRegistry = ClassMappingType.codecRegistry(MongoClientSettings.getDefaultCodecRegistry())
client.getDatabase("db-name").withCodecRegistry(codecRegistry)
}
This code is taken directly from KMongo. (BTW, using database.withKMongo()
resulted in the same error)
Although this works, what I'd like is to let Micronaut use KMongo to create the client, or let it use its codec like above, using configuration (application.yml).
There is a codec-registry
setting mentioned here: https://micronaut-projects.github.io/micronaut-mongodb/latest/guide/configurationreference.html, but I have no idea what to enter in that setting to make it work.
Any help is appreciated!
You can simply define the codec registry as a bean. Since you aren't in control of the class being registered you can create a factory
@Factory
class KMongoFactory {
@Singleton
fun kCodecRegistry(): CodecRegistry {
return ClassMappingType.codecRegistry(MongoClientSettings.getDefaultCodecRegistry());
}
}
Something like the above should do it
EDIT: Be aware that MongoClients.getDefaultCodecRegistry()
is added by default