Skip to content

org.bson.codecs.configuration.CodecConfigurationException: The uuidRepresentation has not been specified, so the UUID cannot be encoded. #3546

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

Closed
airtaste opened this issue Jan 25, 2021 · 7 comments
Assignees
Labels
type: bug A general bug

Comments

@airtaste
Copy link

airtaste commented Jan 25, 2021

I'm trying to upgrade the version of spring boot from 2.3.0 to 2.4.0. After updates I've tried to run my unit tests and got codec exception 😞

Caused by: org.bson.codecs.configuration.CodecConfigurationException: The uuidRepresentation has not been specified, so the UUID cannot be encoded.

at org.bson.codecs.UuidCodec.encode(UuidCodec.java:72)
at org.bson.codecs.UuidCodec.encode(UuidCodec.java:37)
at org.bson.codecs.EncoderContext.encodeWithChildContext(EncoderContext.java:91)
at org.bson.codecs.DocumentCodec.writeValue(DocumentCodec.java:203)
at org.bson.codecs.DocumentCodec.writeMap(DocumentCodec.java:217)
at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:159)
at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:46)
at org.bson.Document.toJson(Document.java:440)
at org.bson.Document.toJson(Document.java:413)
at org.bson.Document.toJson(Document.java:400)
at org.springframework.data.mongodb.core.convert.MongoConverters$DocumentToStringConverter.convert(MongoConverters.java:241)
at org.springframework.data.mongodb.core.convert.MongoConverters$DocumentToStringConverter.convert(MongoConverters.java:234)
at org.springframework.core.convert.support.GenericConversionService$ConverterAdapter.convert(GenericConversionService.java:386)
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41)

An example of a simplified project: https://github.com/airtaste/example/tree/master

Also, I've tried to use Spring Boot property spring.data.mongodb.uuid-representation and set it to 'standard', but the error still occurred. Furthermore, I tried to customize MongoClientSettings to include UuidRepresentation.STANDARD codec registry. Ineffectually.

It's a very odd issue.

Thanks in advance!

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jan 25, 2021
@christophstrobl christophstrobl self-assigned this Jan 27, 2021
@christophstrobl
Copy link
Member

Having a look at the example the error in LessonActivityRepositoryUnitTest results from the log statement invoking org.bson.Document#toJson() using the default Encoder that does not have the UUID setting.
Have you tried providing an encoder that has the representation set? Something like new DocumentCodec().withUuidRepresentation(UuidRepresentation.JAVA_LEGACY).

@christophstrobl christophstrobl added status: waiting-for-feedback We need additional information before we can continue and removed status: waiting-for-triage An issue we've not yet triaged labels Jan 27, 2021
@airtaste
Copy link
Author

airtaste commented Jan 27, 2021

Thanks for the quick response, Christoph!
I tried to change the next line:
log.debug 'Query: {}', aggregationBlock.toJson()
to:
log.debug 'Query: {}', aggregationBlock.toJson( new DocumentCodec().withUuidRepresentation( UuidRepresentation.JAVA_LEGACY ))

