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

Deprecate Parameterizable, introduce default CodecProvider.get(Class<T>, List<Type>, CodecRegistry) instead #1115

Merged
merged 6 commits into from
Jun 2, 2023

Conversation

stIncMale
Copy link
Member

@stIncMale stIncMale commented May 12, 2023

Turns out, we don't even need to introduce ParameterizedCodecProvider to replace Parameterizable. All we need is a new default method on CodecProvider. And the cost of still supporting Parameterizable is really small: a single if block in ProvidersCodecRegistry.getFromCodecProvider.

I also refactored RecordCodec, CollectionCodec, MapCodecV2, org.bson.codecs.kotlin.DataClassCodec such that they no longer implement Parameterizable.

How is this related to JAVA-4954?

JAVA-4954 is about trying to improve PojoCodecImpl to be more like RecordCodec. Given that we discovered a better alternative to Parameterizable, which can be implemented without breaking public API, it seems worth making the improvement before trying to refactor PojoCodecImpl. Otherwise, we will likely have to refactor PojoCodecImpl again in the future.

JAVA-4967

stIncMale added 2 commits May 12, 2023 01:44
…rguments, CodecRegistry registry)`

Refactor `RecordCodec` and `CollectionCodec`.
`MapCodecV2` and `RawDataClassCodec` are still `Parameterizable` and are working.

JAVA-4954
@stIncMale stIncMale self-assigned this May 12, 2023
Comment on lines 38 to 48
/**
* Get a {@code Codec} using the given context, which includes, most importantly, the Class for which a {@code Codec} is required.
*
* <p>This method is called only if {@link #get(Class, List, CodecRegistry)} is not properly overridden.</p>
*
* @param clazz the Class for which to get a Codec
* @param registry the registry to use for resolving dependent Codec instances
* @param <T> the type of the class for which a Codec is required
* @return the Codec instance, which may be null, if this source is unable to provide one for the requested Class
*/
<T> Codec<T> get(Class<T> clazz, CodecRegistry registry);
Copy link
Member Author

@stIncMale stIncMale May 12, 2023

Choose a reason for hiding this comment

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

The driver no longer calls the "old" CodecProvider.get, i.e., we may even deprecate this method in the future and remove in 5.0, thus going back to having only one method on CodecProvider.

@stIncMale stIncMale requested a review from jyemin May 12, 2023 08:12
Comment on lines +68 to +70
default <T> Codec<T> get(Class<T> clazz, List<Type> typeArguments, CodecRegistry registry) {
return get(clazz, registry);
}
Copy link
Member Author

Choose a reason for hiding this comment

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

We don't have Beta in bson, but maybe we should. This will allow us to mark the new method as @Beta(Beta.Reason.CLIENT) and give ourselves more time to realize whether the signature of the method should be different. @jyemin What do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm happy enough with this signature that I'm willing to go with it as is.

Copy link
Member Author

Choose a reason for hiding this comment

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

We were mistakenly happy previously more than once about things in this domain. Let's hope, this is the last time)

@@ -47,7 +44,7 @@
*/
@SuppressWarnings("rawtypes")
final class CollectionCodec<C extends Collection<Object>> extends AbstractCollectionCodec<Object, C>
implements OverridableUuidRepresentationCodec<C>, Parameterizable {
implements OverridableUuidRepresentationCodec<C> {
Copy link
Member Author

Choose a reason for hiding this comment

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

I noticed that while CollectionCodec implements OverridableUuidRepresentationCodec, ParameterizedCollectionCodec does not. The same goes about MapCodecV2 and ParameterizedMapCodec. Is this intentional / OK?

Copy link
Collaborator

Choose a reason for hiding this comment

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

It's intentional

Comment on lines 24 to +29
public class DataClassCodecProvider : CodecProvider {
override fun <T : Any> get(clazz: Class<T>, registry: CodecRegistry): Codec<T>? =
DataClassCodec.create(clazz.kotlin, registry)
get(clazz, emptyList(), registry)

override fun <T : Any> get(clazz: Class<T>, typeArguments: List<Type>, registry: CodecRegistry): Codec<T>? =
DataClassCodec.create(clazz.kotlin, registry, typeArguments)
Copy link
Member Author

Choose a reason for hiding this comment

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

If this provider is rolled back to the previous implementation, some tests in DataClassCodecTest (for example, testDataClassWithParameterizedDataClass), which this PR did not modify, start failing with CodecConfigurationException: Could not find codec for number with type N. I.e., they do test parameterization and it appear to work when the provider properly overrides the new get method.

@@ -51,40 +53,55 @@ public <T> Codec<T> get(final Class<T> clazz) {
@Override
public <T> Codec<T> get(final Class<T> clazz, final List<Type> typeArguments) {
notNull("typeArguments", typeArguments);
isTrueArgument("typeArguments is not empty", !typeArguments.isEmpty());
Copy link
Member Author

Choose a reason for hiding this comment

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

This assertion and the similar assertion in ChildCodecRegistry.get contradicted the documentation of ChildCodecRegistry.get, which explicitly allows empty typeArguments (this PR has not changed that documentation). While all our tests happened to pass despite the assertions existing, users can pass empty typeArguments and get an unjustified error.

Copy link
Collaborator

@jyemin jyemin left a comment

Choose a reason for hiding this comment

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

Very nice improvement.

RecordCodec(final Class<T> clazz, final CodecRegistry codecRegistry, final List<Type> types) {
if (types.size() != clazz.getTypeParameters().length || types.isEmpty()) {
RecordCodec(final Class<T> clazz, final List<Type> types, final CodecRegistry codecRegistry) {
if (types.size() != clazz.getTypeParameters().length) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is so much nicer

@@ -47,7 +44,7 @@
*/
@SuppressWarnings("rawtypes")
final class CollectionCodec<C extends Collection<Object>> extends AbstractCollectionCodec<Object, C>
implements OverridableUuidRepresentationCodec<C>, Parameterizable {
implements OverridableUuidRepresentationCodec<C> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's intentional

Comment on lines +68 to +70
default <T> Codec<T> get(Class<T> clazz, List<Type> typeArguments, CodecRegistry registry) {
return get(clazz, registry);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm happy enough with this signature that I'm willing to go with it as is.

@stIncMale stIncMale requested a review from jyemin May 31, 2023 15:15
@stIncMale stIncMale merged commit 77b549d into mongodb:master Jun 2, 2023
@stIncMale stIncMale deleted the JAVA-4954 branch June 2, 2023 00:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants