kmongo
kmongo copied to clipboard
kotlinx.serialization: Remove the need of @Contextual annotation on Id<T> property
I'm sorry if this is a dupe, couldn't find anything about that in all the web (including docs and this repository). I guess this issue is with kMongo judging by the message of the exception.
I'm having this issue on collection.insertOne
calls. My dependencies looks like this:
dependencies {
implementation(kotlin("stdlib"))
implementation("io.ktor:ktor-server-netty:1.4.1")
implementation("io.ktor:ktor-serialization:1.4.1")
implementation("com.google.firebase:firebase-admin:7.0.0")
implementation("com.github.NathanPB:BootingBits:1.0-SNAPSHOT")
implementation("org.litote.kmongo:kmongo-coroutine-serialization:4.1.2")
implementation("org.slf4j:slf4j-simple:1.7.30")
}
and the class of the entity I'm trying to insert looks like this:
@Serializable
data class Tag (
@SerialName("_id") @MongoId val id: Id<Tag>? = newId(),
val displayName: String,
val description: String? = null,
val createdAt: Long = System.currentTimeMillis()
) {
fun validate(): Boolean {
return displayName.isNotEmpty()
}
}
this is happening in any call like that:
runBlocking {
collection.insertOne(Tag(displayName = "foobar"))
}
and generates the following (pretty long) stacktrace:
(dev.nathanpb.wmd
classes are from my application)
Exception in thread "main" kotlinx.serialization.SerializationException: Class 'WrappedObjectId' is not registered for polymorphic serialization in the scope of 'Id'.
Mark the base class as 'sealed' or register the serializer explicitly.
at kotlinx.serialization.internal.AbstractPolymorphicSerializerKt.throwSubtypeNotRegistered(AbstractPolymorphicSerializer.kt:103)
at kotlinx.serialization.internal.AbstractPolymorphicSerializerKt.throwSubtypeNotRegistered(AbstractPolymorphicSerializer.kt:113)
at kotlinx.serialization.PolymorphicSerializerKt.findPolymorphicSerializer(PolymorphicSerializer.kt:96)
at kotlinx.serialization.internal.AbstractPolymorphicSerializer.serialize(AbstractPolymorphicSerializer.kt:32)
at kotlinx.serialization.encoding.Encoder$DefaultImpls.encodeSerializableValue(Encoding.kt:281)
at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableValue(AbstractEncoder.kt:18)
at kotlinx.serialization.encoding.Encoder$DefaultImpls.encodeNullableSerializableValue(Encoding.kt:301)
at kotlinx.serialization.encoding.AbstractEncoder.encodeNullableSerializableValue(AbstractEncoder.kt:18)
at com.github.jershell.kbson.BsonEncoder.encodeNullableSerializableValue(BsonEncoder.kt:82)
at kotlinx.serialization.encoding.AbstractEncoder.encodeNullableSerializableElement(AbstractEncoder.kt:92)
at dev.nathanpb.wmd.data.Tag.write$Self(Tag.kt:31)
at dev.nathanpb.wmd.data.Tag$$serializer.serialize(Tag.kt)
at dev.nathanpb.wmd.data.Tag$$serializer.serialize(Tag.kt:30)
at kotlinx.serialization.encoding.Encoder$DefaultImpls.encodeSerializableValue(Encoding.kt:281)
at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableValue(AbstractEncoder.kt:18)
at org.litote.kmongo.serialization.SerializationCodec.encode(SerializationCodec.kt:63)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29)
at com.mongodb.internal.connection.SplittablePayload$WriteRequestEncoder.encode(SplittablePayload.java:200)
at com.mongodb.internal.connection.SplittablePayload$WriteRequestEncoder.encode(SplittablePayload.java:187)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29)
at com.mongodb.internal.connection.BsonWriterHelper.writeDocument(BsonWriterHelper.java:77)
at com.mongodb.internal.connection.BsonWriterHelper.writePayload(BsonWriterHelper.java:59)
at com.mongodb.internal.connection.CommandMessage.encodeMessageBodyWithMetadata(CommandMessage.java:162)
at com.mongodb.internal.connection.RequestMessage.encode(RequestMessage.java:138)
at com.mongodb.internal.connection.CommandMessage.encode(CommandMessage.java:59)
at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceiveAsync(InternalStreamConnection.java:393)
at com.mongodb.internal.connection.UsageTrackingInternalConnection.sendAndReceiveAsync(UsageTrackingInternalConnection.java:145)
at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection.sendAndReceiveAsync(DefaultConnectionPool.java:527)
at com.mongodb.internal.connection.CommandProtocolImpl.executeAsync(CommandProtocolImpl.java:77)
at com.mongodb.internal.connection.DefaultServer$DefaultServerProtocolExecutor.executeAsync(DefaultServer.java:273)
at com.mongodb.internal.connection.DefaultServerConnection.executeProtocolAsync(DefaultServerConnection.java:218)
at com.mongodb.internal.connection.DefaultServerConnection.commandAsync(DefaultServerConnection.java:135)
at com.mongodb.internal.operation.MixedBulkWriteOperation.executeCommandAsync(MixedBulkWriteOperation.java:440)
at com.mongodb.internal.operation.MixedBulkWriteOperation.executeBatchesAsync(MixedBulkWriteOperation.java:348)
at com.mongodb.internal.operation.MixedBulkWriteOperation.access$1000(MixedBulkWriteOperation.java:76)
at com.mongodb.internal.operation.MixedBulkWriteOperation$2$1.call(MixedBulkWriteOperation.java:228)
at com.mongodb.internal.operation.OperationHelper.validateWriteRequests(OperationHelper.java:269)
at com.mongodb.internal.operation.MixedBulkWriteOperation$2.call(MixedBulkWriteOperation.java:211)
at com.mongodb.internal.operation.OperationHelper$9.onResult(OperationHelper.java:733)
at com.mongodb.internal.operation.OperationHelper$9.onResult(OperationHelper.java:730)
at com.mongodb.internal.connection.DefaultServer$1.onResult(DefaultServer.java:116)
at com.mongodb.internal.connection.DefaultServer$1.onResult(DefaultServer.java:105)
at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:48)
at com.mongodb.internal.connection.DefaultConnectionPool$2.onResult(DefaultConnectionPool.java:229)
at com.mongodb.internal.connection.DefaultConnectionPool$2.onResult(DefaultConnectionPool.java:210)
at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection$1.onResult(DefaultConnectionPool.java:447)
at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection$1.onResult(DefaultConnectionPool.java:438)
at com.mongodb.internal.connection.UsageTrackingInternalConnection$1.onResult(UsageTrackingInternalConnection.java:66)
at com.mongodb.internal.connection.UsageTrackingInternalConnection$1.onResult(UsageTrackingInternalConnection.java:58)
at com.mongodb.internal.connection.InternalStreamConnection$1$1.onResult(InternalStreamConnection.java:189)
at com.mongodb.internal.connection.InternalStreamConnection$1$1.onResult(InternalStreamConnection.java:175)
at com.mongodb.internal.connection.InternalStreamConnectionInitializer.completeConnectionDescriptionInitializationAsync(InternalStreamConnectionInitializer.java:215)
at com.mongodb.internal.connection.InternalStreamConnectionInitializer.access$100(InternalStreamConnectionInitializer.java:44)
at com.mongodb.internal.connection.InternalStreamConnectionInitializer$1.onResult(InternalStreamConnectionInitializer.java:83)
at com.mongodb.internal.connection.InternalStreamConnectionInitializer$1.onResult(InternalStreamConnectionInitializer.java:76)
at com.mongodb.internal.connection.InternalStreamConnectionInitializer$2.onResult(InternalStreamConnectionInitializer.java:195)
at com.mongodb.internal.connection.InternalStreamConnectionInitializer$2.onResult(InternalStreamConnectionInitializer.java:176)
at com.mongodb.internal.connection.CommandHelper$1.onResult(CommandHelper.java:59)
at com.mongodb.internal.connection.CommandHelper$1.onResult(CommandHelper.java:53)
at com.mongodb.internal.connection.InternalStreamConnection$2$1.onResult(InternalStreamConnection.java:463)
at com.mongodb.internal.connection.InternalStreamConnection$2$1.onResult(InternalStreamConnection.java:440)
at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback$MessageCallback.onResult(InternalStreamConnection.java:745)
at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback$MessageCallback.onResult(InternalStreamConnection.java:712)
at com.mongodb.internal.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:582)
at com.mongodb.internal.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:579)
at com.mongodb.internal.connection.AsynchronousChannelStream$BasicCompletionHandler.completed(AsynchronousChannelStream.java:250)
at com.mongodb.internal.connection.AsynchronousChannelStream$BasicCompletionHandler.completed(AsynchronousChannelStream.java:233)
at java.base/sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:127)
at java.base/sun.nio.ch.Invoker.invokeDirect(Invoker.java:158)
at java.base/sun.nio.ch.UnixAsynchronousSocketChannelImpl.implRead(UnixAsynchronousSocketChannelImpl.java:568)
at java.base/sun.nio.ch.AsynchronousSocketChannelImpl.read(AsynchronousSocketChannelImpl.java:276)
at java.base/sun.nio.ch.AsynchronousSocketChannelImpl.read(AsynchronousSocketChannelImpl.java:297)
at com.mongodb.internal.connection.AsynchronousSocketChannelStream$AsynchronousSocketChannelAdapter.read(AsynchronousSocketChannelStream.java:144)
at com.mongodb.internal.connection.AsynchronousChannelStream.readAsync(AsynchronousChannelStream.java:118)
at com.mongodb.internal.connection.AsynchronousChannelStream.readAsync(AsynchronousChannelStream.java:107)
at com.mongodb.internal.connection.InternalStreamConnection.readAsync(InternalStreamConnection.java:579)
at com.mongodb.internal.connection.InternalStreamConnection.access$1100(InternalStreamConnection.java:78)
at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback.onResult(InternalStreamConnection.java:702)
at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback.onResult(InternalStreamConnection.java:687)
at com.mongodb.internal.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:582)
at com.mongodb.internal.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:579)
at com.mongodb.internal.connection.AsynchronousChannelStream$BasicCompletionHandler.completed(AsynchronousChannelStream.java:250)
at com.mongodb.internal.connection.AsynchronousChannelStream$BasicCompletionHandler.completed(AsynchronousChannelStream.java:233)
at java.base/sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:127)
at java.base/sun.nio.ch.Invoker.invokeDirect(Invoker.java:158)
at java.base/sun.nio.ch.UnixAsynchronousSocketChannelImpl.implRead(UnixAsynchronousSocketChannelImpl.java:568)
at java.base/sun.nio.ch.AsynchronousSocketChannelImpl.read(AsynchronousSocketChannelImpl.java:276)
at java.base/sun.nio.ch.AsynchronousSocketChannelImpl.read(AsynchronousSocketChannelImpl.java:297)
at com.mongodb.internal.connection.AsynchronousSocketChannelStream$AsynchronousSocketChannelAdapter.read(AsynchronousSocketChannelStream.java:144)
at com.mongodb.internal.connection.AsynchronousChannelStream.readAsync(AsynchronousChannelStream.java:118)
at com.mongodb.internal.connection.AsynchronousChannelStream.readAsync(AsynchronousChannelStream.java:107)
at com.mongodb.internal.connection.InternalStreamConnection.readAsync(InternalStreamConnection.java:579)
at com.mongodb.internal.connection.InternalStreamConnection.access$1100(InternalStreamConnection.java:78)
at com.mongodb.internal.connection.InternalStreamConnection$2.onResult(InternalStreamConnection.java:440)
at com.mongodb.internal.connection.InternalStreamConnection$2.onResult(InternalStreamConnection.java:429)
at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:48)
at com.mongodb.internal.connection.InternalStreamConnection$3.completed(InternalStreamConnection.java:536)
at com.mongodb.internal.connection.InternalStreamConnection$3.completed(InternalStreamConnection.java:533)
at com.mongodb.internal.connection.AsynchronousChannelStream$1.completed(AsynchronousChannelStream.java:94)
at com.mongodb.internal.connection.AsynchronousChannelStream$1.completed(AsynchronousChannelStream.java:88)
at com.mongodb.internal.connection.AsynchronousChannelStream$2.completed(AsynchronousChannelStream.java:197)
at com.mongodb.internal.connection.AsynchronousChannelStream$2.completed(AsynchronousChannelStream.java:191)
at com.mongodb.internal.connection.AsynchronousChannelStream$AsyncWritableByteChannelAdapter$WriteCompletionHandler.completed(AsynchronousChannelStream.java:222)
at com.mongodb.internal.connection.AsynchronousChannelStream$AsyncWritableByteChannelAdapter$WriteCompletionHandler.completed(AsynchronousChannelStream.java:213)
at java.base/sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:127)
at java.base/sun.nio.ch.Invoker.invokeDirect(Invoker.java:158)
at java.base/sun.nio.ch.UnixAsynchronousSocketChannelImpl.implWrite(UnixAsynchronousSocketChannelImpl.java:752)
at java.base/sun.nio.ch.AsynchronousSocketChannelImpl.write(AsynchronousSocketChannelImpl.java:382)
at java.base/sun.nio.ch.AsynchronousSocketChannelImpl.write(AsynchronousSocketChannelImpl.java:399)
at java.base/java.nio.channels.AsynchronousSocketChannel.write(AsynchronousSocketChannel.java:582)
at com.mongodb.internal.connection.AsynchronousSocketChannelStream$AsynchronousSocketChannelAdapter.write(AsynchronousSocketChannelStream.java:177)
at com.mongodb.internal.connection.AsynchronousChannelStream$AsyncWritableByteChannelAdapter.write(AsynchronousChannelStream.java:210)
at com.mongodb.internal.connection.AsynchronousChannelStream.pipeOneBuffer(AsynchronousChannelStream.java:191)
at com.mongodb.internal.connection.AsynchronousChannelStream.writeAsync(AsynchronousChannelStream.java:88)
at com.mongodb.internal.connection.InternalStreamConnection.writeAsync(InternalStreamConnection.java:533)
at com.mongodb.internal.connection.InternalStreamConnection.sendMessageAsync(InternalStreamConnection.java:529)
at com.mongodb.internal.connection.InternalStreamConnection.sendCommandMessageAsync(InternalStreamConnection.java:429)
at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceiveAsync(InternalStreamConnection.java:398)
at com.mongodb.internal.connection.CommandHelper.executeCommandAsync(CommandHelper.java:52)
at com.mongodb.internal.connection.InternalStreamConnectionInitializer.initializeConnectionDescriptionAsync(InternalStreamConnectionInitializer.java:175)
at com.mongodb.internal.connection.InternalStreamConnectionInitializer.initializeAsync(InternalStreamConnectionInitializer.java:70)
at com.mongodb.internal.connection.InternalStreamConnection$1.completed(InternalStreamConnection.java:174)
at com.mongodb.internal.connection.InternalStreamConnection$1.completed(InternalStreamConnection.java:171)
at com.mongodb.internal.connection.AsynchronousSocketChannelStream$OpenCompletionHandler.completed(AsynchronousSocketChannelStream.java:115)
at com.mongodb.internal.connection.AsynchronousSocketChannelStream$OpenCompletionHandler.completed(AsynchronousSocketChannelStream.java:100)
at java.base/sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:127)
at java.base/sun.nio.ch.UnixAsynchronousSocketChannelImpl.finishConnect(UnixAsynchronousSocketChannelImpl.java:285)
at java.base/sun.nio.ch.UnixAsynchronousSocketChannelImpl.finish(UnixAsynchronousSocketChannelImpl.java:200)
at java.base/sun.nio.ch.UnixAsynchronousSocketChannelImpl.onEvent(UnixAsynchronousSocketChannelImpl.java:215)
at java.base/sun.nio.ch.EPollPort$EventHandlerTask.run(EPollPort.java:306)
at java.base/sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at java.base/java.lang.Thread.run(Thread.java:832)
@NathanPB do you follow this setup https://litote.org/kmongo/quick-start/#asynchronously-with-coroutines ?
Looks like you don't have the KMongo module registered - be sure to use a
mongo client coming from KMongo.createClient().coroutine
@zigzago yes, i followed these steps, I am using KMongo.createClient("String"). coroutine
Well in the end this is "normal". You just have to add a @Contextual
annotation on the id property. I know this is not ideal but it is a current documented limitation of the implementation. I'm going to change the title of the issue then ;). See https://github.com/Litote/kmongo/commit/eea20053801fd737fa75876a5e070114bb60e78a for the unit test
Summary: now that the polymorphism strategy of koltinx.serialization seems to be stabilized, we need to register a dedicated polymorphism module forId<T>
in order to avoid the need of @Contextual
annotation
Ok, I'll do that. Thanks for fast response
@zigzago sorry to come to this again, I tried the solution you suggested, it worked for kMongo functions (insertOne, find, etc), but it fails completely when used with kTor (ex. context.respond(collection.find().toList())
). Exactly the same exception
I looked at #218 that could be heavily related but it seems that it was fixed long ago, and I'm using the latest version available
Look at the doc - it should work: https://litote.org/kmongo/object-mapping/#id-json-kotlinx-serialization
@NathanPB I have the KMongo, Ktor, Kotlinx.serialization and Kotlinx.Coroutines stack as well.
Do you have the
implementation("org.litote.kmongo:kmongo-id-serialization:4.1.3")
dependency?
and do you have the module registered:
install(ContentNegotiation) {
json(
Json { serializersModule = IdKotlinXSerializationModule },
contentType = ContentType.Application.Json
)
}