You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2018/02/14 00:11:40 UTC

[isis] 02/02: ISIS-1860: improves docs regarding CommandReification

This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch maint-1.16.1
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 392d475ac421ace05b18128f10cb2dea543aeba0
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Wed Feb 14 00:11:31 2018 +0000

    ISIS-1860: improves docs regarding CommandReification
---
 .../guides/rgant/_rgant-Action_command.adoc        | 291 ++++++++++++++++-----
 .../guides/rgant/_rgant-Property_command.adoc      | 218 ++++++++++-----
 2 files changed, 377 insertions(+), 132 deletions(-)

diff --git a/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Action_command.adoc b/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Action_command.adoc
index 9665b22..f03d9a8 100644
--- a/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Action_command.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Action_command.adoc
@@ -1,15 +1,21 @@
 [[_rgant-Action_command]]
-= `command()`
+= Command Persistence and Processing
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 :_basedir: ../../
 :_imagesdir: images/
 
 
-The `@Action(command=...)` attribute (and the related `@Action(commandXxx=...)` attributes) allows an action invocation to be made into a concrete object such that it can be inspected and persisted.
-The primary use case for this are to support the deferring the execution of the action such that it can be invoked in the background, and to replay commands in a master/slave configuration.
+Every action invocation (and property edit for that matter) is automatically reified into a concrete `Command` object.
+The `@Action(command=..., commandXxx=...)` attributes provide hints for the persistence of that `Command` object, and the subsequent processing of that persisted command.
+The primary use cases for this are to support the deferring the execution of the action such that it can be invoked in the background, and to replay commands in a master/slave configuration.
 
+Note that for a `Command` to actually be persisted requires an appropriate implementation of `CommandService` SPI.
+The framework does _not_ provide an implementation of this SPI "out-of-the-box".
+However, the (non-ASF) Incode Platform's link:http://platform.incode.org/modules/spi/command/spi-command.html[ command module]) _does_ provide such an implementation.
 
 
+== Design
+
 The annotation works with (and is influenced by the behaviour of) a number of domain services:
 
 * xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_CommandContext[`CommandContext`]
@@ -18,7 +24,7 @@ The annotation works with (and is influenced by the behaviour of) a number of do
 * xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-spi_BackgroundCommandService[`BackgroundCommandService`]
 
 
