incubator-isis-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Mike Burton <>
Subject Re: More on the Oid refactor
Date Mon, 07 May 2012 19:54:07 GMT
Hi Dan,

Many thanks, helps a lot. 


On 7 May 2012, at 18:40, Dan Haywood <> wrote:

> On Saturday, 5 May 2012, Mike Burton wrote:
>> Hi Dan,
>> Thanks for the update, good work, worth eating a few bits of eggshell:-)
>> Could you list/ clarify meanings of your canonical string for symbols #~!
>> etc please- I'm confused by difference between ~ and # eg
>> CUS:123~NME:2~CTY:LON
> Hi Mike,
> First off, I made two slight mistakes in my first email: # should have been
> $ throughout, and CUS:123#NME:2 should have been CUS:123~NME:2.
> Thus:
> CUS:123                       - persistent root
> !CUS:123                      - transient root
> CUS:123$items                 - collection of persistent root
> !CUS:123$items                - collection of transient root
> CUS:123~NME:2                 - aggregated object within persistent root
> !CUS:123~NME:2                - aggregated object within transient root
> CUS:123~NME:2~CTY:LON         - aggregated object within aggregated object
> within root
> CUS:123~NME:2$items           - collection of an aggregated object within
> root
> CUS:123~NME:2~CTY:LON$streets - collection of an aggregated object within
> aggregated object within root
> I wonder whether that is what caused your confusion?  Otherwise, and to
> answer the question, though:
> There's no intrinsic "meaning" to the symbols, other than to distinguish
> the parts of the OID.  The ~ is the prefix for each aggregated object,
> while $ is the prefix for a collection, if any.  I chose "~" because it's
> easy to see, I chose "$" because it is used as a separator in Java (outer
> vs inner class bytecode).
> A more useful answer, though , might be for me to explain why OIDs are so
> important.
> Within Isis we use an OID as the identifier of an ObjectAdapter, which in
> turn is a wrapper around the pojo.  The main responsibility of an
> ObjectAdapter is to manage the "resolve state", ie lazy loading of an
> object.  It's also used in dirty tracking: whether an object needs to be
> saved to the object store.  The ObjectAdapter also points to the
> corresponding ObjectSpecification which describes the structure of the
> object: ObjectAdapter is like java.lang.Object, while ObjectSpecification
> is like java.lang.Class.  Also: an OID is a value object (equals, hashCode
> etc).
> OIDs are important because they are provide an immutable handle to an
> object.  This is useful for webapps, eg to use in links and forms, and its
> useful for the JSON (restful) viewer, eg in URLs.  It's also useful for
> object stores, because they can (or rather, will now be able to) use the
> OID's string form to represent a reference between an object or the
> contents of a collection.
> OIDs are also more generally useful in supporting workflows: an OID is
> bookmarkable, so could be added into a favourites list, o (as we do on the
> big Irish project), can be converted into a barcode, which is great for
> handling incoming communications/correspondence that's been scanned.
> ~~~
> We've had the concept of "CollectionOid"s for a while in Isis: if a
> Customer has a collection of Order's, then the CollectionOid is the ID for
> the java.util.List that holds a Customer's Order pojos.  The "AggregateOid"
> is newer, introduced to support NoSQL databases and the more general DDD
> concept of an aggregate root.  Each AggregateOid has a localId, which is
> unique within the aggregate; or in other words it is globally unique in
> conjunction with the parent Oid.
> ~~
> The string format I'm suggesting here tries to reflect the "nesting" of
> objects of both aggregated entities and of collections:
> CUS:123 is the RootOid for a simple root aggregate; it's a CUS(tomer),
> id=123.
> CUS:123~NME:1 is an AggregateOid for the N(a)ME of a customer, with
> localId=1.  In other words, this is modelling the fact that a customer
> might have several names or aliases, this being the OID of one of those
> names.  Note that we don't know how the name object is related to its
> "owning" customer; but that's the responsibility of the
> ObjectAdapter/ObjectSpecification to furnish that information.
> CUS:123$items is the CollectionOid of a the "items" collection of customer
> id=123.  We don't know what type of thing are stored in the "items"
> collection; but that's not the responsibility of an Oid: such info can be
> found from the ObjectSpecification for the Customer type.  Again, we also
> don't know what the content of the "items" collection is: but that is the
> responsibility of the ObjectAdapter.
> ~~~
> Lastly, in case it's not obvious, the "CUS" is the abbreviated object type
> (as per @ObjectType annotation).  If there is no such annotation, then the
> object type is taken to be the fully-qualified class name.
> HTH,
> Dan
>> Mike Burton
>> ( iPhone)
>> On 5 May 2012, at 10:13, Dan Haywood <> wrote:
>>> Hello all,
>>> First, just to say that I *know* the build is broken, and it's a pretty
>>> poor show on my part to let it happen, but it's a little bit of breaking
>>> eggs to make an omelette.
>>> Second, wanted to update on my current thinking on OIDs ... because this
>> is
>>> what I'm currently working on and what I intend to commit as soon as I
>> can
>>> (hopefully this coming week).
>>> Already committed:
>>> * our OIDs are now immutable
>>> * we have three types of OID:
>>>  - RootOid, which is the OID of a root entity  (implementation: is
>>> RootOidDefault).
>>>  - AggregateOid, which is an aggregated entity that is persisted within
>> a
>>> root entity (eg part of a JSON doc in MongoDB).
>>>  - CollectionOid, which wraps a List or Set of a root entity
>>> - The RootOidDefault was refactored from SerialOid, but it now has an
>>> "objectType" (eg "CUS" for customer), so is self-describing.
>>> - The CollectionOid also existed previously, and wraps a List or Set for
>> an
>>> entity
>>> - The AggregatedOid we also had a version of; it has a localId to
>>> distinguish it from other aggregates of its type (within its parent root)
>>> - Both CollectionOid and AggregatedOid have a parentOid
>>> Not yet committed:
>>> The first thing I've added to AggregateOid is its own objectType, and so
>>> that has also led me to introduce a TypedOid interface: both
>> RootOidDefault
>>> and AggregatedOid implement TypedOid.  And so from there we can say that
>>> parents (of either AggregateOids or of CollectionOids) are always
>> TypedOids.
>>> With this change to AggregateOid, we can now say that all OIDs contain
>>> enough information to fully recreate them as objects: we do know the type
>>> of the object to instantiate and its unique identity.  That isn't to say
>>> there's enough information to determine how these objects are wired back
>>> together again, but that's a responsibility of the object store to
>> persist
>>> this additional structural information.
>>> ~~~
>>> Following on from this, I've been working on a string format for each of
>>> these three types.  Currently we have numerous incompatible ways of
>>> memo-izing OIDs: the XML object store does it one way, the NOSQL object
>>> store another, the SQL OS object store another, the "*Mapping" classes
>> for
>>> the scimpi and HTML viewers (for storing the states of transient objects
>> in
>>> the Http session) in another, the Memento utility class in yet another,
>> the
>>> JSON viewer (in its URLs) yet another.  It's all very complex and messy.
>>> Having a standard canonical string form would therefore simplify things
>>> enormously.
>>> I've just been writing the unit tests for this, and I've come up with the
>>> following:
>>> CUS:123                       - persistent root
>>> !CUS:123                      - transient root
>>> CUS:123#items                 - collection of persistent root
>>> !CUS:123#items                - collection of transient root
>>> CUS:123#NME:2                 - aggregated object within persistent root
>>> !CUS:123~NME:2                - aggregated object within transient root
>>> CUS:123~NME:2~CTY:LON         - aggregated object within aggregated
>> object
>>> within root
>>> CUS:123~NME:2#items           - collection of an aggregated object within
>>> root
>>> CUS:123~NME:2~CTY:LON#streets - collection of an aggregated object within
>>> aggregated object within root
>>> I've pasted in the unit tests for this below, so you can see the tests in
>>> all its glory.
>>> Note how this allows for aggregates to be embedded within aggregates
>> (even
>>> though I'm not sure that any of the object stores could handle this yet).
>>> OK, that's it for now.  Wanted to put this out there for reaction; as
>> usual
>>> with these things, I'll assume silence = consensus.
>>> Dan
>>> ~~~~~~
>>> package org.apache.isis.core.metamodel.adapter.oid;
>>> import

View raw message