Kotlin Coroutine Driver can't serialise a simple data class

Good day All,
I am using the latest Kotlin Coroutine driver (org.mongodb:mongodb-driver-kotlin-coroutine:4.10.2) to connect to my local MongoDB instance (running locally via docker).
Following the quick start guides I am able to connect to DB, send a ping and create a new empty collection with no issues.

But when I try to insert a new record to my new collection, I get a codec not found error:

org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for CodecCacheKey{clazz=class com.example.kotlinmongo.SampleEntity, types=null}.

My entity type is a fairly trivial data class, which contains a single String field and according to the following page kotlin data classes are supposed to be serialized/de-serialized out-of-the-box using a default codec.

I tried a data class only with primitive types, I tried it with @BsonId field, tried with and without kotlinx serialization library in the project - same result.
I am using JDK17 and Kotlin 1.8.
Am I missing something or found a bug?

Here’s a sample code repo to reproduce the problem:

Appreciate your help!

Update: it appears that this issue is only occurring when running in a SpringBoot.
I tried to run my code from a plain gradle project and everything worked fine.
Note: I did not use Spring Data (which has its own mongo libs) at all.
Haven’t got to the bottom of why this is happening under Spring though…

1 Like

I found the solution: You need to register a codec from api("org.mongodb:bson-kotlin:4.11.0").
And then:

package cz.pos.library.mongo

import com.mongodb.ConnectionString
import com.mongodb.MongoClientSettings
import com.mongodb.reactivestreams.client.MongoClients
import org.bson.UuidRepresentation
import org.bson.codecs.configuration.CodecRegistries.fromProviders
import org.bson.codecs.configuration.CodecRegistries.fromRegistries
import org.bson.codecs.configuration.CodecRegistry
import org.bson.codecs.kotlin.DataClassCodecProvider
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class MongoConfig {

    var databaseName: String = "appDatabase"
    var connectionString: String = "mongodb://admin:admin@localhost:27017/"

    fun getClientSettings() = MongoClientSettings.builder()
        .uuidRepresentation(UuidRepresentation.STANDARD)
        .applyConnectionString(ConnectionString(connectionString))
        .codecRegistry(getCodecRegistry())
        .build()

    fun getCodecRegistry(): CodecRegistry {
        return fromRegistries(
            MongoClientSettings.getDefaultCodecRegistry(),
            fromProviders(DataClassCodecProvider())
        )
    }

    @Bean
    fun mongoClient() = MongoClients.create(getClientSettings())

    @Bean
    fun mongoDatabase() = mongoClient().getDatabase(databaseName)

}

Facing similar issue
Somehow spring interferes with the codec registries

Note:- I already tried adding following in application.properties

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration

I discovered that Spring Boot had configured Gradle to pull an old version of the MongoDB Kotlin Drivers (4.8.2), I could not figure out why. This driver does not properly support Kotlin data classes, so I needed to manually add an additional dependency on a few Mongo projects.

    // MongoDB
    implementation("org.mongodb:mongodb-driver-core:5.1.3") {
        because("Spring pulls 4.8.2 by default which does not support Kotlin. Have I mentioned that Spring is terrible.")
    }
    implementation("org.mongodb:bson:5.1.3") {
        because("Spring pulls 4.8.2 by default which does not support Kotlin.")
    }
    implementation("org.mongodb:mongodb-driver-reactivestreams:5.1.3") {
        because("Spring pulls 4.8.2 by default which does not support Kotlin.")
    }

After this, the default codec properly worked with data classes, without needing to even specify.