Issue with UUID after upgrading to 4.2.1 for java client

I am trying to upgrade us from 3.12.8 to 4.2.1.
I know that the uuidRepresentation now needs to be set to java legacy if that was used before and it works fine with my main client(s). But unfortunately we have lots of code in tests and elsewhere, that is failing now, due to equality not working anymore and default printing to json not working anymore. A short example case:

    "simple test case" in {
      val uuid = UUID.randomUUID()

      val dbo1 = new BasicDBObject()
      dbo1.put("subfield", uuid)

      val dbo2 = new BasicDBObject()
      dbo2.put("subfield", uuid)

      dbo1.toJson
      dbo1.equals(dbo2)
    }

fails with The uuidRepresentation has not been specified, so the UUID cannot be encoded.

What is the way to go to make all these tests work again? Can I not pass in the uuid natively anymore?

It looks to me like equality on BasicDBObject is broken as soon as we put a UUID as a value? There is no way to override the UuidRepresentation. Still it should somehow work, as it is a valid BasicDBObject that I can send to mongo db with a client specified to use a UuidRepresentation.

Is the only solution to now everywhere I put uuids into BasicDBObject to use

val uuid = new BsonBinary(UUID.randomUUID(), UuidRepresentation.JAVA_LEGACY)
val dbo1 = new BasicDBObject()
dbo1.put("subfield", uuid)

?

Can that lead to any compatibility problems if I do that with BasicDBObjects that are written to MongoDB with a client which has java legacy as uuidRepresentation specified? (in 3.x.x version we had no uuidRepresentation specified and did just pass the uuid in)

Hi @Yannick_Gladow,

I agree that’s a problem, and I don’t have a solution for you that doesn’t involve a change in your code. But here is an example of what you can do:

    // store a reference to this registry somewhere that's easy to access
    var registry =
            CodecRegistries.fromRegistries(
                    // Put a UuidCodec with representation specified in the first provider, which 
                    // will override the default one with no representation specified
                    CodecRegistries.fromCodecs(new UuidCodec(UuidRepresentation.JAVA_LEGACY)),
                    MongoClientSettings.getDefaultCodecRegistry());

    var document = new BasicDBObject("_id", UUID.randomUUID());

    // Get an Encoder<BasicDBObject> from the registry and pass it to the #toJson method
    String json = document.toJson(registry.get(BasicDBObject.class));

    System.out.println(json);

This prints:

{"_id": {"$binary": {"base64": "oUyLWtHF29MJqv5y89Emvg==", "subType": "03"}}}

Let me know if that works for you and if not I can open up an issue in Jira to consider other options.

Regards,
Jeff Yemin

Yes that is a workaround, but actually the worse thing for me is, that .equals does not work anymore. I can not work with these BasicDBObjects anymore. E.g. when using a Set data structure, which internally relies on object equality it throws the UUID exception. This seems to me a big problem, what do you think?

Yeah, I see what you’re saying, and sorry for my misunderstanding of the main source of pain. I opened https://jira.mongodb.org/browse/JAVA-4051 to see what we can do to address the issue.

Regards,
Jeff

2 Likes

The bug in BasicDBObject equals/hashCode has been fixed and can be tested using the 4.2.3-SNAPSHOT release. If you have a chance please give it a go. The 4.2.3 release is planned for April 6.

Regards,
Jeff

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.