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 null
s, (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.