-Each action invocation is reified by the xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_CommandContext[`CommandContext`] service into a `Command` object, capturing details of the target object, the action, the parameter arguments, the user, a timestamp and so on.
+Each action invocation is automatically reified by the xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_CommandContext[`CommandContext`] service into a `Command` object, capturing details of the target object, the action, the parameter arguments, the user, a timestamp and so on.
 
 If an appropriate `CommandService` is configured (for example using (non-ASF) link:http://platform.incode.org/modules/spi/command/spi-command.html[Incode Platform's command] module), then the `Command` itself is persisted.
 
@@ -32,79 +38,240 @@ If background ``Command``s are used, then an external scheduler, using xref:../u
 
 
 
-The `command()` attribute determines whether the action invocation should be reified into a `Command` object (by the xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_CommandContext[`CommandContext`] service).
-
-The default is `AS_CONFIGURED`, meaning that the xref:../rgcfg/rgcfg.adoc#_rgcfg_configuring-core[configuration property] `isis.services.command.actions` is used to determine whether the action invocation is reified:
-
-* `all` +
-+
-all action invocations are reified
-
-* `ignoreSafe` (or `ignoreQueryOnly`) +
-+
-invocations of actions with safe (read-only) semantics are ignored, but actions which may modify data are not ignored
-
-* `none` +
-+
-no action invocations are reified.
-
-If there is no configuration property in `isis.properties` then all action invocations are reified into ``Command``s.
-
-[NOTE]
-====
-Note: `Command` reification does not necessarily imply that `Command` objects will be persisted; that depends on whether there is a xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-spi_CommandService[`CommandService`] configured that will persist said ``Command``s.
-====
-
-This default can be overridden on an action-by-action basis; if `command()` is set to `ENABLED` then the action is reified irrespective of the configured value; if set to `DISABLED` then the action invocation is NOT reified irrespective of the configured value.
+[[_rgant-Action_commandPersistence]]
+== `command()` and `commandPersistence()`
+
+The `command()` and `commandPersistence() attributes work together to determine whether a command will actually be persisted.
+There inter-relationship is somewhat complex, so is probably best explained by way of examples:
+
+[cols="1a,1a,1a,1a,1a,2a", options="header"]
+|===
+
+| `command()`
+|`isis.services.
+command.actions` config property
+| action's declared `semantics()`
+| `command
+Persistence()`
+| action dirties objects?
+| is command persisted?
+
+| `ENABLED`
+| (any)
+| (any)
+| `PERSISTED`
+| (either)
+| yes
+
+| `ENABLED`
+| (any)
+| (any)
+| `IF_HINTED`
+| no
+| no
+
+| `ENABLED`
+| (any)
+| (any)
+| `IF_HINTED`
+| yes
+| yes
+
+| `ENABLED`
+| (any)
+| (any)
+| `NOT_PERSISTED`
+| (any)
+| no
+
+| `AS_CONFIGURED`
+| `all`
+| (any)
+| `PERSISTED`
+| no
+| yes
+
+| `AS_CONFIGURED`
+| `all`
+| (any)
+| `IF_HINTED`
+| no
+| no
+
+| `AS_CONFIGURED`
+| `all`
+| (any)
+| `IF_HINTED`
+| yes
+| yes
+
+| `AS_CONFIGURED`
+| `all`
+| (any)
+| `NOT_PERSISTED`
+| (any)
+| no
+
+| `AS_CONFIGURED`
+| `ignoreSafe` or `ignoreQueryOnly`
+| `SAFE`
+| `PERSISTED`
+| no
+| no (!)
+
+| `AS_CONFIGURED`
+| `ignoreSafe` or `ignoreQueryOnly`
+| `SAFE`
+| `IF_HINTED` or `NOT_PERSISTED`
+| no
+| no
+
+| `AS_CONFIGURED`
+| `ignoreSafe` or `ignoreQueryOnly`
+| `SAFE`
+| `PERSISTED` or `IF_HINTED`
+| yes
+| yes
+
+| `AS_CONFIGURED`
+| `ignoreSafe` or `ignoreQueryOnly`
+| `SAFE`
+| `NOT_PERSISTED`
+| yes
+| yes (!)
+
+| `AS_CONFIGURED`
+| `ignoreSafe` or `ignoreQueryOnly`
+| `IDEMPOTENT` or `NON_IDEMPOTENT`
+| `PERSISTED`
+| (any)
+| yes
+
+| `AS_CONFIGURED`
+| `ignoreSafe` or `ignoreQueryOnly`
+| `IDEMPOTENT` or `NON_IDEMPOTENT`
+| `IF_HINTED`
+| no
+| no
+
+| `AS_CONFIGURED`
+| `ignoreSafe` or `ignoreQueryOnly`
+| `IDEMPOTENT` or `NON_IDEMPOTENT`
+| `IF_HINTED`
+| yes
+| yes
+
+| `AS_CONFIGURED`
+| `ignoreSafe` or `ignoreQueryOnly`
+| `IDEMPOTENT` or `NON_IDEMPOTENT`
+| `NOT_PERSISTED`
+| (any)
+| no
+
+| `AS_CONFIGURED`
+| `none`
+| (any)
+| `PERSISTED`
+| no
+| no (!)
+
+| `AS_CONFIGURED`
+| `none`
+| (any)
+| `PERSISTED`
+| yes
+| yes
+
+| `AS_CONFIGURED`
+| `none`
+| (any)
+| `IF_HINTED`
+| no
+| no
+
+| `AS_CONFIGURED`
+| `none`
+| (any)
+| `IF_HINTED`
+| yes
+| yes
+
+| `AS_CONFIGURED`
+| `none`
+| (any)
+| `NOT_PERSISTED`
+| no
+| no
+
+| `AS_CONFIGURED`
+| `none`
+| (any)
+| `NOT_PERSISTED`
+| yes
+| yes (!)
+
+| `DISABLED`
+| (any)
+| (any)
+| `PERSISTED`
+| no
+| no (!)
+
+| `DISABLED`
+| (any)
+| (any)
+| `PERSISTED`
+| yes
+| yes
+
+| `DISABLED`
+| (any)
+| (any)
+| `IF_HINTED`
+| no
+| no
+
+| `DISABLED`
+| (any)
+| (any)
+| `IF_HINTED`
+| yes
+| yes
+
+| `DISABLED`
+| (any)
+| (any)
+| `NOT_PERSISTED`
+| no
+| no
+
+| `DISABLED`
+| (any)
+| (any)
+| `NOT_PERSISTED`
+| yes
+| yes (!)
+
+|===
 
 For example:
 
 [source,java]
 ----
 public class Order {
-    @Action(command=CommandReification.ENABLED)
-    public Invoice generateInvoice(...) { ... }
-}
-----
-
-corresponds to the behaviour described above; the `Command` object is persisted (assuming an appropriate `CommandService` is defined, and executed immediately in the foreground).
-
-
-
-
-== `commandPersistence()`
-
-If the action invocation has been reified, then the `commandPersistence()` attribute determines whether that `Command` object should then also be persisted (the default), or not persisted, or only if hinted.
-
-To explain this last alternative:
-
-[source,java]
-----
-public class Order {
     @Action(
         command=CommandReification.ENABLED,
-        commandPersistence=CommandPersistence.IF_HINTED
+        commandPersistence=CommandPersistence.PERSISTED
     )
     public Invoice generateInvoice(...) { ... }
 }
 ----
 
-will suppress the persistence of the `Command` object _unless_ a child background `Command` has been created in the body of the action by way of the xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_BackgroundService[`BackgroundService`].
-
-On the other hand:
+As can be seen, whether a command is actually persisted does not always follow the value of the `commandPersistence()` attribute.
+This is because the `command()` attribute actually determines whether any command metadata for the action is captured within the framework's internal metamodel.
+If `command` is `DISABLED` or does not otherwise apply due to the action's declared semantics, then the framework decides to persist a command based solely on whether the action dirtied any objects (as if `commandPersistence()` was set to `IF_HINTED`).
 
-[source,java]
-----
-public class Order {
-    @Action(
-        command=CommandReification.ENABLED,
-        commandPersistence=CommandPersistence.NOT_PERSISTED
-    )
-    public Invoice generateInvoice(...) { ... }
-}
-----
 
-will prevent the parent `Command` object from being persisted, _even if_ a child background `Command` is created.
 
 
 
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Property_command.adoc b/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Property_command.adoc
index 99be07d..ecfc3b7 100644
--- a/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Property_command.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Property_command.adoc
@@ -1,14 +1,16 @@
 [[_rgant-Property_command]]
-= `command()`
+= Command Persistence and Processing
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 :_basedir: ../../
 :_imagesdir: images/
 
 
-The `@Property(command=...)` attribute (and the related `@Property(commandXxx=...)` attributes) allows a property edit to be made into a concrete object such that it can be inspected and persisted.
-The primary use case for this are to support the deferring the execution of the action such that it can be invoked in the background, and to replay commands in a master/slave configuration.
+Every property edit (and action invocation for that matter) is automatically reified into a concrete `Command` object.
+The `@Property(command=..., commandXxx=...)` attributes provide hints for the persistence of that `Command` object, and the subsequent processing of that persisted command.
+The primary use cases for this are to support the deferring the execution of the action such that it can be invoked in the background, and to replay commands in a master/slave configuration.
 
 
+== Design
 
 The annotation works with (and is influenced by the behaviour of) a number of domain services:
 
@@ -18,7 +20,7 @@ The annotation works with (and is influenced by the behaviour of) a number of do
 * xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-spi_BackgroundCommandService[`BackgroundCommandService`]
 
 
-Each property edit is reified by the xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_CommandContext[`CommandContext`] service into a `Command` object, capturing details of the target object, the property, the proposed new value fo the property, the user, a timestamp and so on.
+Each property edit is automatically reified by the xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_CommandContext[`CommandContext`] service into a `Command` object, capturing details of the target object, the property, the proposed new value fo the property, the user, a timestamp and so on.
 
 If an appropriate `CommandService` is configured (for example using (non-ASF) link:http://platform.incode.org/modules/spi/command/spi-command.html[Incode Platform's command] module), then the `Command` itself is persisted.
 
@@ -30,86 +32,162 @@ If there is an implementation of `BackgroundCommandService` (as the (non-ASF) li
 If background ``Command``s are used, then an external scheduler, using xref:../ugbtb/ugbtb.adoc#_ugbtb_headless-access_BackgroundCommandExecution[headless access], must also be configured.
 ====
 
-
-
-The `command()` attribute determines whether the property edit should be reified into a `Command` object (by the xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_CommandContext[`CommandContext`] service).
-
-The default is `AS_CONFIGURED`, meaning that the xref:../rgcfg/rgcfg.adoc#_rgcfg_configuring-core[configuration property] `isis.services.command.properties` is used to determine whether the property edit is reified:
-
-* `all` +
-+
-all property edits are reified
-
-* `none` +
-+
-no property edits are reified.
-
-If there is no configuration property in `isis.properties` then all property edits are reified into ``Command``s.
-
-[NOTE]
-====
-Note: `Command` reification does not necessarily imply that `Command` objects will be persisted; that depends on whether there is a xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-spi_CommandService[`CommandService`] configured that will persist said ``Command``s.
-====
-
-This default can be overridden on an property-by-property basis; if `command()` is set to `ENABLED` then the action is reified irrespective of the configured value; if set to `DISABLED` then the property edit is NOT reified irrespective of the configured value.
+[[_rgant-Property_commandPersistence]]
+== `command()` and `commandPersistence()`
+
+The `command()` and `commandPersistence() attributes work together to determine whether a command will actually be persisted.
+There inter-relationship is somewhat complex, so is probably best explained by way of examples:
+
+[cols="1a,1a,1a,1a,2a", options="header"]
+|===
+
+| `command()`
+|`isis.services.
+command.properties` config property
+| `command
+Persistence()`
+| action dirties objects?
+| is command persisted?
+
+| `ENABLED`
+| (any)
+| `PERSISTED`
+| (either)
+| yes
+
+| `ENABLED`
+| (any)
+| `IF_HINTED`
+| no
+| no
+
+| `ENABLED`
+| (any)
+| `IF_HINTED`
+| yes
+| yes
+
+| `ENABLED`
+| (any)
+| `NOT_PERSISTED`
+| (any)
+| no
+
+| `AS_CONFIGURED`
+| `all`
+| `PERSISTED`
+| no
+| yes
+
+| `AS_CONFIGURED`
+| `all`
+| `IF_HINTED`
+| no
+| no
+
+| `AS_CONFIGURED`
+| `all`
+| `IF_HINTED`
+| yes
+| yes
+
+| `AS_CONFIGURED`
+| `all`
+| `NOT_PERSISTED`
+| (any)
+| no
+
+| `AS_CONFIGURED`
+| `none`
+| `PERSISTED`
+| no
+| no (!)
+
+| `AS_CONFIGURED`
+| `none`
+| `PERSISTED`
+| yes
+| yes
+
+| `AS_CONFIGURED`
+| `none`
+| `IF_HINTED`
+| no
+| no
+
+| `AS_CONFIGURED`
+| `none`
+| `IF_HINTED`
+| yes
+| yes
+
+| `AS_CONFIGURED`
+| `none`
+| `NOT_PERSISTED`
+| no
+| no
+
+| `AS_CONFIGURED`
+| `none`
+| `NOT_PERSISTED`
+| yes
+| yes (!)
+
+| `DISABLED`
+| (any)
+| `PERSISTED`
+| no
+| no (!)
+
+| `DISABLED`
+| (any)
+| `PERSISTED`
+| yes
+| yes
+
+| `DISABLED`
+| (any)
+| `IF_HINTED`
+| no
+| no
+
+| `DISABLED`
+| (any)
+| `IF_HINTED`
+| yes
+| yes
+
+| `DISABLED`
+| (any)
+| `NOT_PERSISTED`
+| no
+| no
+
+| `DISABLED`
+| (any)
+| `NOT_PERSISTED`
+| yes
+| yes (!)
+
+|===
 
 For example:
 
 [source,java]
 ----
 public class Order {
-    @Property(command=CommandReification.ENABLED)
-    public Product getProduct() { ... }
-    public void setProduct(Product p) { ... }
-}
-----
-
-corresponds to the behaviour described above; the `Command` object is persisted (assuming an appropriate `CommandService` is defined, and executed immediately in the foreground).
-
-
-
-
-== `commandPersistence()`
-
-If the property edit has been reified, then the `commandPersistence()` attribute determines whether that `Command` object should then also be persisted (the default), or not persisted, or only if hinted.
-
-To explain this last alternative:
-
-[source,java]
-----
-public class Order {
     @Property(
         command=CommandReification.ENABLED,
-        commandPersistence=CommandPersistence.IF_HINTED
+        commandPersistence=CommandPersistence.PERSISTED
     )
     public Product getProduct() { ... }
     public void setProduct(Product p) { ... }
 }
 ----
 
-will suppress the persistence of the `Command` object _unless_ a child background `Command` has been created in the body of the property by way of the xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_BackgroundService[`BackgroundService`].
-
-[NOTE]
-====
-Unlike actions, where this is quite feasible, it is rather unlikely to occur as a side-effect of editing a property.
-====
-
-On the other hand:
-
-[source,java]
-----
-public class Order {
-    @Property(
-        command=CommandReification.ENABLED,
-        commandPersistence=CommandPersistence.NOT_PERSISTED
-    )
-    public Product getProduct() { ... }
-    public void setProduct(Product p) { ... }
-}
-----
-
-will prevent the parent `Command` object from being persisted, _even if_ a child background `Command` is created.
-
+As can be seen, whether a command is actually persisted does not always follow the value of the `commandPersistence()` attribute.
+This is because the `command()` attribute actually determines whether any command metadata for the action is captured within the framework's internal metamodel.
+If `command` is `DISABLED` or does not otherwise apply due to the action's declared semantics, then the framework decides to persist a command based solely on whether the action dirtied any objects (as if `commandPersistence()` was set to `IF_HINTED`).
 
 
 

-- 
To stop receiving notification emails like this one, please contact
danhaywood@apache.org.