[JAVA-3925] DocumentCodec ignores registry when writing Iterable or Map instances Created: 10/Jan/21  Updated: 28/Oct/23  Resolved: 01/Nov/21

Status: Closed
Project: Java Driver
Component/s: Codecs
Affects Version/s: None
Fix Version/s: 4.4.0

Type: Improvement Priority: Major - P3
Reporter: Conchi Bueno Assignee: Jeffrey Yemin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: Text File codec_example.txt    
Issue Links:
Documented
Tested
Case:
Backwards Compatibility: Minor Change
Documentation Changes: Needed

 Description   

Using POJO serialization, updates seem to be problematic. Considering this POJO:

 
	@BsonId
	public String key;
	@BsonProperty("value")
	public ObjectNode value;  

Note, the "value" is Jackson.

To support this, it was registered a custom Codec for ObjectNode. Updates will not invoke the codec. For example:

 
	Document setters = new Document("value", Mappers.getJacksonMapper().createObjectNode());
	Document d = new Document("$set", setters);
	// does not invoke codec, you get []
	pojoCollection.updateOne(new Document("_id", "key1"), d);

The ObjectNode is replaced with [] in the resulting BSON, which makes subsequent POJO reads fail.

After some investigation, it was identified the root cause is [this line](https://github.com/mongodb/mongo-java-driver/blob/r3.12.5/bson/src/main/org/bson/codecs/DocumentCodec.java#L192) in the DocumentCodec. [This line](https://github.com/mongodb/mongo-java-driver/blob/r3.12.5/bson/src/main/org/bson/codecs/DocumentCodec.java#L192) special-cases encoding instances of Iterable with its own encoder. Normally this is not an issue. However in this case it is an issue because ObjectNode extends JsonNode which implements Iterable<JsonNode>. This prevents the process from falling through to [this line](https://github.com/mongodb/mongo-java-driver/blob/r3.12.5/bson/src/main/org/bson/codecs/DocumentCodec.java#L197).

As a workaround, the ObjectNode can be wrapped in some other class that does not implement Iterable, and provide a codec for that class as well.



 Comments   
Comment by Githook User [ 01/Nov/21 ]

Author:

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

Message: Use CodecRegistry in DocumentCodec for Iterable and Map instances (#811)

  • Instead of using private methods within DocumentCodec to encode instances
    of Iterable and Map, look up the Codec in the registry as with
    any other instance.
  • Instead of using a private method within DocumentCodec to decode BSON arrays,
    lookup up the Codec in the registry according to the type mapped to array in the
    BsonTypeClassMap.

JAVA-3925
Branch: master
https://github.com/mongodb/mongo-java-driver/commit/53b0ff156a33d883ec6c78a64d2c9c3d14e9218c

Comment by John Lilley [ 11/Jan/21 ]

This is the workaround we implemented for the issue.  Unfortunately, it cannot be added to existing code, you must retrofit POJOs with the wrapper type. 

 

See attached codec_example.txt

 

Generated at Thu Feb 08 09:00:47 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.