1

https://github.com/reticent-monolith/winds_server是 github 存储库,如果有人发现那里更容易看的话。

我正在尝试将 KMongo 和 Ktor 与 Kotlin 的序列化模块一起使用,但创建 MongoClient 会导致以下异常:

java.lang.ClassCastException: class org.litote.kmongo.serialization.SerializationCodecRegistry cannot be cast to class org.bson.codecs.configuration.CodecProvider (org.litote.kmongo.serialization.SerializationCodecRegistry and org.bson.codecs.configuration.CodecProvider are in unnamed module of loader 'app')
    at org.litote.kmongo.service.ClassMappingTypeService$DefaultImpls.codecRegistry(ClassMappingTypeService.kt:83)
    at org.litote.kmongo.serialization.SerializationClassMappingTypeService.codecRegistry(SerializationClassMappingTypeService.kt:40)
    at org.litote.kmongo.serialization.SerializationClassMappingTypeService.coreCodecRegistry(SerializationClassMappingTypeService.kt:97)
    at org.litote.kmongo.service.ClassMappingType.coreCodecRegistry(ClassMappingType.kt)
    at org.litote.kmongo.service.ClassMappingTypeService$DefaultImpls.codecRegistry$default(ClassMappingTypeService.kt:79)
    at org.litote.kmongo.KMongo.configureRegistry$kmongo_core(KMongo.kt:79)
    at org.litote.kmongo.KMongo.createClient(KMongo.kt:70)
    at org.litote.kmongo.KMongo.createClient(KMongo.kt:57)
    at org.litote.kmongo.KMongo.createClient(KMongo.kt:47)
    at org.litote.kmongo.KMongo.createClient(KMongo.kt:39)
    at com.reticentmonolith.repo.MongoDispatchRepo.<init>(MongoDispatchRepo.kt:11)
    at com.reticentmonolith.ApplicationKt.<clinit>(Application.kt:14)
    ... 23 more

我在 build.gradle 中遗漏了什么吗?

buildscript {
    repositories {
        mavenCentral()
    }
    
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
    }
}

plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.5.10'
    id 'org.jetbrains.kotlin.plugin.serialization' version '1.5.10'
    id 'application'
}

group 'com.reticentmonolith'
version '0.0.1-SNAPSHOT'
mainClassName = "io.ktor.server.netty.EngineMain"

sourceSets {
    main.kotlin.srcDirs = main.java.srcDirs = ['src']
    test.kotlin.srcDirs = test.java.srcDirs = ['test']
    main.resources.srcDirs = ['resources']
    test.resources.srcDirs = ['testresources']
}

repositories {
    mavenLocal()
    mavenCentral()
}

dependencies {
//    KOTLIN
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"

//    KTOR
    implementation "io.ktor:ktor-server-netty:$ktor_version"
    implementation "ch.qos.logback:logback-classic:$logback_version"
    implementation "io.ktor:ktor-server-core:$ktor_version"
    testImplementation "io.ktor:ktor-server-tests:$ktor_version"
    implementation "io.ktor:ktor-serialization:$ktor_version"

//    MONGO
    implementation group: 'org.mongodb', name: 'mongo-java-driver', version: '3.12.8'

//    KOTLINX SERIALIZATION
    implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.1"

//    KMONGO
    implementation 'org.litote.kmongo:kmongo-serialization:4.2.7'
    implementation group: 'org.litote.kmongo', name: 'kmongo-id-serialization', version: '4.2.7'

//    KBSON (optional dependency for KMONGO and Serialization)
    implementation "com.github.jershell:kbson:0.4.4"

}

这是我的 MongoClient 类:

import com.mongodb.client.MongoDatabase
import com.reticentmonolith.models.Dispatch
import java.time.LocalDate

import org.litote.kmongo.*

class MongoDispatchRepo: DispatchRepoInterface {

    private val client = KMongo.createClient()
    private val database: MongoDatabase = client.getDatabase("zw")
    private val windsData = database.getCollection<Dispatch>("winds")


    override fun createDispatch(dispatch: Dispatch) {
        windsData.insertOne(dispatch)
    }

    override fun getAllDispatches(): Map<String, List<Dispatch>> {
        val list = windsData.find().toList()
        return mapOf("dispatches" to list)
    }

    override fun getDispatchesByDate(date: LocalDate): Map<String, List<Dispatch>> {
        return mapOf("dispatches" to windsData.find(Dispatch::date eq date).toList())
    }

    override fun getDispatchesByDateRange(start: LocalDate, end: LocalDate): Map<String, List<Dispatch>> {
        return mapOf("dispatches" to windsData.find(Dispatch::date gte(start), Dispatch::date lte(end)).toList())
    }

