Codec and unmodifiable POJO

Hi
I’ve just finish the course and started writing code in a real project and am facing a small problem.

Let’s say I have a POJO with a property named “firstName” that I want to map to a Mongo property named “name1” (for sack of simplicity, they a both Strings). I know I could annotate the POJO’s property with @BsonProperty, but what if I can’t modify the POJO (third party lib). Is it feasible to do such mapping with a ClassModelBuilder and a PropertyModelBuilder for instance?

With the same restriction in mind, what happens if my POJO does not have a default constructor? Can I specify somewhere how to instantiate a POJO based on the database model (i.e retrieving one or two fields and passing them to a specific constructor)?

I know I could do both of these by registering a custom Codec with the CodeRegistries.fromCodecs(…) when building my CodecRegistry but if I do so, I need to map the whole POJO class (each and every property). I was maybe hoping to be able to a tinker with just one or two PropertyModelBuilder…

Regards
William

Hi @William_01115,

Awesome questions!

Correct, in these cases you will have to resort to the ClassModelBuilder which can be crated via the ClassModel.builder() method.
Now, there are few default requirements all listed in this page, that can be override:
http://mongodb.github.io/mongo-java-driver/3.9/bson/pojos/

You will have to use a combination between PropertyModel and ClassModel builders in cases where you do not have direct access to the POJO class. Via reflection, and as long has the fields themselves are exposed with public setters and getters, you will be able to define a Codec for the class.

This is the part where I’m not 100% sure, but I’ll get back to you on this.
In any case, if you do have such a scenario, where you are required to have a default constructor, and it does not exist, we can always a class extending the third library POJO that handles the mapping

import external.third.party.UserPOJO;

class ExtendedUserPOJO extends UserPOJO {
  // MAGIC OF ENCAPSULATION 
}

Again, I’m going to check in more detail on can we override, without resorting to encapsulation workarounds, to achieve this.

You can extend the usage of the PropertyModel inside the ClassModel in your code registry and use generics to achieve the map all other fields that do not require any “special” type conversion or naming mapping.

N.

HI @Norberto
Thanks for the answer. I will have a look at the link provided.

However extending the POJO is not always possible. If the POJO is final or if the argument constructor is used to initialize final or private properties with no setter method.
In a UserPOJO, I could easily see a “private final String id” which uniquely identifies the user. In such scenario, the id HAS to be initialize in a constructor.

w.

Hi @William_01115,

You stand correct, we might now always be able to extend a class.
I’ve done a bit of digging and here some extended points:

what happens if my POJO does not have a default constructor? Can I specify somewhere how to instantiate a POJO based on the database model (i.e retrieving one or two fields and passing them to a specific constructor)?

In that case they would have to use the ClassModelBuilder and register your own custom InstanceCreatorFactory to create new instances.

I was maybe hoping to be able to a tinker with just one or two PropertyModelBuilder…

Thats fine just call ClassModel.builder(clazz) to get a configured builder that you can then go and tweak.

N.