[JAVA-2931] Unable to encode a BsonDocument with a nested RawBsonArray Created: 16/Aug/18  Updated: 28/Oct/23  Resolved: 17/Aug/18

Status: Closed
Project: Java Driver
Component/s: BSON
Affects Version/s: 3.7.0
Fix Version/s: 3.8.1

Type: Bug Priority: Major - P3
Reporter: Matthew Monteleone Assignee: Jeffrey Yemin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Problem/Incident
is caused by JAVA-1442 Make RawBsonDocument#get return RawBs... Closed
Related
is related to JAVA-2932 Add RawBsonArrayCodec Backlog
Case:

 Description   

When trying to upgrade to Mongo Java driver we are having some failures in our existing code.

Please find isolated test cases which should reproduce them and the exceptions they cause in 3.8.0 driver version. In 3.6.4 the same code produces no exceptions and works as expected - updates docs/ creates docs/ etc.

I haven't found any information on these breaking changes and/or ways to fix them. Can you please check with your team and let us know what the issue and fix or workaround is? And if the below are no longer valid usage let us know why and a link to the documentation related to them.

To me it looks like the changes are related to the .get() returning RawBsonArray since 3.7

Example 1

Code

        BsonArray bsonArray = new BsonArray();
        bsonArray.add(new BsonInt32(1));
        bsonArray.add(new BsonInt32(2));
        bsonArray.add(new BsonInt32(3));
        bsonArray.add(new BsonInt32(4));
 
        BsonDocument bsonDocument = new BsonDocument().append("_id", new BsonObjectId())
                .append("status", new BsonInt32(1))
                .append("references", bsonArray);
 
 
        RawBsonDocument rawBsonDocument = new RawBsonDocument(bsonDocument, new BsonDocumentCodec());
 
        BsonValue references = rawBsonDocument.get("references");
 
        BsonDocument newDocument = new BsonDocument().append("status", new BsonInt32(0))
                .append("references", references);
 
        RawBsonDocument updatedDoc = new RawBsonDocument(newDocument, new BsonDocumentCodec());
 
{
    return foo;
}

Exception:

org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class org.bson.RawBsonArray.
	at org.bson.codecs.configuration.CodecCache.getOrThrow(CodecCache.java:46)
	at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:63)
	at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:37)
	at org.bson.codecs.BsonDocumentCodec.writeValue(BsonDocumentCodec.java:135)
	at org.bson.codecs.BsonDocumentCodec.encode(BsonDocumentCodec.java:115)
	at org.bson.codecs.BsonDocumentCodec.encode(BsonDocumentCodec.java:41)
	at org.bson.RawBsonDocument.<init>(RawBsonDocument.java:117)

Example 2

Code

        BsonArray bsonArray = new BsonArray();
        bsonArray.add(new BsonInt32(1));
        bsonArray.add(new BsonInt32(2));
        bsonArray.add(new BsonInt32(3));
        bsonArray.add(new BsonInt32(4));
 
        BsonDocument bsonDocument = new BsonDocument().append("_id", new BsonObjectId())
                .append("status", new BsonInt32(1))
                .append("references", bsonArray);
 
 
        RawBsonDocument rawBsonDocument = new RawBsonDocument(bsonDocument, new BsonDocumentCodec());
 
        BsonDocument updateDocument = new BsonDocument();
        updateDocument.put("$set", new BsonDocument("references", rawBsonDocument.get("references")));
 
        dbCollection.findOneAndUpdate(Filters.eq("status", 1),
                updateDocument,
                new FindOneAndUpdateOptions().upsert(true));

Exception

