[JAVA-5128] Add annotations to support default values for primitive types Created: 31/Aug/23 Updated: 05/Sep/23 |
|
| Status: | Backlog |
| Project: | Java Driver |
| Component/s: | POJO |
| Affects Version/s: | 4.10.0 |
| Fix Version/s: | None |
| Type: | New Feature | Priority: | Major - P3 |
| Reporter: | Ben Weidig | Assignee: | Jeffrey Yemin |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Description |
SummaryIf a Record evolves by gaining a new component, the RecordCodec will trigger an IllegalArgumentException in case of a new primitive component, as the missing field is translated into null. Please provide the version of the driver. If applicable, please provide the MongoDB server version and topology (standalone, replica set, or sharded cluster).4.10.0, standalone, running in Docker How to Reproduce
Any retrieval from a MongoCollection<Aspect> triggers the exception. Additional BackgroundThe newInstance call in https://github.com/mongodb/mongo-java-driver/blob/master/bson-record-codec/src/main/org/bson/codecs/record/RecordCodec.java#L285 will result in an IllegalArgumentException, as the constructorArguments contain null for the new component.
The problem, in my opinion, is that the componentModel uses wrapper types, but the constructor is detected with the original/non-wrapper types, so adding another constructor that uses wrapper types isn't a feasible workaround. |
| Comments |
| Comment by Ben Weidig [ 02/Sep/23 ] | ||||
|
Thank you for the explanation of the current behavior. My reasoning was how evolving Records behave during regular serialization. Looking at other serialization libraries, annotations seem to be the way to go for default values. I haven't dug too deep into the code, so I'm not even sure my following (rough) ideas are feasible or makes sense in the general context... Thinking about possible use cases, I come up with the same you mentioned:
If only the first one is required, I think a single annotation like @BsonDefaultValue will suffice, as the user must not provide an actual default value. In the case of needing a custom value, having multiple annotations for each type would be a necessity, as annotations don't allow Object as a value. But thinking further than just primitives, how about supplying a default value for a nested Record or Object-based component? The @BsonDefaultValue could accept a org.bson.codecs.Decoder<T> class that creates the value if the document is missing the field:
This way, not a full-blown Codec is required from the user, but they can build a default value provider as complex as they need. Long story short, any kind of default value support is a welcomed addition to the driver. Having a simple annotation-based solution, a single one or one per primitive type, would be the easiest approach from a user perspective IMO. | ||||
| Comment by Jeffrey Yemin [ 01/Sep/23 ] | ||||
|
Hi ben@netzgut.net, this behavior is intentional and consistent with the PojoCodec (for which we have a test that asserts the behavor). The reason it works this way is because otherwise there would be no way to distinguish between an actual value decoded from the database and the default value for the primitive type. Moreover, you might want the default value for a missing field to be something other than the default value for primitives in Java, e.g. in the case above, you might want the component name to be filterable and default to true. But your use case is certainly valid, so the driver should provide some solution. One idea is to add a new annotation that allows the application to tell the decoder that it's allowed to be missing, and to supply a default value as well. Something like:
And something similar for the other primitive types. Let us know what you think about this idea. | ||||
| Comment by PM Bot [ 31/Aug/23 ] | ||||
|
Hi ben@netzgut.net, thank you for reporting this issue! The team will look into it and get back to you soon. |