Skip to content
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

Ensure bson-kotlin handles possible NPE #1395

Closed
wants to merge 1 commit into from
Closed

Conversation

rozza
Copy link
Member

@rozza rozza commented May 17, 2024

If the user provides their own CodecRegistry it could return null from CodecRegistry#get(clazz)

JAVA-5477

If the user provides their own CodecRegistry it could return `null` from
CodecRegistry#get(clazz)

JAVA-5477
@@ -236,6 +236,8 @@ internal data class DataClassCodec<T : Any>(
} else {
this.get(clazz, types)
}
codec ?: throw CodecConfigurationException("Can't find a codec for $clazz.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should not do this ad hoc check. Both of the CodecRegistry.get methods don't allow returning nulls, so when a custom CodecRegistry.get returns null, it violates its contract. There are three ways we can go about that:

  1. [the current approach in the driver, though I can't guarantee that it is used consistently] Do nothing, assuming nulls can't be returned, but also not asserting that values are non-null, because we use assertions only for driver bugs, and here a bug may be in the application code.
  2. [the approach proposed in this PR, but the PR applies it to a single place of many] Everywhere we call CodecRegistry.get, we check if the result is null, and do something with it. This approach is error-prone, and we should avoid it.
  3. [the approach I propose] Wrap all application-provided CodecRegistry objects in CheckedCodecRegistry, which checks the return value of the get methods for null, and either converts it into the CodecConfigurationException with accordance to the contract, or throws an NPE, informing an application that it violated the contract at runtime.
    3.1. If we were just now designing this API, I would have suggested the "throw NPE from CheckedCodecRegistry" approach. However, since we already have it implemented, and there is a chance we sometimes may do the ad hoc checks somewhere in the driver, I propose to use the "convert null into the CodecConfigurationException" approach.
    3.2 Following are all the places where a user may specify a custom CodecRegistry:
    • MongoClientSettings.Builder.codecRegistry
    • MongoCollection.withCodecRegistry
    • CodecRegistries.fromRegistries
      3.3 We can optimize wrapping by omitting it when the instance given to us is of the concrete type we own and know users may not extend: ChildCodecRegistry, ProvidersCodecRegistry, CheckedCodecRegistry.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The adhoc check is needed to inform the user if they are able to encode / decode the Kotlin DataClass and all its properties (fields). If it were to return null it means that there is no Codec available in the registry for the type.

Note: CodecRegistry.getCodec here is an extension function to CodecRegistry and is only for the use within the DataClassCodec. The call to this.get is a call to codecRegistry#get which uses the users configured CodecRegistry.

@rozza rozza requested a review from stIncMale May 20, 2024 08:22
@rozza rozza closed this May 21, 2024
@rozza
Copy link
Member Author

rozza commented May 21, 2024

Check was a false positive :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants