Uploaded image for project: 'Causeway'
  1. Causeway
  2. CAUSEWAY-1807

Wrap Domain Entities by default



    • Wish
    • Status: Closed
    • Major
    • Resolution: Won't Fix
    • 1.15.1
    • None
    • Core
    • None


      Maybe this should be controlled by a new nature on domain services?  Whether to wrap should be "inherited", ie if invoke a wrapped domain service then any entities returned would also be wrapped.



      This way, all hide/disable/validate constraints, and other constraints/invariants forced through actions, are always ensured by default.

      This will require to wrap by default:

      • New Domain Entity instances / objects (ie, changes on FactoryService).
      • Domain Entities returned by queries (ie, changes on RepositoryService).

      Users might disable this new default behaviour through configuration, as some projects can prioritize performance (avoiding wrapping invocations) vs Domain constraints/invariants enforcement.

      Dan's notes:

      I'd like to refine the concept of wrapping while implementing this ticket.

      The idea of wrapping was originally to allow the UI to be simulated within integration tests. The intent of this ticket is to formalize the idea of the same set of validations being done automatically between programmatic interactions from one service/entity to another service/entity.

      So, the more general concept (common to both UI/domain interactions and domain-to-domain programmatic interactions) is one of trust boundaries. If there is no trust from the calling client to the supplying service/entity, then that interaction should be wrapped.

      However, the wrapping model as it currently stands is a little bit too UI/domain oriented, in that it has both hidden AND disabled as well as validate phases. From the perspective of a programmatic domain-to-domain interaction there's no meaningful distinction between the hidden and disabled constraints: they both mean: "that object isn't in a state to be called". In other words its a pre constraint that is not satisfied.

      The other aspect here is that I can imagine that there are actions that we would like to allow to be made programmatically (ie through a wrapper) but which shouldn't be part of the UI. In other words these actions form part of the programmatic API of a module, just not part of its UI.

      Putting all this together, I propose that we slightly change the meaning of wrapping (though we'll keep the current implementation too for backwards compatibility), namely that by default wrapped object will check the disable and validate phases only, ie it will not check the hidden phase. This allows such actions to be indicated as hidden (probably using @ActionLayout or .layout.xml or security) but still able to be called programmatically. The disable phase = pre check.

      We could define the following terminology:

      • "default" wrapping : as described above, checks only disable and validate, not hidden
      • "strict" wrapping - for backward compatibility, also checks hidden first

      We could define a configuration property:

      isis.runtime.wrapping=default | strict | none

      with "default" wrapping being the default if not specified.

      In terms of the programming API, the WrapperFactory#wrap(...) will obviously be less important than it was, because by default objects will be wrapped. For backward compatibilty, I think this should continue to create strict wrappers

      The wrap(...) method is also overloaded, with wrap(ExecutionMode). We can extend this enum:

      • EXECUTE - (existing) returns a strict wrapper
      • SKIP_RULES - (existing) skips applying the hidden/disable/validate rules
      • NO_EXECUTE - (existing) applies hidden/disabled/validate, but does not execute
      • DEFAULT - (new) returns a "default" wrapper, applies only disable/validate but not hidden

      (new if the object passed in is already wrapped, then it should be replaced with a wrapper with the specified mode. Prevoiusly this was a no-op, I think.

      The unwrap(...) method is unchanged.


        Issue Links



              Unassigned Unassigned
              oscarbou Óscar Bou
              0 Vote for this issue
              3 Start watching this issue