Uploaded image for project: 'Isis'
  1. Isis
  2. ISIS-743

Remove the concept of transient objects and of @NotPersistable; instead we have view models.

    Details

    • Type: Wish
    • Status: Open
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: 3.0.0
    • Component/s: Core
    • Labels:
      None

      Description

      For discussion; but think that view models supercede our earlier ideas of transient objects etc.

      1. Design-1.PNG
        28 kB
        Dan Haywood
      2. Design-2.PNG
        31 kB
        Dan Haywood

        Activity

        Hide
        davotnz David Tildesley added a comment -

        I don't see the link between view models and "transient objects" (which I assume is referring to domain objects).

        If by transient is meant non-persisted then there is a problem. Many business applications have been built that do not rely on their own persistence store. They fetch and send information to external services and those external services take care of any persistence required. However these business applications have a full domain model for their problem domain.

        if the only type of domain object I can create in ISIS is a persisted object then I can't use ISIS in the future.

        Hopefully I am misinterpreting the intention of this ticket.

        Show
        davotnz David Tildesley added a comment - I don't see the link between view models and "transient objects" (which I assume is referring to domain objects). If by transient is meant non-persisted then there is a problem. Many business applications have been built that do not rely on their own persistence store. They fetch and send information to external services and those external services take care of any persistence required. However these business applications have a full domain model for their problem domain. if the only type of domain object I can create in ISIS is a persisted object then I can't use ISIS in the future. Hopefully I am misinterpreting the intention of this ticket.
        Hide
        danhaywood Dan Haywood added a comment -

        I can tell you sound a bit disturbed about this idea... let me see if I can allay that.

        Start with... you ask about the link with transient objects.

        Back in time, when Isis was still Naked Objects Framework, the main production deployment was the drag-n-drop viewer with a client/server architecture. (This is the architecture that still runs in the big government system in Ireland). This architecture does/did fully support transient objects, in the sense that a transient object is a domain object that might or might get persisted. Any actions invoked on it are invoked client-side, within the DnD viewer. Its Oid (object identifier) is basically a GUID. If the object does get persisted, then it is sent to the server, and is returned with a n updated Oid, being the one assigned by the server-side object store. There was lots of horrendous code involved to do with syncing the identity maps that associate Oids/pojos/ObjectAdapter wrappers when this happens... I was very happy to remove this code when we dropped client/server support a few years back. The Restful Objects spec refers to such transient objects as "proto-persistent".

        In the Irish system we also have used (or perhaps mis-used) transient objects to act as a view model, eg for bulk entry and like an extended action prompt. Here the user enters data into the transient object (and perhaps child transient objects). Invoking an action on the transient object then generally goes off and updates/persists a bunch of other data. The @NotPersistable annotation was a way to suppress the "save" button from being rendered in the DnD viewer.

        So, historically, transient objects have had these two roles... to act as genuine proto-persistent objects, and to act as a view model of sorts.

        In the Wicket viewer, things are necessarily different, because there is no client to hold the state of the transient object. The same effect is achievable though, because Wicket is stateful, and so each rendered page is held in the user's HTTP session and so can encode the state of a transient object. The Wicket viewer's ObjectAdapterMemento class basically does this... if the object is persistent, we just serialize its Oid, but if the object is transient, then we serialize the object's entire state.

        That said, Estatio doesn't use this technique at all, so it could be buggy, and - since I originally coded up that stuff - I've started to change my mind about the desirability of transient object support in this way. The main reason I'm changing my mind is because of the work I've been doing more recently on the Restful Objects spec.

        So, to talk about that for a moment... unlike the Wicket viewer, the RO viewer is stateless; this absolutely must be the case. So the responsibility of holding the state of transient objects moves to the restful client, ie outside of scope of Isis. Now the Restful Objects spec does support transient objects (calling them proto-persistent objects, as I mentioned). However, the representation of a transient object has no Oid and no "self" link (ie URL)... which makes sense because there is no resource on the server-side to address.

        View models, however, are supported by the RO viewer. The Oid of a view model is basically the encoded state of its values. This has the side-effect of making it immutable, but that's not a bad thing; its actions can always return a different view model.

        Given that view models fulfill our historic requirements for what transient objects have done, we're considering simplifying the RO spec in v2.0 and dropping proto-persistents; they don't really fit in anyway. And so what this ticket is about is the idea of removing the concept completely also from core and from the Wicket viewer.

        OK, that's the background to this. Let me talk about how I envisage you could write apps in Isis where the persistence is managed by some external service. A good example, actually, is context.io [2] that Dileepa on the dev list is considering using for a Google Summer of Code project this year. Here context.io provides a REST API to return information about email messages; these are persisted elsewhere. How would write an Isis application that acts as the front-end of sorts to these externally persisted emails? I see two design alternatives.

        The first is through a domain service, eg acting as a client to an external service. If we wanted Isis to render a given email message, then we could create a view model that acts as a wrapper around the JSON returned by that domain service. The user could invoke actions on that Isis view model, which would then interact through the domain service (eg to context.io) to interact with the corresponding externally-managed object.

        The second is to integrate a little deeper, by writing a custom Isis Object Store. Here the object would appear to be a regular persistent entity as far as the rest of Isis is considered, however its actual persistence would be accomplished through calls to the domain service.

        Writing an object store like this is a pretty serious undertaking, and so an alternative is to configure to use the regular JDO/DN object store, but then DataNucleus's own Store Manager API [2] to plug in some different persistence mechanism. Given that DN has a whole bunch of Store Manager implementations (including for example persisting to an Excel spreadsheet!), I'm expecting that to be an easier thing to do than to write an Isis Object Store. (It's also why I think we should ditch Isis ObjectStore API completely, but that's a different ticket).

        The attached diagrams show alternatives (1) and (2).

        I don't know if the above missive helps dispel your fears or not. If not, I guess the main question I have back is how would you tackle the addressability issue that the stateless RO viewer introduces (if we just carried on supporting transient objects as is).

        [1] http://context.io/
        [2] http://www.datanucleus.org/extensions/store_manager.html

        Show
        danhaywood Dan Haywood added a comment - I can tell you sound a bit disturbed about this idea... let me see if I can allay that. Start with... you ask about the link with transient objects. Back in time, when Isis was still Naked Objects Framework, the main production deployment was the drag-n-drop viewer with a client/server architecture. (This is the architecture that still runs in the big government system in Ireland). This architecture does/did fully support transient objects, in the sense that a transient object is a domain object that might or might get persisted. Any actions invoked on it are invoked client-side, within the DnD viewer. Its Oid (object identifier) is basically a GUID. If the object does get persisted, then it is sent to the server, and is returned with a n updated Oid, being the one assigned by the server-side object store. There was lots of horrendous code involved to do with syncing the identity maps that associate Oids/pojos/ObjectAdapter wrappers when this happens... I was very happy to remove this code when we dropped client/server support a few years back. The Restful Objects spec refers to such transient objects as "proto-persistent". In the Irish system we also have used (or perhaps mis-used) transient objects to act as a view model, eg for bulk entry and like an extended action prompt. Here the user enters data into the transient object (and perhaps child transient objects). Invoking an action on the transient object then generally goes off and updates/persists a bunch of other data. The @NotPersistable annotation was a way to suppress the "save" button from being rendered in the DnD viewer. So, historically, transient objects have had these two roles... to act as genuine proto-persistent objects, and to act as a view model of sorts. In the Wicket viewer, things are necessarily different, because there is no client to hold the state of the transient object. The same effect is achievable though, because Wicket is stateful, and so each rendered page is held in the user's HTTP session and so can encode the state of a transient object. The Wicket viewer's ObjectAdapterMemento class basically does this... if the object is persistent, we just serialize its Oid, but if the object is transient, then we serialize the object's entire state. That said, Estatio doesn't use this technique at all, so it could be buggy, and - since I originally coded up that stuff - I've started to change my mind about the desirability of transient object support in this way. The main reason I'm changing my mind is because of the work I've been doing more recently on the Restful Objects spec. So, to talk about that for a moment... unlike the Wicket viewer, the RO viewer is stateless; this absolutely must be the case. So the responsibility of holding the state of transient objects moves to the restful client, ie outside of scope of Isis. Now the Restful Objects spec does support transient objects (calling them proto-persistent objects, as I mentioned). However, the representation of a transient object has no Oid and no "self" link (ie URL)... which makes sense because there is no resource on the server-side to address. View models, however, are supported by the RO viewer. The Oid of a view model is basically the encoded state of its values. This has the side-effect of making it immutable, but that's not a bad thing; its actions can always return a different view model. Given that view models fulfill our historic requirements for what transient objects have done, we're considering simplifying the RO spec in v2.0 and dropping proto-persistents; they don't really fit in anyway. And so what this ticket is about is the idea of removing the concept completely also from core and from the Wicket viewer. OK, that's the background to this. Let me talk about how I envisage you could write apps in Isis where the persistence is managed by some external service. A good example, actually, is context.io [2] that Dileepa on the dev list is considering using for a Google Summer of Code project this year. Here context.io provides a REST API to return information about email messages; these are persisted elsewhere. How would write an Isis application that acts as the front-end of sorts to these externally persisted emails? I see two design alternatives. The first is through a domain service, eg acting as a client to an external service. If we wanted Isis to render a given email message, then we could create a view model that acts as a wrapper around the JSON returned by that domain service. The user could invoke actions on that Isis view model, which would then interact through the domain service (eg to context.io) to interact with the corresponding externally-managed object. The second is to integrate a little deeper, by writing a custom Isis Object Store. Here the object would appear to be a regular persistent entity as far as the rest of Isis is considered, however its actual persistence would be accomplished through calls to the domain service. Writing an object store like this is a pretty serious undertaking, and so an alternative is to configure to use the regular JDO/DN object store, but then DataNucleus's own Store Manager API [2] to plug in some different persistence mechanism. Given that DN has a whole bunch of Store Manager implementations (including for example persisting to an Excel spreadsheet!), I'm expecting that to be an easier thing to do than to write an Isis Object Store. (It's also why I think we should ditch Isis ObjectStore API completely, but that's a different ticket). The attached diagrams show alternatives (1) and (2). I don't know if the above missive helps dispel your fears or not. If not, I guess the main question I have back is how would you tackle the addressability issue that the stateless RO viewer introduces (if we just carried on supporting transient objects as is). [1] http://context.io/ [2] http://www.datanucleus.org/extensions/store_manager.html
        Hide
        davotnz David Tildesley added a comment - - edited

        Not really (fears remain). Anything can be an "oid" for a domain object - it doesn't have to be a persisted object identifier (that you would get automatically via the DM). e.g it could be an employee number, social security number, acccount number ... which would typically be the case if the information was coming from an external service. I can see you would have an immediate problem with this with a generated viewer - so I would need to give it some thought.

        Using JDO with a custom plugged in persistence implementation appears way too complex to me. Bypassing the PD layer ( i.e. UI <-- SI) is promoting shifting business logic into the UI layer. Both unpalatable. By the way I am assuming the domain service is pretty much the equivalent of a System Integration layer (takes care of the marshalling and unmarshalling of data to and from some service integration and connected to the domain object via DI.

        This old but relevant thread is worth reading [1]

        [1] http://www.featuredrivendevelopment.com/node/582

        Show
        davotnz David Tildesley added a comment - - edited Not really (fears remain). Anything can be an "oid" for a domain object - it doesn't have to be a persisted object identifier (that you would get automatically via the DM). e.g it could be an employee number, social security number, acccount number ... which would typically be the case if the information was coming from an external service. I can see you would have an immediate problem with this with a generated viewer - so I would need to give it some thought. Using JDO with a custom plugged in persistence implementation appears way too complex to me. Bypassing the PD layer ( i.e. UI <-- SI) is promoting shifting business logic into the UI layer. Both unpalatable. By the way I am assuming the domain service is pretty much the equivalent of a System Integration layer (takes care of the marshalling and unmarshalling of data to and from some service integration and connected to the domain object via DI. This old but relevant thread is worth reading [1] [1] http://www.featuredrivendevelopment.com/node/582
        Hide
        davotnz David Tildesley added a comment -

        Some more thoughts/assumptions on transient domain objects:

        1. oid - annotate an attribute or use attribute naming pattern
        2. Restful remoting mean client maintains required state - client doesn't care whether domain object is transient or not.
        3. Restful remoting means the server trashes the domain object instance after the response. However domain behaviour is not transferred and everytime a behaviour is invoked on a domain object graph, the domain graph has to re-instantiated at the server - big performance hit unless developer uses a cache (ehcache or similar).

        Am I wide of the mark with any of the above?

        Show
        davotnz David Tildesley added a comment - Some more thoughts/assumptions on transient domain objects: 1. oid - annotate an attribute or use attribute naming pattern 2. Restful remoting mean client maintains required state - client doesn't care whether domain object is transient or not. 3. Restful remoting means the server trashes the domain object instance after the response. However domain behaviour is not transferred and everytime a behaviour is invoked on a domain object graph, the domain graph has to re-instantiated at the server - big performance hit unless developer uses a cache (ehcache or similar). Am I wide of the mark with any of the above?
        Hide
        danhaywood Dan Haywood added a comment -

        Further discussion is taking place directly on the dev list, see http://isis.markmail.org/thread/rko2cf7kbi6uvvqd.

        Show
        danhaywood Dan Haywood added a comment - Further discussion is taking place directly on the dev list, see http://isis.markmail.org/thread/rko2cf7kbi6uvvqd .

          People

          • Assignee:
            Unassigned
            Reporter:
            danhaywood Dan Haywood
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:

              Development