The cache management we have with ObjectAdapter, might be simplified such that we just work with java.lang.Object so far as possible. We would have a "disposable" ObjectAdapter that we instantiate around an Object whenever we need it - to access into the metamodel - and then throw it away after. Or perhaps eventually we might not need ObjectAdapter at all, just simply use #getClass() to look up the ObjectSpecification.
The main objective is to get rid of these two maps:
As their name suggests, these map:
oid -> adapter (look up an adapter from an oid)
pojo -> adapter (look up an adapter from a pojo)
The adapter itself has a reference to its oid (getOid()) and to its pojo (getObject()).
Most, though not all, objects have Oids. Certainly DN persistent objects do, in fact they do even if they are not yet persisted (prior to calling RepositoryService#persist(...). These will have a RootOid, which will indicate if the object is persistent or still transient.
The same is true of view models, these also have a RootOid. They also have a RecreatableObjectFacet which is used to actually manufacture the Oid (because the oid for view models is basically a serialization of the state of the domain object). The RootOid for view models will indicate that they are view models.
Values (ints, strings etc), do NOT have an oid. This also means that - obviously - they don't get saved in the OidAdapterHashMap; and they probably aren't saved in PojoAdapterHashMap. Value objects will have a ValueFacet.
There's one other subtype of Oid (apart from RootOid), namely ParentedCollectionOid. That's because the Set or List that holds "child" objects is also managed as an adapter; ie:
Why is this done? Because a long time ago (before DN) the framework did its own persistence, so this was for lazy loading etc.
The "ensureMapsConsistent" method in PersistenceSessionXxx is there to ensure that these are maintained correctly; it's rather paranoid because if these get out of sync, then bad things would happen; eg:
There's also some rather horrible "remapRecreatedPojo" methods that hack this stuff
All this stuff is a legacy from the original client/server architecture that the framework used to have; it was probably needed then but I really don't think it's needed now.
At the moment the object adapters are created eagerly, typically using PersistenceSession#adapterFor(...). For domain services, we eagerly create an adapter around every service before each session, "just in case" it gets interacted with. This could be removed
This also requires the ability to infer the Oid from the pojo, on the fly. There are two different ways this is done:
- for DN entities, there is the JdoObjectIdSerlaizer
- for view models, there's RecreatableObjectFacet, already mentioned.
Ideally the code to recreate/rehydrate the object should define a consistent API to the rest of the framework. My thinking is that it could perhaps be a pluggable service so that we can then support other persistence runtime stores ... The idea is that the framework encounters a pojo and then asks for a service (via an SPI) to see which can extract/infer an Oid from it, using the usual chain-of-responsibility pattern. Out-of-the-box the framework would provide two default implementations, one for DN entities (JdoIdHelper), the other for view models.
Looking forward, ideally, PersistenceSession shouldn't need to use ObjectAdapter at all; the ObjectAdapter really exists only for the viewer(s) etc to obtain the ObjectSpecification to know how to render the object. Ultimately, we could get rid of ObjectAdapter completely and just uses pojos (=domain objects) everywhere. ObjectSpecification would remain, though. I think this is for other tickets, though, not this one.
OK, hopefully some the above makes sense!!!