[JAVA-3775] Concurrency issue causing PropertyModel.getCachedCodec to return null Created: 02/Jul/20  Updated: 28/Oct/23  Resolved: 08/Oct/20

Status: Closed
Project: Java Driver
Component/s: POJO
Affects Version/s: 3.12.5
Fix Version/s: 4.2.0

Type: Bug Priority: Major - P3
Reporter: Jeroen Sikkes Assignee: Ross Lawley
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

java 8, mongodb 4.2.8


Attachments: Zip Archive example.zip     Text File stacktrace.txt    
Issue Links:
Duplicate
duplicates JAVA-3606 NullPointerException: DecoderContext.... Closed
Related
related to JAVA-3606 NullPointerException: DecoderContext.... Closed

 Description   

I'm getting a NullPointerException in EncoderContext.encodeWithChildContext when encoding POJO's with many nested objects using multiple threads.

After a random number of serializations PropertyModel.getCachedCodec keeps returning null and the method fails when it is called by PojoCodecImpl.encodeValue

  • Simplifying the POJO structure reduces the chance on exceptions; as does lowering the amount of threads or adding delays.
  • When running on a single thread no exceptions are thrown

The issue could be related to / the same asĀ JAVA-3606; however the attached example code reproduces the issue.



 Comments   
Comment by Githook User [ 08/Oct/20 ]

Author:

{'name': 'Ross Lawley', 'email': 'ross.lawley@gmail.com', 'username': 'rozza'}

Message: Fix PojoCodec caching (#585)

Reduce the number of required CodecRegistry lookups for properties
Reduce the number of Lazy Codecs for properties

JAVA-3775 JAVA-3847
Branch: master
https://github.com/mongodb/mongo-java-driver/commit/a2ff8c063bb07b27b293c592f6153719792fea44

Comment by Ross Lawley [ 10/Jul/20 ]

PR: https://github.com/rozza/mongo-java-driver/pull/391

Comment by Jeroen Sikkes [ 07/Jul/20 ]

Hi Ross,

I have spent a short time fiddeling with the java-driver and don't have time to continue at this moment. Additional investigation will be needed.

The following question arise to me investigating the stacktrace:

What happens if another thread is accessing the classModel entry in the codecCache before the for loop addToCache is completed?

In the PojoCodecImpl the following method exists:

  private void specialize() {
        if (specialized) {
            codecCache.put(classModel, this);
            for (PropertyModel<?> propertyModel : classModel.getPropertyModels()) {
                addToCache(propertyModel);
            }
        }
    }

Re-ordering the implementation to:

  private void specialize() {
        if (specialized) {
            for (PropertyModel<?> propertyModel : classModel.getPropertyModels()) {
                addToCache(propertyModel);
            }
            codecCache.put(classModel, this);
        }
    }

prevents the NPE to occur.

Comment by Ross Lawley [ 03/Jul/20 ]

Thanks jsikkes@xs4all.nl for the ticket and the example code.

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