org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class org.bson.RawBsonArray.
	at org.bson.codecs.configuration.CodecCache.getOrThrow(CodecCache.java:46)
	at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:63)
	at org.bson.codecs.configuration.ChildCodecRegistry.get(ChildCodecRegistry.java:51)
	at org.bson.codecs.BsonDocumentCodec.writeValue(BsonDocumentCodec.java:135)
	at org.bson.codecs.BsonDocumentCodec.encode(BsonDocumentCodec.java:115)
	at org.bson.codecs.BsonDocumentCodec.encode(BsonDocumentCodec.java:41)
	at org.bson.codecs.configuration.LazyCodec.encode(LazyCodec.java:37)
	at org.bson.codecs.EncoderContext.encodeWithChildContext(EncoderContext.java:91)
	at org.bson.codecs.BsonDocumentCodec.writeValue(BsonDocumentCodec.java:136)
	at org.bson.codecs.BsonDocumentCodec.encode(BsonDocumentCodec.java:115)
	at org.bson.codecs.BsonDocumentCodec.encode(BsonDocumentCodec.java:41)
	at org.bson.codecs.configuration.LazyCodec.encode(LazyCodec.java:37)
	at org.bson.codecs.EncoderContext.encodeWithChildContext(EncoderContext.java:91)
	at org.bson.codecs.BsonDocumentCodec.writeValue(BsonDocumentCodec.java:136)
	at org.bson.codecs.BsonDocumentCodec.encode(BsonDocumentCodec.java:115)
	at org.bson.codecs.BsonDocumentCodec.encode(BsonDocumentCodec.java:41)
	at com.mongodb.internal.connection.RequestMessage.addDocument(RequestMessage.java:238)
	at com.mongodb.internal.connection.RequestMessage.addDocument(RequestMessage.java:188)
	at com.mongodb.internal.connection.CommandMessage.encodeMessageBodyWithMetadata(CommandMessage.java:136)
	at com.mongodb.internal.connection.RequestMessage.encode(RequestMessage.java:138)
	at com.mongodb.internal.connection.CommandMessage.encode(CommandMessage.java:57)
	at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:244)
	at com.mongodb.internal.connection.UsageTrackingInternalConnection.sendAndReceive(UsageTrackingInternalConnection.java:99)
	at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection.sendAndReceive(DefaultConnectionPool.java:444)
	at com.mongodb.internal.connection.CommandProtocolImpl.execute(CommandProtocolImpl.java:72)
	at com.mongodb.internal.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:200)
	at com.mongodb.internal.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:269)
	at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:131)
	at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:123)
	at com.mongodb.operation.CommandOperationHelper$4.call(CommandOperationHelper.java:452)
	at com.mongodb.operation.OperationHelper.withReleasableConnection(OperationHelper.java:419)
	at com.mongodb.operation.CommandOperationHelper.executeRetryableCommand(CommandOperationHelper.java:445)
	at com.mongodb.operation.BaseFindAndModifyOperation.execute(BaseFindAndModifyOperation.java:69)
	at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.execute(MongoClientDelegate.java:193)
	at com.mongodb.client.internal.MongoCollectionImpl.executeFindOneAndUpdate(MongoCollectionImpl.java:743)
	at com.mongodb.client.internal.MongoCollectionImpl.findOneAndUpdate(MongoCollectionImpl.java:723)



 Comments   
Comment by Githook User [ 17/Aug/18 ]

Author:

{'name': 'Jeff Yemin', 'email': 'jeff.yemin@10gen.com', 'username': 'jyemin'}

Message: JAVA-2931: Support nesting RawBsonArray in BsonDocument

In BsonValueCodecProvider, use the BsonArrayCodec to encode RawBsonArray
as well as BsonArray. This allows the default BsonDocumentCodec to encode
a BsonDocument that nests a RawBsonArray.
Branch: 3.8.x
https://github.com/mongodb/mongo-java-driver/commit/9780947b9a28fc5eb883332454823c2f77ba0604

Comment by Githook User [ 17/Aug/18 ]

Author:

{'name': 'Jeff Yemin', 'email': 'jeff.yemin@10gen.com', 'username': 'jyemin'}

Message: JAVA-2931: Support nesting RawBsonArray in BsonDocument

In BsonValueCodecProvider, use the BsonArrayCodec to encode RawBsonArray
as well as BsonArray. This allows the default BsonDocumentCodec to encode
a BsonDocument that nests a RawBsonArray.
Branch: master
https://github.com/mongodb/mongo-java-driver/commit/23708eac52490a114abc747fa2948800c275d943

Comment by Jeffrey Yemin [ 16/Aug/18 ]

Both examples don't work because by default the BsonDocumentCodec doesn't know how to encode a nested RawBsonArray. I initially thought the second example would pick up a Codec from the MongoClient's CodecRegistry, but it doesn't because that registry is ignored when the actual type of a Bson instance or the generic type T is BsonDocument. See this code in the Operations class. In both cases, when the actual type is BsonDocument, the registry is ignored.

I think we can fix this by making BsonValueCodecProvider able to encode RawBsonArray as well as BsonArray

Generated at Thu Feb 08 08:58:24 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.