Caveats - gkresic/commons-fields GitHub Wiki

Working with partial objects solves some problems, but it also introduces some new ones.

Buckle up.

Serialization

Checked getters help a lot in tracing bugs, but also may interfere with popular serialization libraries since most of them use reflection to detect getters to serialize and will fail with FieldUnavailableException as soon as they encounter a getter for an uninitialized attribute.

Additionally, if you serialize your entities to format that doesn't support nulls, (for example, if you use XML serializers that don't support xsi:nil), you'll have to serialize fields attribute, but also make sure it is deserialized last (so that setter invocations during deserialization don't corrupt the list of initialized fields).

commons-fields-jackson subproject provides such functionality when working with Jackson, but for other formats/libs you are on your own.

Stale data

commons-fields is much about optimizing unnecessary objects resolves (to avoid "waterfall effects"), but holding objects on a client for too long without refresh can be equally dangerous. For example, if you try to extend an object whose subgraph has changed, be ready to meet EntityUnavailableException.

General advice on how to stay safe would be to assume objects are extendable only for the duration of one event loop. Everything older than that requires special treatment, either by listening for mutation events or by passing entities around as references (to force called function to extend entity with fresh values). Obvious exception to this rule are "data" objects (ones that implement HasFields, but not HasEntityFields) that are never extended and can be used as such for unlimited amount of time (with only "problem" that stored data may become stale).

Slow batched operations

Batchers have proven to be enormously useful pattern (yes, even with HTTP/2's cheap requests, as they optimize multiple, often expensive, reads from backing storage, too), but keep in mind that all batched operations on one entity (get and extend) will effectively take as long as longest operation. So, if you find that your whole app pauses because of some not-so-important background task, feel free to use multiple batchers for one entity type: use one only for operations that you can guarantee will be small and fast and other for potentially slow ops.