Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

May be incorrect serialization of UUID object with JacksonCodec #338

Closed
xthebat opened this issue Apr 17, 2022 · 1 comment
Closed

May be incorrect serialization of UUID object with JacksonCodec #338

xthebat opened this issue Apr 17, 2022 · 1 comment

Comments

@xthebat
Copy link

xthebat commented Apr 17, 2022

I tried to insert object containing UUID field. This operation work ok but when I checked database the UUID representation is LUUID (v3). So the uuidRepresentation option work incorrectly for insertOne operation. Also when I tried to obtain object from database findOne operation (or may eq) use correct UUID serialization mechanism and represent UUID in v4. The result of code sample bellow is null

data class UUIDContainer(val uuid: UUID)

fun main() {
    val settings = MongoClientSettings.builder()
        .uuidRepresentation(UuidRepresentation.STANDARD)
        .build()

    val client = KMongo.createClient(settings)
    val database = client.getDatabase("db")
    val uuids = database.getCollection<UUIDContainer>()

    uuids.drop()

    val entry = UUIDContainer(UUID.fromString("151e83ca-1f8e-4d22-b042-7fb439402b29"))
    uuids.insertOne(entry)

    val result = uuids.findOne(UUIDContainer::uuid eq "151e83ca-1f8e-4d22-b042-7fb439402b29".toUUID())
    println(result)
}

I also try to add codec for database using withCodecRegistry method but this will have no effect.

data class UUIDContainer(val uuid: UUID)

fun main() {
    val settings = MongoClientSettings.builder()
        .uuidRepresentation(UuidRepresentation.STANDARD)
        .build()

    val client = KMongo.createClient(settings)
    val database = client.getDatabase("db")
    val uuids = database.getCollection<UUIDContainer>()
        .run {
            withCodecRegistry(
                CodecRegistries.fromRegistries(
                    CodecRegistries.fromProviders(UuidCodecProvider(UuidRepresentation.STANDARD)),
                    codecRegistry
                )
            )
        }

    uuids.drop()

    val entry = UUIDContainer(UUID.fromString("151e83ca-1f8e-4d22-b042-7fb439402b29"))
    uuids.insertOne(entry)

    val result = uuids.findOne(UUIDContainer::uuid eq "151e83ca-1f8e-4d22-b042-7fb439402b29".toUUID())
    println(result)
}

I tried to debug internal code and figure out that KMongo use JacksonCodec in my case and I suppose that JacksonCodec knows nothing about specified UUID representation (may be I wrong). I also tried to setup JAVA_LEGACY representation and this result in exception and as I found out there is no way to get around of this exception because of code bellow:

    private fun createRegistry(codecRegistry: CodecRegistry, uuidRepresentation: UuidRepresentation): CodecRegistry =
        if (uuidRepresentation !== UuidRepresentation.JAVA_LEGACY) {
            OverridableUuidRepresentationCodecRegistry(codecRegistry, uuidRepresentation)
        } else {
            throw CodecConfigurationException(
                "Changing the default UuidRepresentation requires a CodecRegistry that also "
                        + "implements the CodecProvider interface"
            )
        }

I have no idea what this check is for and how I can pass it.

But when I created KMongo client only to get default codecRegistry and then configured standard mongo client with this registry and JAVA_LEGACY representation (as shown in code bellow) I can successfully got object after it inserted in database.

data class UUIDContainer(val uuid: UUID)

fun main() {
    val registries = KMongo.createClient().getDatabase("db").codecRegistry

    val settings = MongoClientSettings.builder()
        .uuidRepresentation(UuidRepresentation.JAVA_LEGACY)
        .build()

    val client = MongoClients.create(settings)
    val database = client.getDatabase("db").withCodecRegistry(
        CodecRegistries.fromProviders(
            UuidCodecProvider(UuidRepresentation.JAVA_LEGACY),
            registries
        )
    )

    val uuids = database.getCollection<UUIDContainer>()


    uuids.drop()

    val entry = UUIDContainer(UUID.fromString("151e83ca-1f8e-4d22-b042-7fb439402b29"))
    uuids.insertOne(entry)

    val result = uuids.findOne(UUIDContainer::uuid eq "151e83ca-1f8e-4d22-b042-7fb439402b29".toUUID())
    println(result)
}

What did I do wrong?

@zigzago
Copy link
Member

zigzago commented Apr 17, 2022

Have you tried to use the setUUIDRepresentation function? http://litote.org/kmongo/dokka/kmongo/org.litote.kmongo.util/-k-mongo-jackson-feature/index.html

HTH

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants