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

JAVA-3815: Pojo Codec - Detect property models on extended interfaces #563

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

jflorencio
Copy link
Contributor

@jflorencio jflorencio commented Aug 14, 2020

If we have an interface like:

public interface SampleInterface {
  int getFirst();
  String getSecond();
}

which is implemented as:

public abstract class SampleImplementor implements SampleInterface {
  public abstract boolean isThird();
}

and has a concrete implementation that's called SampleImplementorImpl.
When PojoBuilderHelper goes to create the property models, it only checks
for methods on the current class and super classes - not interfaces. In
the above example, this means the property model will only have "third" entry -
no "first" or "second" property model. Today, you can manually get around that by
creating a @BsonCreator by hand:

public abstract class SampleImplementor implements SampleInterface {
  @BsonCreator
  public static SampleImplementor newInstance(
    @BsonProperty("first") int first,
    @BsonProperty("second") String second,
    @BsonProperty("third") boolean third) {
    return new SampleImplementorImpl(first, second, third);
  }

  public abstract boolean isThird();
}

The presence of the @BsonProperty on the @BsonCreator method will
create the property models. Conversely though, if you want to leverage a
Convention implementation to dynamically create a InstanceCreator
that knows how to find SampleImplementorImpl above, you won't be able
to. InstanceCreator is only provided properties for which
PropertyModel exists, so above, since PojoBuilderHelper didn't
discover the interface fields, and there is no exposed API to add
property models, your InstanceCreator will never be provided the
first and second fields present on the interface.

Simply put, if you provide the pojo codec a class that is not concrete,
extends an interface for methods, and does not have a @BsonCreator
annotation, there is no way to implement a InstanceCreator
implementation that works for the non concrete class. You get stuck in
a place where the class can serialize since the concrete implementation
SampleImplementorImpl is provided at runtime, but then you have no way
to deserialize it since usages in the code only reference SampleImplementor.

We've worked around this problem for years and created 700+ hand written
@BsonCreator annotations, so at this point I want to fix actual the problem.

This fix is relatively straight forward: Update PojoBuilderHelper to
scan implementing classes and interfaces, which provides a fully
populated property model.

JAVA-3815

If you have an interface like:
```
public interface SampleInterface {
  int getFirst();
  String getSecond();
}
```

which is implemented as:
```
public abstract class SampleImplementor implements SampleInterface {
  public abstract boolean isThird();
}
```

With a concrete implementation of SampleImplementor. When
`PojoBuilderHelper` goes to create the property models, it only checks
for methods on the current class, and super classes - not interfaces. In
the above example, this means the property model will only have "third",
and not "first" or "second". Today, you can manually get around that by
creating a @BsonCreator by hand:

```
public abstract class SampleImplementor implements SampleInterface {
  @BsonCreator
  public static SampleImplementor newInstance(
    @BsonProperty("first") int first,
    @BsonProperty("second") String second,
    @BsonProperty("third") boolean third) {
    return new SampleImplementorImpl(first, second, third);
  }

  public abstract boolean isThird();
}
```

The presence of the `@BsonProperty` on the `@BsonCreator` method will
create the property models. Conversely though, if you want to leverage a
Convention implementation to dynamically create a `InstanceCreator`
that knows how to find `SampleImplementorImpl` above, you won't be able
to. `InstanceCreator` only is provided properties for which
`PropertyModel` exists, so above, since `PojoBuilderHelper` didn't
discover the interface fields, and there is no exposed API to add
property models, your `InstanceCreator` will never be provided the
`first` and `second` fields present on the interface.

Simply put, if you provide the pojo codec a class that is not concrete,
extends an interface for methods, and does not have a @BsonCreator
annotation, there is no way to implement a InstanceCreator
implementation that works. We've worked around this problem for years
and created 700+ hand written @BsonCreator annotations, but, enough is
enough :-)

This fix is relatively straight forward: Update `PojoBuilderHelper` to
scan implementing classes and interfaces, which provides a fully
populated property model.
@jflorencio
Copy link
Contributor Author

Is there anything I can do to help make progress on this?

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