But the test still blowing up :(

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Jan 27, 2021
@christophstrobl
Copy link
Member

It seems the uuidRepresentation setting is not picked up by the registry.
I had to do something like the following to make it work.

MongoClientSettings clientSettings = MongoClientSettings.builder().uuidRepresentation(UuidRepresentation.JAVA_LEGACY).build();
CodecRegistry codecRegistry = MongoClients.create(clientSettings).getDatabase("test").getCodecRegistry();

aggregationBlock.toJson(codecRegistry.get(org.bson.Document.class))

You might want to report this issue to the MongoDB Drivers Team

@christophstrobl christophstrobl added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Jan 27, 2021
@airtaste
Copy link
Author

airtaste commented Feb 2, 2021

@christophstrobl is there a way to customize DocumentCodec uuidRepresentation through spring-context/beans?
I know that MongoClientSettingsBuilderCustomizer exists. I tried to create its bean with the necessary uuidRepresentation, but in the toJson() method spring uses default DocumentCodec with UuidRepresentation.UNSPECIFIED uuid-representation type... How I could customize this? Thanks in advance!

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Feb 2, 2021
@airtaste
Copy link
Author

airtaste commented Feb 2, 2021

It seems the uuidRepresentation setting is not picked up by the registry.
I had to do something like the following to make it work.

MongoClientSettings clientSettings = MongoClientSettings.builder().uuidRepresentation(UuidRepresentation.JAVA_LEGACY).build();
CodecRegistry codecRegistry = MongoClients.create(clientSettings).getDatabase("test").getCodecRegistry();

aggregationBlock.toJson(codecRegistry.get(org.bson.Document.class))

You might want to report this issue to the MongoDB Drivers Team

I found that when the encoder try to write the value for a document that has UUID property the next code has executed:

Codec codec = registry.get(value.getClass());
encoderContext.encodeWithChildContext(codec, writer, value);

In case when we write UUID value registry.get() method returned UuidCodec with default Unspecified UUID representation...
And then, when we try to encode value in the UuidCodec we have the next logic in the encode() method:

if (uuidRepresentation == UuidRepresentation.UNSPECIFIED) {
throw new CodecConfigurationException("The uuidRepresentation has not been specified, so the UUID cannot be encoded.");
}

Therefore we always will have such error :(
Odd case... I am really confused.

@airtaste
Copy link
Author

airtaste commented Feb 3, 2021

Eventually, I found the cause… So the problem is that in Spring Data 3.x when I use group like:

Aggregation.group( FieldOne, FieldTwo, FieldThree )

I will have as result the next aggregation:

Document { _id: Document { [FieldOne: X, FieldTwo: Y, FieldThree: Z] }, FieldOne: X, FieldTwo: Y, FieldThree: Z }

I have CodecConfigurationExcpetion because _id: [FieldOne: X, FieldTwo: Y, FieldThree: Z] can not be cast to UUID…

Composite ids from Aggregation.Group() are no longer mapped to their respective fields. Could you please provide some info on how to deal with such a case, and is there any way to reverse/configure this?

@christophstrobl
Copy link
Member

I'm afraid I do not quite understand the last comment on composite ids.
The CodecConfigurationExcpetion originates from the driver library when writing the debug output. You can try SerializationUtils.serializeToJsonSafely, which will suppress errors, but generate a slightly different output, for logging, or contact the MongoDB Drivers Team.
If there's problem with the conversion of the aggregation pipeline itself, please consider opening a new dedicated issue.

@christophstrobl christophstrobl added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Feb 4, 2021
@airtaste airtaste closed this as completed Feb 8, 2021
mp911de pushed a commit that referenced this issue Feb 17, 2021
This commit makes sure to use an Encoder having UuidRepresentation set when calling org.bson.Document#toJson, preventing CodecConfigurationException from being raised.

Future versions will make sure the UUID string representation matches the Java default one.

Closes #3546.
Original pull request: #3551.
mp911de pushed a commit that referenced this issue Feb 17, 2021
…to a json String.

This commit switches the rendering of UUID values to their toString format when printing org.bson.Document to json via the DocumentToString converter.

This will move the resulting representation from {"$binary": "QUK3ZihZ9cdhWjTf5TZqrw==", "$type": "03"} to 480971b0-7160-4120-acd0-6fd6b82418ad which is the more natural variant within Java applications.

The conversion only applies on read in cases where an entire document eg. a composite id, is mapped to a String property of the domain model.

Closes #3546.
Original pull request: #3551.
mp911de pushed a commit that referenced this issue Feb 17, 2021
Reduce method visibility in tests, enable missed test and format code.

Closes #3546.
Original pull request: #3551.
mp911de pushed a commit that referenced this issue Feb 17, 2021
This commit makes sure to use an Encoder having UuidRepresentation set when calling org.bson.Document#toJson, preventing CodecConfigurationException from being raised.

Future versions will make sure the UUID string representation matches the Java default one.

Closes #3546.
Original pull request: #3551.
@mp911de mp911de added type: bug A general bug and removed status: waiting-for-feedback We need additional information before we can continue labels Feb 17, 2021
@mp911de mp911de added this to the 3.1.4 (2020.0.4) milestone Feb 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

4 participants