[ 
https://issues.apache.org/jira/browse/ISIS-1807?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Dan Haywood updated ISIS-1807:
------------------------------
    Description: 
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.

  was:
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.







> Wrap Domain Entities by default
> -------------------------------
>
>                 Key: ISIS-1807
>                 URL: https://issues.apache.org/jira/browse/ISIS-1807
>             Project: Isis
>          Issue Type: Improvement
>          Components: Core
>    Affects Versions: 1.15.1
>            Reporter: Oscar Bou
>            Priority: Major
>             Fix For: 2.0.0
>
>
> 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.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to