    override fun getDispatchById(id: Id<Dispatch>): Dispatch? {
        return windsData.findOneById(id)
    }

    override fun updateDispatchById(id: Id<Dispatch>, update: Dispatch): Boolean {
        val oldDispatch = getDispatchById(id)
        if (oldDispatch != null) {
            update.date = oldDispatch.date
            update._id = oldDispatch._id
            windsData.updateOneById(id, update)
            return true
        }
        return false
    }

    override fun updateLastDispatch(update: Dispatch): Boolean {
        val lastDispatch = getLastDispatch() ?: return false
        update.date = lastDispatch.date
        update._id = lastDispatch._id
        windsData.updateOneById(lastDispatch._id, update)
        return true
    }

    override fun deleteDispatchById(id: Id<Dispatch>) {
        windsData.deleteOne(Dispatch::_id eq id)
    }

    override fun getLastDispatch(): Dispatch? {
        val todaysDispatches = getDispatchesByDate(LocalDate.now())
        if (todaysDispatches.isEmpty()) return null
        return todaysDispatches["dispatches"]?.last()
    }

    override fun addSpeedsToLastDispatch(line4: Int?, line3: Int?, line2: Int?, line1: Int?) {
        val lastDispatch = getLastDispatch() ?: return
        lastDispatch.riders.get(4)?.speed = line4
        lastDispatch.riders.get(3)?.speed = line3
        lastDispatch.riders.get(2)?.speed = line2
        lastDispatch.riders.get(1)?.speed = line1
        updateLastDispatch(lastDispatch)
    }

    fun purgeDatabase() {
        windsData.deleteMany(Dispatch::comment eq "")
    }
}

还有我的 Ktor 的 Application.kt:

package com.reticentmonolith

import com.reticentmonolith.models.createExampleDispatches
import io.ktor.application.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.http.*
import com.reticentmonolith.repo.MongoDispatchRepo
import io.ktor.features.*
import io.ktor.serialization.*
import kotlinx.serialization.json.Json
import org.litote.kmongo.id.serialization.IdKotlinXSerializationModule

val repo = MongoDispatchRepo()

fun main(args: Array<String>) = io.ktor.server.netty.EngineMain.main(args)

@Suppress("unused") // Referenced in application.conf
@kotlin.jvm.JvmOverloads
fun Application.module(testing: Boolean = false) {

    install(ContentNegotiation) {
        json(
            Json { serializersModule = IdKotlinXSerializationModule  },
            contentType = ContentType.Application.Json
        )
    }

    repo.purgeDatabase()
    val dispatchList = repo.getAllDispatches()["dispatches"]
    if (dispatchList != null && dispatchList.isEmpty()) {
        createExampleDispatches(0).forEach {
            repo.createDispatch(it)
            println("######## date: ${it.date} ################")
        }
    }

    routing {
        get("/dispatches/") {
            call.response.status(HttpStatusCode.OK)
            val dispatches = repo.getAllDispatches()
            println("Dispatches from Mongo: $dispatches")
            println("Dispatches encoded for response: $dispatches")
        }
    }
}


最后是被序列化的类:

package com.reticentmonolith.models

import com.reticentmonolith.serializers.DateSerializer
import com.reticentmonolith.serializers.TimeSerializer
import kotlinx.serialization.Contextual
import org.litote.kmongo.*
import kotlinx.serialization.Serializable
import java.time.LocalDate
import java.time.LocalTime

@Serializable
data class Dispatch(
    var riders: MutableMap<Int, @Contextual Rider?> = mutableMapOf(
        1 to null,
        2 to null,
        3 to null,
        4 to null
    ),
    var comment: String = "",
    var wind_degrees: Int,
    var wind_speed: Double,
    var winds_instructor: String,
    var bt_radio: String,
    var _id: @Contextual Id<Dispatch> = newId(),
//    @Serializable(with=DateSerializer::class)
    @Contextual var date: LocalDate = LocalDate.now(),
//    @Serializable(with=TimeSerializer::class)
    @Contextual var time: LocalTime = LocalTime.now()
)

fun createExampleDispatches(amount: Int): Collection<Dispatch> {
    val dispatches = mutableListOf<Dispatch>()
    for (i in 0..amount) {
        dispatches.add(Dispatch(
            bt_radio = "BT Instructor",
            winds_instructor = "Winds Instructor",
            wind_speed = 20.5,
            wind_degrees = 186
        ).apply {
            this.riders[2] = Rider(67, front_slider = Slider.BLACK, trolley = 125)
            this.riders[3] = Rider(112, front_slider = Slider.NEW_RED, rear_slider = Slider.YELLOW, trolley = 34)
        })
    }
    return dispatches
}

任何帮助将不胜感激:) 谢谢!

4

0 回答 0