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/01/29 23:16:33 UTC

[isis] branch ISIS-1569-replay-commands updated (ce192de -> 9996eab)

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

danhaywood pushed a change to branch ISIS-1569-replay-commands
in repository https://gitbox.apache.org/repos/asf/isis.git.


    from ce192de  ISIS-1569: renames MetaModelService5 API from commandDtoProcessorFor() to commandWithDtoProcessorFor()
     new 19dfb53  ISIS-1569: fixes issue to fail-fast.
     new 20458aa  ISIS-1822: fixes NPE if encounters non-existent action in menubars.layout.xml
     new 85ef278  ISIS-1569: also catches exception when attempt to commit.
     new 9996eab  ISIS-1569: renames CommandWithDtoProcessor to CommandDtoProcessor ...

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../main/asciidoc/guides/rgant/_rgant-Action.adoc  |   6 +
 .../guides/rgant/_rgant-Action_command.adoc        |  76 +++++-----
 .../asciidoc/guides/rgant/_rgant-Property.adoc     |  28 ++++
 ...n_command.adoc => _rgant-Property_command.adoc} | 159 +++++++--------------
 .../guides/rgcms/_rgcms_schema-common.adoc         |  77 +++++++++-
 .../_rgsvc_metadata-api_MetamodelService.adoc      |   4 +-
 ...esentation-layer-spi_ContentMappingService.adoc |   9 +-
 .../org/apache/isis/applib/annotation/Action.java  |   6 +-
 .../apache/isis/applib/annotation/Property.java    |   6 +-
 .../conmap/ContentMappingServiceForCommandDto.java |  10 +-
 ...hDtoProcessor.java => CommandDtoProcessor.java} |  12 +-
 ...a => CommandDtoProcessorForActionAbstract.java} |   2 +-
 ...=> CommandDtoProcessorForPropertyAbstract.java} |   4 +-
 .../services/metamodel/MetaModelService5.java      |   4 +-
 .../command/CommandFacetForActionAnnotation.java   |  10 +-
 .../facets/actions/command/CommandFacet.java       |   4 +-
 .../actions/command/CommandFacetAbstract.java      |  18 +--
 .../command/CommandFacetForPropertyAnnotation.java |  10 +-
 .../metamodel/MetaModelServiceDefault.java         |   4 +-
 .../background/BackgroundCommandExecution.java     |  95 +++++++++---
 .../org/apache/isis/schema/common/common-1.1.xsd   |   4 -
 .../serviceactions/ServiceActionUtil.java          |   4 +
 22 files changed, 338 insertions(+), 214 deletions(-)
 copy adocs/documentation/src/main/asciidoc/guides/rgant/{_rgant-Action_command.adoc => _rgant-Property_command.adoc} (51%)
 rename core/applib/src/main/java/org/apache/isis/applib/services/command/{CommandWithDtoProcessor.java => CommandDtoProcessor.java} (81%)
 rename core/applib/src/main/java/org/apache/isis/applib/services/command/{CommandWithDtoProcessorForActionAbstract.java => CommandDtoProcessorForActionAbstract.java} (94%)
 rename core/applib/src/main/java/org/apache/isis/applib/services/command/{CommandWithDtoProcessorForPropertyAbstract.java => CommandDtoProcessorForPropertyAbstract.java} (92%)

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

[isis] 01/04: ISIS-1569: fixes issue to fail-fast.

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch ISIS-1569-replay-commands
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 19dfb5324cf32c9fd1015ab01308439fe313d76b
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Mon Jan 29 14:23:43 2018 +0000

    ISIS-1569: fixes issue to fail-fast.
---
 .../background/BackgroundCommandExecution.java     | 23 +++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java
index ec2ee0e..b408af3 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java
@@ -50,6 +50,7 @@ import org.apache.isis.core.runtime.sessiontemplate.AbstractIsisSessionTemplate;
 import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
 import org.apache.isis.core.runtime.system.transaction.TransactionalClosure;
+import org.apache.isis.core.runtime.system.transaction.TransactionalClosureWithReturn;
 import org.apache.isis.schema.cmd.v1.ActionDto;
 import org.apache.isis.schema.cmd.v1.CommandDto;
 import org.apache.isis.schema.cmd.v1.MemberDto;
@@ -116,7 +117,12 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
         LOG.info("Found {} to execute", backgroundCommands.size());
 
         for (final Command backgroundCommand : backgroundCommands) {
-            execute(transactionManager, backgroundCommand);
+            final boolean shouldContinue = execute(transactionManager, backgroundCommand);
+            if(!shouldContinue) {
+                LOG.info("OnExceptionPolicy is to QUIT, so skipping further processing",
+                        backgroundCommand.getMemberIdentifier());
+                return;
+            }
         }
     }
 
@@ -128,15 +134,15 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
     // //////////////////////////////////////
 
     
-    private void execute(
+    private boolean execute(
             final IsisTransactionManager transactionManager,
             final Command backgroundCommand) {
 
-        transactionManager.executeWithinTransaction(
+        return transactionManager.executeWithinTransaction(
                 backgroundCommand,
-                new TransactionalClosure() {
+                new TransactionalClosureWithReturn<Boolean>() {
             @Override
-            public void execute() {
+            public Boolean execute() {
 
                 // setup for us by IsisTransactionManager; will have the transactionId of the backgroundCommand
                 final Interaction backgroundInteraction = interactionContext.getInteraction();
@@ -291,10 +297,9 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
                 backgroundCommand.setCompletedAt(completedAt);
 
                 // if we hit an exception processing this command, then quit if instructed
-                if(exceptionIfAny != null && onExceptionPolicy == OnExceptionPolicy.QUIT) {
-                    LOG.info("OnExceptionPolicy is to QUIT, so skipping further processing", backgroundCommand.getMemberIdentifier());
-                    return;
-                }
+                final boolean shouldQuit = exceptionIfAny != null && onExceptionPolicy == OnExceptionPolicy.QUIT;
+                final boolean shouldContinue = !shouldQuit;
+                return shouldContinue;
 
             }
 

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

[isis] 02/04: ISIS-1822: fixes NPE if encounters non-existent action in menubars.layout.xml

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch ISIS-1569-replay-commands
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 20458aaf95fbd6293d03023f58fb59dd4a8ee89c
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Mon Jan 29 15:16:05 2018 +0000

    ISIS-1822: fixes NPE if encounters non-existent action in menubars.layout.xml
---
 .../ui/components/actionmenu/serviceactions/ServiceActionUtil.java    | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
index 0ba7e42..c4bdca4 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
@@ -234,6 +234,10 @@ public final class ServiceActionUtil {
                     final Bookmark bookmark = new Bookmark(objectType, PersistenceSession.SERVICE_IDENTIFIER);
                     final String oid = bookmark.toString();
                     final ObjectAdapter serviceAdapter = serviceAdapterByOid.get(oid);
+                    if(serviceAdapter == null) {
+                        // service not recognised, presumably the menu layout is out of sync with actual configured modules
+                        continue;
+                    }
                     final EntityModel entityModel = new EntityModel(serviceAdapter);
                     final ObjectAction objectAction = serviceAdapter.getSpecification()
                             .getObjectAction(actionLayoutData.getId());

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

[isis] 03/04: ISIS-1569: also catches exception when attempt to commit.

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch ISIS-1569-replay-commands
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 85ef278081983e751a6b7f48405e3725a7ed04dc
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Mon Jan 29 18:06:28 2018 +0000

    ISIS-1569: also catches exception when attempt to commit.
---
 .../background/BackgroundCommandExecution.java     | 78 ++++++++++++++++++----
 1 file changed, 65 insertions(+), 13 deletions(-)

diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java
index b408af3..4c4ea88 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java
@@ -114,9 +114,10 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
             }
         });
 
-        LOG.info("Found {} to execute", backgroundCommands.size());
+        LOG.debug("{}: Found {} to execute", getClass().getName(), backgroundCommands.size());
 
         for (final Command backgroundCommand : backgroundCommands) {
+
             final boolean shouldContinue = execute(transactionManager, backgroundCommand);
             if(!shouldContinue) {
                 LOG.info("OnExceptionPolicy is to QUIT, so skipping further processing",
@@ -138,6 +139,47 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
             final IsisTransactionManager transactionManager,
             final Command backgroundCommand) {
 
+        try {
+            return executeWithinTran(transactionManager, backgroundCommand);
+        } catch (final RuntimeException ex) {
+
+            // attempting to commit the xactn itself could cause an issue
+            // so we need extra exception handling here, it seems.
+
+            org.apache.isis.applib.annotation.Command.ExecuteIn executeIn = backgroundCommand.getExecuteIn();
+            LOG.warn("Exception when committing for: {} {}", executeIn, backgroundCommand.getMemberIdentifier(), ex);
+
+            //
+            // the previous transaction will have been aborted as part of the recovery handling within
+            // TransactionManager's executeWithinTran
+            //
+            // we therefore start a new xactn in order to make sure that this background command is marked as a failure
+            // so it won't be attempted again.
+            //
+            transactionManager.executeWithinTransaction(new TransactionalClosure(){
+                @Override
+                public void execute() {
+
+                    final Interaction backgroundInteraction = interactionContext.getInteraction();
+                    final Interaction.Execution currentExecution = backgroundInteraction.getCurrentExecution();
+                    backgroundCommand.setStartedAt(
+                            currentExecution != null
+                                    ? currentExecution.getStartedAt()
+                                    : clockService.nowAsJavaSqlTimestamp());
+
+                    backgroundCommand.setCompletedAt(clockService.nowAsJavaSqlTimestamp());
+                    backgroundCommand.setException(Throwables.getStackTraceAsString(ex));
+                }
+            });
+
+            return determineIfContinue(ex);
+        }
+    }
+
+    private Boolean executeWithinTran(
+            final IsisTransactionManager transactionManager,
+            final Command backgroundCommand) {
+
         return transactionManager.executeWithinTransaction(
                 backgroundCommand,
                 new TransactionalClosureWithReturn<Boolean>() {
@@ -162,11 +204,18 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
                     // thrown then we would have a command with only completedAt, which is inconsistent.
                     // Therefore instead we copy down from the backgroundInteraction (similar to how we populate the
                     // completedAt at the end)
-                    final Interaction.Execution currentExecution = backgroundInteraction.getCurrentExecution();
-                    backgroundCommand.setStartedAt(
-                            currentExecution != null
-                                    ? currentExecution.getStartedAt()
-                                    : clockService.nowAsJavaSqlTimestamp());
+                    final Interaction.Execution priorExecution = backgroundInteraction.getPriorExecution();
+
+                    final Timestamp startedAt = priorExecution != null
+                            ? priorExecution.getStartedAt()
+                            : clockService.nowAsJavaSqlTimestamp();
+                    final Timestamp completedAt =
+                            priorExecution != null
+                                    ? priorExecution.getCompletedAt()
+                                    : clockService.nowAsJavaSqlTimestamp();  // close enough...
+
+                    backgroundCommand.setStartedAt(startedAt);
+                    backgroundCommand.setCompletedAt(completedAt);
 
                     final boolean legacy = memento.startsWith("<memento");
                     if(legacy) {
@@ -267,15 +316,15 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
 
                     }
 
-                } catch (RuntimeException e) {
+                } catch (RuntimeException ex) {
 
-                    LOG.warn("Exception for: {}, e", backgroundCommand.getMemberIdentifier(), e);
+                    LOG.warn("Exception for: {} {}", executeIn, backgroundCommand.getMemberIdentifier(), ex);
 
                     // hmmm, this doesn't really make sense if >1 action
                     //
                     // in any case, the capturing of the result of the action invocation should be the
                     // responsibility of the interaction...
-                    backgroundCommand.setException(Throwables.getStackTraceAsString(e));
+                    backgroundCommand.setException(Throwables.getStackTraceAsString(ex));
 
                     // lower down the stack the IsisTransactionManager will have set the transaction to abort
                     // however, we don't want that to occur (because any changes made to the backgroundCommand itself
@@ -284,7 +333,7 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
                     transactionManager.getCurrentTransaction().clearAbortCauseAndContinue();
 
                     // checked at the end
-                    exceptionIfAny = e;
+                    exceptionIfAny = ex;
                 }
 
                 // it's possible that there is no priorExecution, specifically if there was an exception
@@ -297,9 +346,7 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
                 backgroundCommand.setCompletedAt(completedAt);
 
                 // if we hit an exception processing this command, then quit if instructed
-                final boolean shouldQuit = exceptionIfAny != null && onExceptionPolicy == OnExceptionPolicy.QUIT;
-                final boolean shouldContinue = !shouldQuit;
-                return shouldContinue;
+                return determineIfContinue(exceptionIfAny);
 
             }
 
@@ -332,6 +379,11 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
         });
     }
 
+    private boolean determineIfContinue(final RuntimeException exceptionIfAny) {
+        final boolean shouldQuit = exceptionIfAny != null && onExceptionPolicy == BackgroundCommandExecution.OnExceptionPolicy.QUIT;
+        return !shouldQuit;
+    }
+
     protected ObjectAdapter newValueAdapterFor(final PropertyDto propertyDto) {
         final ValueWithTypeDto newValue = propertyDto.getNewValue();
         final Object arg = CommonDtoUtils.getValue(newValue);

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

[isis] 04/04: ISIS-1569: renames CommandWithDtoProcessor to CommandDtoProcessor ...

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch ISIS-1569-replay-commands
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 9996eabad5ce39eb68217b43d418bf2cfed2654a
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Mon Jan 29 23:15:35 2018 +0000

    ISIS-1569: renames CommandWithDtoProcessor to CommandDtoProcessor ...
    
    ... and updates docs
---
 .../main/asciidoc/guides/rgant/_rgant-Action.adoc  |   6 +
 .../guides/rgant/_rgant-Action_command.adoc        |  76 +++++-----
 .../asciidoc/guides/rgant/_rgant-Property.adoc     |  28 ++++
 ...n_command.adoc => _rgant-Property_command.adoc} | 159 +++++++--------------
 .../guides/rgcms/_rgcms_schema-common.adoc         |  77 +++++++++-
 .../_rgsvc_metadata-api_MetamodelService.adoc      |   4 +-
 ...esentation-layer-spi_ContentMappingService.adoc |   9 +-
 .../org/apache/isis/applib/annotation/Action.java  |   6 +-
 .../apache/isis/applib/annotation/Property.java    |   6 +-
 .../conmap/ContentMappingServiceForCommandDto.java |  10 +-
 ...hDtoProcessor.java => CommandDtoProcessor.java} |  12 +-
 ...a => CommandDtoProcessorForActionAbstract.java} |   2 +-
 ...=> CommandDtoProcessorForPropertyAbstract.java} |   4 +-
 .../services/metamodel/MetaModelService5.java      |   4 +-
 .../command/CommandFacetForActionAnnotation.java   |  10 +-
 .../facets/actions/command/CommandFacet.java       |   4 +-
 .../actions/command/CommandFacetAbstract.java      |  18 +--
 .../command/CommandFacetForPropertyAnnotation.java |  10 +-
 .../metamodel/MetaModelServiceDefault.java         |   4 +-
 .../org/apache/isis/schema/common/common-1.1.xsd   |   4 -
 20 files changed, 258 insertions(+), 195 deletions(-)

diff --git a/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Action.adoc b/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Action.adoc
index 3b8f5c9..3d0c422 100644
--- a/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Action.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Action.adoc
@@ -37,6 +37,12 @@ The table below summarizes the annotation's attributes.
 |whether the reified `Command` (as provided by the `CommandContext` domain service) should actually be persisted (assuming an appropriate implementation of xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-spi_CommandService[`CommandService`] has been configured).
 
 
+|`commandDtoProcessor()`
+|Implementation of `CommandDtoProcessor` interface +
+(null)
+|If the `Command` also implements `CommandWithDto` (meaning that it can return a `CommandDto`, in other words be converted into an XML memento), then optionally specifies a processor that can refine this XML.
+
+
 |xref:../rgant/rgant.adoc#_rgant-Action_domainEvent[`domainEvent()`]
 |subtype of `ActionDomainEvent` +
 (`ActionDomainEvent.Default`)
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 cf2a952..9665b22 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
@@ -5,7 +5,7 @@
 :_imagesdir: images/
 
 
-The `@Action(command=...)` attribute (and the related `@Action(commandPersistence=...)` and  `@Action(commandExecuteIn=...)` attributes) allows an action invocation to be made into a concrete object such that it can be inspected and persisted.
+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.
 
 
@@ -34,28 +34,28 @@ 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 the whether the action is reified:
+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 actions are reified
+all action invocations are reified
 
 * `ignoreSafe` (or `ignoreQueryOnly`) +
 +
-actions with safe (read-only) semantics are ignored, but actions which may modify data are not ignored
+invocations of actions with safe (read-only) semantics are ignored, but actions which may modify data are not ignored
 
 * `none` +
 +
-no actions are reified.
+no action invocations are reified.
 
-If there is no configuration property in `isis.properties` then all actions are reified into ``Command``s.
+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 is NOT reified irrespective of the configured value.
+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.
 
 For example:
 
@@ -74,7 +74,7 @@ corresponds to the behaviour described above; the `Command` object is persisted
 
 == `commandPersistence()`
 
-If the action 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.
+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:
 
@@ -98,7 +98,6 @@ On the other hand:
 public class Order {
     @Action(
         command=CommandReification.ENABLED,
-        commandExecuteIn=CommandExecuteIn.FOREGROUND,
         commandPersistence=CommandPersistence.NOT_PERSISTED
     )
     public Invoice generateInvoice(...) { ... }
@@ -123,47 +122,61 @@ For example:
 public class Order {
     @Action(
         command=CommandReification.ENABLED,
-        commandExecuteIn=CommandExecuteIn.BACKGROUND)
+        commandExecuteIn=CommandExecuteIn.BACKGROUND
+    )
     public Invoice generateInvoice(...) { ... }
 }
 ----
 
 will result in the `Command` being persisted but its execution deferred to a background execution mechanism.
-The returned object from this action is the persisted `Command` itself.
+The returned object from this action invocation is the persisted `Command` itself.
 
 
 
 
-== `commandWithDtoProcessor()`
+== `commandDtoProcessor()`
 
-The `commandWithDtoProcessor()` attribute allows an implementation of `CommandWithDtoProcessor` to be specified.
-This has the following API:
+The `commandDtoProcessor()` attribute allows an implementation of `CommandDtoProcessor` to be specified.
+This interface has the following API:
 
 [source,java]
 ----
-public interface CommandWithDtoProcessor {
-    CommandDto process(CommandWithDto commandWithDto);
+public interface CommandDtoProcessor {
+    CommandDto process(             // <1>
+            Command command,        // <2>
+            CommandDto dto);        // <3>
 }
 ----
+<1> The returned `CommandDto`.
+This will typically be the `CommandDto` passed in, but supplemented in some way.
+<2> The `Command` being processed
+<3> The `CommandDto` (XML) obtained already from the `Command` (by virtue of it also implementing `CommandWithDto`, see discussion below).
 
 This interface is used by the framework-provided implementations of `ContentMappingService` for the REST API, allowing ``Command``s implementations that also implement `CommandWithDto` to be further customised as they are serialized out.
 The primary use case for this capability is in support of master/slave replication.
 
 * on the master, ``Command``s are serialized to XML.
-This includes the identity of the target object and the value of all parameters.
+This includes the identity of the target object and the argument values of all parameters.
+
++
+[IMPORTANT]
+====
 However, any ``Blob``s and ``Clob``s are deliberately excluded from this XML (they are instead stored as references).
+This is to prevent the storage requirements for `Command` from becoming excessive.
+A `CommandDtoProcessor` can be provided to re-attach blob information if required.
+====
 
 * replaying ``Command``s requires this missing parameter information to be reinstated.
-The `CommandWithDtoProcessor` therefore offers a hook to dynamically re-attach the missing `Blob` or `Clob` argument.
+The `CommandDtoProcessor` therefore offers a hook to dynamically re-attach the missing `Blob` or `Clob` argument.
 
 
 As a special case, returning `null` means that the command's DTO is effectively excluded when retrieving the list of commands.
 If replicating from master to slave, this effectively allows certain commands to be ignored.
-The `CommandWithDtoProcessor.Null` class provides a convenience implementation for this requirement.
+The `CommandDtoProcessor.Null` class provides a convenience implementation for this requirement.
 
 [NOTE]
 ====
-If `commandWithDtoProcessor()` is specified, then `command()` is assumed to be ENABLED.
+If `commandDtoProcessor()` is specified, then `command()` is assumed to be ENABLED.
 ====
 
 
@@ -176,7 +189,7 @@ Consider the following method:
 ----
 @Action(
     domainEvent = IncomingDocumentRepository.UploadDomainEvent.class,
-    commandWithDtoProcessor = DeriveBlobArg0FromReturnedDocument.class
+    commandDtoProcessor = DeriveBlobArg0FromReturnedDocument.class
 )
 public Document upload(final Blob blob) {
     final String name = blob.getName();
@@ -196,11 +209,10 @@ The `DeriveBlobArg0FromReturnedDocument` processor retrieves this information an
 [source,java]
 ----
 public class DeriveBlobArg0FromReturnedDocument
-        extends CommandWithDtoProcessorForActionAbstract {
+        extends CommandDtoProcessorForActionAbstract {
 
     @Override
-    public CommandDto process(final CommandWithDto commandWithDto) {
-        final CommandDto commandDto = commandWithDto.asDto();
+    public CommandDto process(Command command, CommandDto commandDto) {
         final Bookmark result = commandWithDto.getResult();
         if(result == null) {
             return commandDto;
@@ -224,19 +236,17 @@ public class DeriveBlobArg0FromReturnedDocument
 
 === Null implementation
 
-
+The null implementation can be used to simply indicate that no DTO should be returned for a `Command`.
+The effect is to ignore it for replay purposes:
 
 [source,xml]
 ----
-    /**
-     * Convenience implementation to simply indicate that no DTO should be returned for a command,
-     * effectively ignoring it for replay purposes.
-     */
-    public static class Null implements CommandWithDtoProcessor {
-        @Override
-        public CommandDto process(final CommandWithDto commandWithDto) {
+pubc interface CommandDtoProcessor {
+    ...
+    class Null implements CommandDtoProcessor {
+        public CommandDto process(Command command, CommandDto commandDto) {
             return null;
         }
     }
-
+}
 ----
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Property.adoc b/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Property.adoc
index bda8795..2fb9f1a 100644
--- a/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Property.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Property.adoc
@@ -20,6 +20,33 @@ It is also possible to apply the annotation to actions of domain services that a
 | Description
 
 
+|xref:../rgant/rgant.adoc#_rgant-Property_command[`command()`]
+|`AS_CONFIGURED`, `ENABLED`, `DISABLED` +
+(`AS_CONFIGURED`)
+|whether the property edit should be reified into a `o.a.i.applib.` +
+`services.command.Command` object through the xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_CommandContext[`CommandContext`] service.
+
+
+|`commandExecuteIn()`
+|`FOREGROUND`,`BACKGROUND` +
+(`FOREGROUND`)
+|whether to execute the command immediately, or to persist it (assuming that an appropriate implementation of xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-spi_CommandService[`CommandService`] has been configured) such that a background scheduler can execute the command asynchronously
+
+
+|`commandPersistence()`
+|`PERSISTED`, `NOT_PERSISTED`, `IF_HINTED` +
+(`PERSISTED`)
+|whether the reified `Command` (as provided by the `CommandContext` domain service) should actually be persisted (assuming an appropriate implementation of xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-spi_CommandService[`CommandService`] has been configured).
+
+
+
+|`commandDtoProcessor()`
+|Implementation of `CommandDtoProcessor` interface +
+(null)
+|If the `Command` also implements `CommandWithDto` (meaning that it can return a `CommandDto`, in other words be converted into an XML memento), then optionally specifies a processor that can refine this XML.
+
+
+
 |xref:../rgant/rgant.adoc#_rgant-Property_domainEvent[`domainEvent()`]
 |subtype of `PropertyDomainEvent` +
 (`PropertyDomainEvent.Default`)
@@ -129,6 +156,7 @@ so that boilerplate-busting tools such as link:https://projectlombok.org/[Projec
 ====
 
 
+include::_rgant-Property_command.adoc[leveloffset=+1]
 include::_rgant-Property_domainEvent.adoc[leveloffset=+1]
 include::_rgant-Property_editing.adoc[leveloffset=+1]
 include::_rgant-Property_fileAccept.adoc[leveloffset=+1]
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Action_command.adoc b/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Property_command.adoc
similarity index 51%
copy from adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Action_command.adoc
copy to adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Property_command.adoc
index cf2a952..99be07d 100644
--- a/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Action_command.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Property_command.adoc
@@ -1,11 +1,11 @@
-[[_rgant-Action_command]]
+[[_rgant-Property_command]]
 = `command()`
 :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(commandPersistence=...)` and  `@Action(commandExecuteIn=...)` attributes) allows an action invocation to be made into a concrete object such that it can be inspected and persisted.
+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.
 
 
@@ -18,7 +18,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 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.
 
 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,38 +32,35 @@ 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 `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.actions` is used to determine the whether the action is reified:
+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 actions are reified
-
-* `ignoreSafe` (or `ignoreQueryOnly`) +
-+
-actions with safe (read-only) semantics are ignored, but actions which may modify data are not ignored
+all property edits are reified
 
 * `none` +
 +
-no actions are reified.
+no property edits are reified.
 
-If there is no configuration property in `isis.properties` then all actions are reified into ``Command``s.
+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 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 is NOT reified irrespective of the configured value.
+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.
 
 For example:
 
 [source,java]
 ----
 public class Order {
-    @Action(command=CommandReification.ENABLED)
-    public Invoice generateInvoice(...) { ... }
+    @Property(command=CommandReification.ENABLED)
+    public Product getProduct() { ... }
+    public void setProduct(Product p) { ... }
 }
 ----
 
@@ -74,34 +71,40 @@ corresponds to the behaviour described above; the `Command` object is persisted
 
 == `commandPersistence()`
 
-If the action 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.
+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 {
-    @Action(
+    @Property(
         command=CommandReification.ENABLED,
         commandPersistence=CommandPersistence.IF_HINTED
     )
-    public Invoice generateInvoice(...) { ... }
+    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 action by way of the xref:../rgsvc/rgsvc.adoc#_rgsvc_application-layer-api_BackgroundService[`BackgroundService`].
+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 {
-    @Action(
+    @Property(
         command=CommandReification.ENABLED,
-        commandExecuteIn=CommandExecuteIn.FOREGROUND,
         commandPersistence=CommandPersistence.NOT_PERSISTED
     )
-    public Invoice generateInvoice(...) { ... }
+    public Product getProduct() { ... }
+    public void setProduct(Product p) { ... }
 }
 ----
 
@@ -121,122 +124,68 @@ For example:
 [source,java]
 ----
 public class Order {
-    @Action(
+    @Property(
         command=CommandReification.ENABLED,
-        commandExecuteIn=CommandExecuteIn.BACKGROUND)
-    public Invoice generateInvoice(...) { ... }
+        commandExecuteIn=CommandExecuteIn.BACKGROUND
+    )
+    public Product getProduct() { ... }
+    public void setProduct(Product p) { ... }
 }
 ----
 
 will result in the `Command` being persisted but its execution deferred to a background execution mechanism.
-The returned object from this action is the persisted `Command` itself.
+The returned object from this property edit is the persisted `Command` itself.
 
 
 
 
-== `commandWithDtoProcessor()`
+== `commandDtoProcessor()`
 
-The `commandWithDtoProcessor()` attribute allows an implementation of `CommandWithDtoProcessor` to be specified.
-This has the following API:
+The `commandDtoProcessor()` attribute allows an implementation of `CommandDtoProcessor` to be specified.
+This interface has the following API:
 
 [source,java]
 ----
-public interface CommandWithDtoProcessor {
-    CommandDto process(CommandWithDto commandWithDto);
+public interface CommandDtoProcessor {
+    CommandDto process(             // <1>
+            Command command,        // <2>
+            CommandDto dto);        // <3>
 }
 ----
+<1> The returned `CommandDto`.
+This will typically be the `CommandDto` passed in, but supplemented in some way.
+<2> The `Command` being processed
+<3> The `CommandDto` (XML) obtained already from the `Command` (by virtue of it also implementing `CommandWithDto`, see discussion below).
 
 This interface is used by the framework-provided implementations of `ContentMappingService` for the REST API, allowing ``Command``s implementations that also implement `CommandWithDto` to be further customised as they are serialized out.
 The primary use case for this capability is in support of master/slave replication.
 
 * on the master, ``Command``s are serialized to XML.
-This includes the identity of the target object and the value of all parameters.
+This includes the identity of the target object and the intended new value of the property.
+
++
+[IMPORTANT]
+====
 However, any ``Blob``s and ``Clob``s are deliberately excluded from this XML (they are instead stored as references).
+This is to prevent the storage requirements for `Command` from becoming excessive.
+A `CommandDtoProcessor` can be provided to re-attach blob information if required.
+====
 
 * replaying ``Command``s requires this missing parameter information to be reinstated.
-The `CommandWithDtoProcessor` therefore offers a hook to dynamically re-attach the missing `Blob` or `Clob` argument.
+The `CommandDtoProcessor` therefore offers a hook to dynamically re-attach the missing `Blob` or `Clob` argument.
 
 
 As a special case, returning `null` means that the command's DTO is effectively excluded when retrieving the list of commands.
 If replicating from master to slave, this effectively allows certain commands to be ignored.
-The `CommandWithDtoProcessor.Null` class provides a convenience implementation for this requirement.
+The `CommandDtoProcessor.Null` class provides a convenience implementation for this requirement.
 
 [NOTE]
 ====
-If `commandWithDtoProcessor()` is specified, then `command()` is assumed to be ENABLED.
+If `commandDtoProcessor()` is specified, then `command()` is assumed to be ENABLED.
 ====
 
 
 
-=== Example implementation
+For an example application, see xref:rgant.adoc#_rgant-Action_command[`Action#command()`].
 
-Consider the following method:
 
-[source,java]
-----
-@Action(
-    domainEvent = IncomingDocumentRepository.UploadDomainEvent.class,
-    commandWithDtoProcessor = DeriveBlobArg0FromReturnedDocument.class
-)
-public Document upload(final Blob blob) {
-    final String name = blob.getName();
-    final DocumentType type = DocumentTypeData.INCOMING.findUsing(documentTypeRepository);
-    final ApplicationUser me = meService.me();
-    String atPath = me != null ? me.getAtPath() : null;
-    if (atPath == null) {
-        atPath = "/";
-    }
-    return incomingDocumentRepository.upsertAndArchive(type, atPath, name, blob);
-}
-----
-
-The `Blob` argument will not be persisted in the memento of the `Command`, but the information is implicitly available in the `Document` that is returned by the action.
-The `DeriveBlobArg0FromReturnedDocument` processor retrieves this information and dynamically adds:
-
-[source,java]
-----
-public class DeriveBlobArg0FromReturnedDocument
-        extends CommandWithDtoProcessorForActionAbstract {
-
-    @Override
-    public CommandDto process(final CommandWithDto commandWithDto) {
-        final CommandDto commandDto = commandWithDto.asDto();
-        final Bookmark result = commandWithDto.getResult();
-        if(result == null) {
-            return commandDto;
-        }
-        try {
-            final Document document = bookmarkService.lookup(result, Document.class);
-            if (document != null) {
-                ParamDto paramDto = getParamDto(commandDto, 0);
-                CommonDtoUtils.setValueOn(paramDto, ValueType.BLOB, document.getBlob(), bookmarkService);
-            }
-        } catch(Exception ex) {
-            return commandDto;
-        }
-        return commandDto;
-    }
-    @Inject
-    BookmarkService bookmarkService;
-}
-----
-
-
-=== Null implementation
-
-
-
-[source,xml]
-----
-    /**
-     * Convenience implementation to simply indicate that no DTO should be returned for a command,
-     * effectively ignoring it for replay purposes.
-     */
-    public static class Null implements CommandWithDtoProcessor {
-        @Override
-        public CommandDto process(final CommandWithDto commandWithDto) {
-            return null;
-        }
-    }
-
-----
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgcms/_rgcms_schema-common.adoc b/adocs/documentation/src/main/asciidoc/guides/rgcms/_rgcms_schema-common.adoc
index 9e2a9dc..1bda81c 100644
--- a/adocs/documentation/src/main/asciidoc/guides/rgcms/_rgcms_schema-common.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/rgcms/_rgcms_schema-common.adoc
@@ -79,6 +79,28 @@ They are also used to represent references to any action arguments/properties th
 * third, as references to the target of an interaction capturing the actual execution of an action invocation or property edit, as described by the xref:../rgcms/rgcms.adoc#_rgcms_schema-ixn["ixn" (interaction)] schema.
 
 
+[[__rgcms_schema-common_collectionDto]]
+== `collectionDto` etc
+
+The `collectionDto` type defines a collection of values, also capturing the type of those values (for example ``string``s, or ``OidDto``s).
+It is used primarily to model invocations of actions with collection parameters.
+
+[source,xml]
+----
+<xs:schema targetNamespace="http://isis.apache.org/schema/common" ... >
+    ...
+    <xs:complexType name="collectionDto">
+        <xs:sequence>
+            <xs:element name="value" type="valueDto" minOccurs="1" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="type" use="required" type="valueType"/>
+        <xs:attribute name="null" use="optional" type="xs:boolean"/>
+    </xs:complexType>
+    ...
+</xs:schema>
+----
+
+
 [[__rgcms_schema-common_valueDto]]
 == `valueDto` etc
 
@@ -97,6 +119,9 @@ The common schema also defines two types representing values: the `valueDto` com
             <xs:element name="timestamp" type="xs:dateTime"/>
             <xs:element name="enum" type="enumDto"/>
             <xs:element name="reference" type="oidDto"/>
+            <xs:element name="collection" type="collectionDto"/>
+            <xs:element name="blob" type="blobDto"/>
+            <xs:element name="clob" type="clobDto"/>
         </xs:choice>
     </xs:complexType>
 
@@ -108,6 +133,9 @@ The common schema also defines two types representing values: the `valueDto` com
             ...
             <xs:enumeration value="enum"/>
             <xs:enumeration value="reference"/>
+            <xs:enumeration value="collection"/>
+            <xs:enumeration value="blob"/>
+            <xs:enumeration value="clob"/>
             <xs:enumeration value="void"/>                          <!--3-->
         </xs:restriction>
     </xs:simpleType>
@@ -135,6 +163,13 @@ The first, `valueDto` is The second, `valueType`, enumerates the different types
 formal parameter to an action.
 
 
+[IMPORTANT]
+====
+When used as a parameter, blob and clob arguments are _not_ serialized.
+Instead these are persisted only as references.
+This is primarily to save storage space if the resultant XML is persisted as a memento (eg `CommandDto`).
+====
+
 
 [[__rgcms_schema-common_ancillary]]
 == Ancillary types
@@ -152,7 +187,27 @@ The common schema also defines a number of ancillary types, used either by the c
         </xs:sequence>
     </xs:complexType>
 
-    <xs:complexType name="periodDto">                               <!--2-->
+    <xs:complexType name="blobDto">                                 <!--2-->
+        <xs:sequence>
+            <xs:element name="name" type="xs:string"/>
+            <xs:element name="mimeType" type="xs:string"/>
+            <xs:element name="bytes" type="xs:hexBinary"/>
+        </xs:sequence>
+        <xs:attribute name="type" use="required" type="valueType"/>
+        <xs:attribute name="null" use="optional" type="xs:boolean"/>
+    </xs:complexType>
+
+    <xs:complexType name="clobDto">                                 <!--3-->
+        <xs:sequence>
+            <xs:element name="name" type="xs:string"/>
+            <xs:element name="mimeType" type="xs:string"/>
+            <xs:element name="chars" type="xs:string"/>
+        </xs:sequence>
+        <xs:attribute name="type" use="required" type="valueType"/>
+        <xs:attribute name="null" use="optional" type="xs:boolean"/>
+    </xs:complexType>
+
+    <xs:complexType name="periodDto">                               <!--4-->
         <xs:sequence>
             <xs:element name="startedAt" type="xs:dateTime"/>
             <xs:element name="completedAt" type="xs:dateTime"
@@ -160,24 +215,34 @@ The common schema also defines a number of ancillary types, used either by the c
         </xs:sequence>
     </xs:complexType>
 
-    <xs:complexType name="differenceDto">                           <!--3-->
+    <xs:complexType name="differenceDto">                           <!--5-->
         <xs:sequence/>
         <xs:attribute name="before" type="xs:int"/>
         <xs:attribute name="after" type="xs:int"/>
     </xs:complexType>
 
-    <xs:simpleType name="interactionType">                          <!--4-->
+    <xs:simpleType name="interactionType">                          <!--6-->
         <xs:restriction base="xs:string">
             <xs:enumeration value="action_invocation" />
             <xs:enumeration value="property_edit" />
         </xs:restriction>
     </xs:simpleType>
+
+    <xs:complexType name="oidsDto">                                 <!--7-->
+        <xs:sequence>
+            <xs:element name="oid" type="oidDto" minOccurs="1" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+
 </xs:schema>
 ----
 <1> Models an instance member of an enum (eg `Color.RED`).
-<2> Captures a period of time, eg for capturing metrics/timings.
-<3> Captures a pair of numbers representing a difference.
+<2> Models a `Blob`
+<3> Models a `Clob`
+<4> Captures a period of time, eg for capturing metrics/timings.
+<5> Captures a pair of numbers representing a difference.
 Used for example to capture metrics (number objects modified before and after).
-<4> Whether this command/interaction with a member is invoking an action, or editing a property.
+<6> Whether this command/interaction with a member is invoking an action, or editing a property.
 Used by both the xref:../rgcms/rgcms.adoc#_rgcms_schema_cmd["cmd"] and xref:../rgcms/rgcms.adoc#_rgcms_schema_ixn["ixn"] schemas.
+<7> Contains a list of OIDs, eg for use in "bulk" actions that apply to multiple targets.
 
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_metadata-api_MetamodelService.adoc b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_metadata-api_MetamodelService.adoc
index 2166df6..b610a59 100644
--- a/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_metadata-api_MetamodelService.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_metadata-api_MetamodelService.adoc
@@ -45,7 +45,7 @@ public interface MetaModelService4 {
     AppManifest2 getAppManifest2();
 
     // introduced in MetaModelService5
-    CommandWithDtoProcessor commandWithDtoProcessorFor( // <8>
+    CommandDtoProcessor commandDtoProcessorFor(         // <8>
                         String memberIdentifier);
 
 }
@@ -58,7 +58,7 @@ public interface MetaModelService4 {
 <6> whether to throw an exception or return `Sort.UNKNOWN` if the object type is not recognized.  (The overloads with no `Mode` parameter default to strict mode).
 <7> returns the `AppManifest` used to bootstrap the application.
 If an `AppManifest2` was used (from a `Module`), then this is also returned (else just `null`).
-<8> obtain an implementation of `CommandWithDtoProcessor` (if any) as per an xref:../rgant/rgant.adoc#_rgant_Action_command[`@Action#commandWithDtoProcessor()`] or xref:../rgant/rgant.adoc#_rgant_Property_command[`@Property#commandWithDtoProcessor()`].
+<8> obtain an implementation of `CommandDtoProcessor` (if any) as per an xref:../rgant/rgant.adoc#_rgant_Action_command[`@Action#commandDtoProcessor()`] or xref:../rgant/rgant.adoc#_rgant_Property_command[`@Property#commandDtoProcessor()`].
 +
 This is used by the xref:rgsvc.adoc#_rgsvc_presentation-layer-spi_ContentMappingService_implementations[framework-provided implementations] of `ContentMappingService`.
 
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_presentation-layer-spi_ContentMappingService.adoc b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_presentation-layer-spi_ContentMappingService.adoc
index b98354a..f2ade47 100644
--- a/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_presentation-layer-spi_ContentMappingService.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/rgsvc/_rgsvc_presentation-layer-spi_ContentMappingService.adoc
@@ -54,7 +54,10 @@ For framework implementations of `ContentMappingService` allow domain service ac
 * `o.a.i.applib.conmap.ContentMappingServiceForCommandDto` will map any single instnce of a `CommandWithDto` into a `CommandDto` XML document
 * `o.a.i.applib.conmap.ContentMappingServiceForCommandsDto` will map list of ``CommandWithDto``s into a `CommandsDto` XML document, and will wrap any single instance of a `CommandWithDto` into a singleton list and thence into a `CommandsDto` XML document.
 
-The framework also provides `ContentMappingService.Util` which includes a couple of convenience utilities for implementations:
+If the action invocation or property edit represent provides an implementation of a `CommandDtoProcessor` (by way of xref:../rgant/rgant.adoc#_rgant_Action_command[`@Action#commandDtoProcessor()`] or xref:../rgant/rgant.adoc#_rgant_Property_command[`@Property#commandDtoProcessor()`]) then this is also called to post-process the persisted `CommandDto` if required.
+A typical use case for this is to dynamically add in serialized ``Blob``s or ``Clob``s, the values of which are not captured by default in `CommandDto`.
+
+To support the writing of custom implementations of this interface, the framework also provides `ContentMappingService.Util` which includes a couple of convenience utilities:
 
 [source,java]
 ----
@@ -72,4 +75,6 @@ public static class Util {
 
 == Related Services
 
-This service is a companion to the default implementation of the xref:../rgfis/rgfis.adoc#_rgfis_presentation-layer_ContentNegotiationService[`ContentNegotiationService`].
\ No newline at end of file
+This service is a companion to the default implementation of the xref:../rgfis/rgfis.adoc#_rgfis_presentation-layer_ContentNegotiationService[`ContentNegotiationService`].
+
+The framework implementations of `ContentMappingService` use the xref:rgsvc.adoc#_rgsvc_metadata-api_MetamodelService[`MetaModelService`] to lookup any custom implementations of `CommandDtoProcessor`.
\ No newline at end of file
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/Action.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/Action.java
index 1798a31..17aca49 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/Action.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/Action.java
@@ -27,8 +27,8 @@ import java.lang.annotation.Target;
 
 import org.apache.isis.applib.conmap.ContentMappingServiceForCommandDto;
 import org.apache.isis.applib.conmap.ContentMappingServiceForCommandsDto;
+import org.apache.isis.applib.services.command.CommandDtoProcessor;
 import org.apache.isis.applib.services.command.CommandWithDto;
-import org.apache.isis.applib.services.command.CommandWithDtoProcessor;
 import org.apache.isis.applib.services.command.spi.CommandService;
 import org.apache.isis.applib.services.eventbus.ActionDomainEvent;
 import org.apache.isis.applib.services.publish.PublisherService;
@@ -150,7 +150,7 @@ public @interface Action {
     CommandExecuteIn commandExecuteIn() default CommandExecuteIn.FOREGROUND;
 
     /**
-     * The {@link CommandWithDtoProcessor} to process this command's DTO.
+     * The {@link CommandDtoProcessor} to process this command's DTO.
      *
      * <p>
      *     Specifying a processor requires that the implementation of {@link CommandService} provides a
@@ -163,7 +163,7 @@ public @interface Action {
      *     {@link ContentMappingServiceForCommandsDto} to dynamically transform the DTOs.
      * </p>
      */
-    Class<? extends CommandWithDtoProcessor> commandWithDtoProcessor() default CommandWithDtoProcessor.class;
+    Class<? extends CommandDtoProcessor> commandDtoProcessor() default CommandDtoProcessor.class;
 
 
     // //////////////////////////////////////
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/Property.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/Property.java
index 106f380..ed91f9e 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/Property.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/Property.java
@@ -29,8 +29,8 @@ import javax.jdo.annotations.NotPersistent;
 
 import org.apache.isis.applib.conmap.ContentMappingServiceForCommandDto;
 import org.apache.isis.applib.conmap.ContentMappingServiceForCommandsDto;
+import org.apache.isis.applib.services.command.CommandDtoProcessor;
 import org.apache.isis.applib.services.command.CommandWithDto;
-import org.apache.isis.applib.services.command.CommandWithDtoProcessor;
 import org.apache.isis.applib.services.command.spi.CommandService;
 import org.apache.isis.applib.services.eventbus.PropertyDomainEvent;
 import org.apache.isis.applib.spec.Specification;
@@ -140,7 +140,7 @@ public @interface Property {
 
 
     /**
-     * The {@link CommandWithDtoProcessor} to process this command's DTO.
+     * The {@link CommandDtoProcessor} to process this command's DTO.
      *
      * <p>
      *     Specifying a processor requires that the implementation of {@link CommandService} provides a
@@ -153,7 +153,7 @@ public @interface Property {
      *     {@link ContentMappingServiceForCommandsDto} to dynamically transform the DTOs.
      * </p>
      */
-    Class<? extends CommandWithDtoProcessor> commandWithDtoProcessor() default CommandWithDtoProcessor.class;
+    Class<? extends CommandDtoProcessor> commandDtoProcessor() default CommandDtoProcessor.class;
 
 
 
diff --git a/core/applib/src/main/java/org/apache/isis/applib/conmap/ContentMappingServiceForCommandDto.java b/core/applib/src/main/java/org/apache/isis/applib/conmap/ContentMappingServiceForCommandDto.java
index 87149b6..717e70d 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/conmap/ContentMappingServiceForCommandDto.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/conmap/ContentMappingServiceForCommandDto.java
@@ -26,8 +26,8 @@ import javax.ws.rs.core.MediaType;
 import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.command.CommandDtoProcessor;
 import org.apache.isis.applib.services.command.CommandWithDto;
-import org.apache.isis.applib.services.command.CommandWithDtoProcessor;
 import org.apache.isis.applib.services.metamodel.MetaModelService5;
 import org.apache.isis.schema.cmd.v1.CommandDto;
 
@@ -70,12 +70,12 @@ public class ContentMappingServiceForCommandDto implements ContentMappingService
             CommandWithDto commandWithDto,
             final MetaModelService5 metaModelService) {
         final CommandDto commandDto = commandWithDto.asDto();
-        final CommandWithDtoProcessor commandWithDtoProcessor =
-                metaModelService.commandWithDtoProcessorFor(commandDto.getMember().getLogicalMemberIdentifier());
-        if (commandWithDtoProcessor == null) {
+        final CommandDtoProcessor commandDtoProcessor =
+                metaModelService.commandDtoProcessorFor(commandDto.getMember().getLogicalMemberIdentifier());
+        if (commandDtoProcessor == null) {
             return commandDto;
         }
-        return commandWithDtoProcessor.process(commandWithDto);
+        return commandDtoProcessor.process(commandWithDto, commandDto);
     }
 
     @Inject
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/command/CommandWithDtoProcessor.java b/core/applib/src/main/java/org/apache/isis/applib/services/command/CommandDtoProcessor.java
similarity index 81%
rename from core/applib/src/main/java/org/apache/isis/applib/services/command/CommandWithDtoProcessor.java
rename to core/applib/src/main/java/org/apache/isis/applib/services/command/CommandDtoProcessor.java
index 7511a9e..e1dbf13 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/command/CommandWithDtoProcessor.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/command/CommandDtoProcessor.java
@@ -21,23 +21,27 @@ package org.apache.isis.applib.services.command;
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.schema.cmd.v1.CommandDto;
 
-public interface CommandWithDtoProcessor {
+public interface CommandDtoProcessor {
 
     /**
      * Returning <tt>null</tt> means that the command's DTO is effectively excluded from any list.
      * If replicating from master to slave, this allows commands that can't be replicated to be ignored.
+     * @param command
+     * @param commandDto
      */
     @Programmatic
-    CommandDto process(CommandWithDto commandWithDto);
+    CommandDto process(final Command command, CommandDto commandDto);
 
 
     /**
      * Convenience implementation to simply indicate that no DTO should be returned for a command,
      * effectively ignoring it for replay purposes.
      */
-    public static class Null implements CommandWithDtoProcessor {
+    public static class Null implements CommandDtoProcessor {
         @Override
-        public CommandDto process(final CommandWithDto commandWithDto) {
+        public CommandDto process(
+                final Command command,
+                final CommandDto commandDto) {
             return null;
         }
     }
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/command/CommandWithDtoProcessorForActionAbstract.java b/core/applib/src/main/java/org/apache/isis/applib/services/command/CommandDtoProcessorForActionAbstract.java
similarity index 94%
rename from core/applib/src/main/java/org/apache/isis/applib/services/command/CommandWithDtoProcessorForActionAbstract.java
rename to core/applib/src/main/java/org/apache/isis/applib/services/command/CommandDtoProcessorForActionAbstract.java
index 8b755b3..9eccbb9 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/command/CommandWithDtoProcessorForActionAbstract.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/command/CommandDtoProcessorForActionAbstract.java
@@ -26,7 +26,7 @@ import org.apache.isis.schema.cmd.v1.ParamsDto;
 /**
  * Convenience adapter for command processors for action invocations.
  */
-public abstract class CommandWithDtoProcessorForActionAbstract implements CommandWithDtoProcessor {
+public abstract class CommandDtoProcessorForActionAbstract implements CommandDtoProcessor {
     protected CommandDto asDto(final CommandWithDto commandWithDto) {
         return commandWithDto.asDto();
     }
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/command/CommandWithDtoProcessorForPropertyAbstract.java b/core/applib/src/main/java/org/apache/isis/applib/services/command/CommandDtoProcessorForPropertyAbstract.java
similarity index 92%
rename from core/applib/src/main/java/org/apache/isis/applib/services/command/CommandWithDtoProcessorForPropertyAbstract.java
rename to core/applib/src/main/java/org/apache/isis/applib/services/command/CommandDtoProcessorForPropertyAbstract.java
index 6f0251f..fafe4a2 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/command/CommandWithDtoProcessorForPropertyAbstract.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/command/CommandDtoProcessorForPropertyAbstract.java
@@ -24,8 +24,8 @@ import org.apache.isis.schema.cmd.v1.PropertyDto;
 /**
  * Convenience adapter for command processors for property edits.
  */
-public abstract class CommandWithDtoProcessorForPropertyAbstract
-        implements CommandWithDtoProcessor {
+public abstract class CommandDtoProcessorForPropertyAbstract
+        implements CommandDtoProcessor {
     protected CommandDto asDto(final CommandWithDto commandWithDto) {
         return commandWithDto.asDto();
     }
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/metamodel/MetaModelService5.java b/core/applib/src/main/java/org/apache/isis/applib/services/metamodel/MetaModelService5.java
index f2c8d09..11b2301 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/metamodel/MetaModelService5.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/metamodel/MetaModelService5.java
@@ -19,11 +19,11 @@
 package org.apache.isis.applib.services.metamodel;
 
 import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.services.command.CommandWithDtoProcessor;
+import org.apache.isis.applib.services.command.CommandDtoProcessor;
 
 public interface MetaModelService5 extends MetaModelService4 {
 
     @Programmatic
-    CommandWithDtoProcessor commandWithDtoProcessorFor(String memberIdentifier);
+    CommandDtoProcessor commandDtoProcessorFor(String memberIdentifier);
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/command/CommandFacetForActionAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/command/CommandFacetForActionAnnotation.java
index 2a455bb..725d54d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/command/CommandFacetForActionAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/command/CommandFacetForActionAnnotation.java
@@ -24,7 +24,7 @@ import org.apache.isis.applib.annotation.Command.Persistence;
 import org.apache.isis.applib.annotation.CommandExecuteIn;
 import org.apache.isis.applib.annotation.CommandPersistence;
 import org.apache.isis.applib.annotation.CommandReification;
-import org.apache.isis.applib.services.command.CommandWithDtoProcessor;
+import org.apache.isis.applib.services.command.CommandDtoProcessor;
 import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.actions.command.CommandFacet;
@@ -43,9 +43,9 @@ public class CommandFacetForActionAnnotation extends CommandFacetAbstract {
         CommandReification commandReification = action != null ? action.command() : CommandReification.AS_CONFIGURED;
         final CommandPersistence commandPersistence = action != null ? action.commandPersistence() : CommandPersistence.PERSISTED;
         final CommandExecuteIn commandExecuteIn = action != null? action.commandExecuteIn() :  CommandExecuteIn.FOREGROUND;
-        final Class<? extends CommandWithDtoProcessor> processorClass =
-                action != null ? action.commandWithDtoProcessor() : null;
-        final CommandWithDtoProcessor processor = (CommandWithDtoProcessor) newProcessorElseNull(processorClass);
+        final Class<? extends CommandDtoProcessor> processorClass =
+                action != null ? action.commandDtoProcessor() : null;
+        final CommandDtoProcessor processor = (CommandDtoProcessor) newProcessorElseNull(processorClass);
 
         if(processor != null) {
             commandReification = CommandReification.ENABLED;
@@ -91,7 +91,7 @@ public class CommandFacetForActionAnnotation extends CommandFacetAbstract {
             final Persistence persistence,
             final ExecuteIn executeIn,
             final Enablement enablement,
-            final CommandWithDtoProcessor processor,
+            final CommandDtoProcessor processor,
             final FacetHolder holder,
             final ServicesInjector servicesInjector) {
         super(persistence, executeIn, enablement, processor, holder, servicesInjector);
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/command/CommandFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/command/CommandFacet.java
index 45d842c..b9f8fdd 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/command/CommandFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/command/CommandFacet.java
@@ -22,7 +22,7 @@ package org.apache.isis.core.metamodel.facets.actions.command;
 import org.apache.isis.applib.annotation.Command.ExecuteIn;
 import org.apache.isis.applib.annotation.Command.Persistence;
 import org.apache.isis.applib.services.command.Command;
-import org.apache.isis.applib.services.command.CommandWithDtoProcessor;
+import org.apache.isis.applib.services.command.CommandDtoProcessor;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 
 /**
@@ -50,5 +50,5 @@ public interface CommandFacet extends Facet {
      */
     public boolean isDisabled();
 
-    public CommandWithDtoProcessor getProcessor();
+    public CommandDtoProcessor getProcessor();
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/command/CommandFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/command/CommandFacetAbstract.java
index 22812ef..e08b4ca 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/command/CommandFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/command/CommandFacetAbstract.java
@@ -21,7 +21,7 @@ package org.apache.isis.core.metamodel.facets.actions.command;
 
 import org.apache.isis.applib.annotation.Command.ExecuteIn;
 import org.apache.isis.applib.annotation.Command.Persistence;
-import org.apache.isis.applib.services.command.CommandWithDtoProcessor;
+import org.apache.isis.applib.services.command.CommandDtoProcessor;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.MarkerFacetAbstract;
@@ -45,13 +45,13 @@ public abstract class CommandFacetAbstract extends MarkerFacetAbstract implement
     private final Persistence persistence;
     private final ExecuteIn executeIn;
     private final Enablement enablement;
-    private final CommandWithDtoProcessor processor;
+    private final CommandDtoProcessor processor;
 
     public CommandFacetAbstract(
             final Persistence persistence,
             final ExecuteIn executeIn,
             final Enablement enablement,
-            final CommandWithDtoProcessor processor,
+            final CommandDtoProcessor processor,
             final FacetHolder holder,
             final ServicesInjector servicesInjector) {
         super(type(), holder);
@@ -63,7 +63,7 @@ public abstract class CommandFacetAbstract extends MarkerFacetAbstract implement
     }
 
     private static void inject(
-            final CommandWithDtoProcessor processor, final ServicesInjector servicesInjector) {
+            final CommandDtoProcessor processor, final ServicesInjector servicesInjector) {
         if(processor == null || servicesInjector == null) {
             return;
         }
@@ -86,26 +86,26 @@ public abstract class CommandFacetAbstract extends MarkerFacetAbstract implement
     }
 
     @Override
-    public CommandWithDtoProcessor getProcessor() {
+    public CommandDtoProcessor getProcessor() {
         return processor;
     }
 
     /**
      * For benefit of subclasses.
      */
-    protected static CommandWithDtoProcessor newProcessorElseNull(final Class<?> cls) {
+    protected static CommandDtoProcessor newProcessorElseNull(final Class<?> cls) {
         if(cls == null) {
             return null;
         }
-        if(cls == CommandWithDtoProcessor.class) {
+        if(cls == CommandDtoProcessor.class) {
             // ie the default value, namely the interface
             return null;
         }
-        if (!(CommandWithDtoProcessor.class.isAssignableFrom(cls))) {
+        if (!(CommandDtoProcessor.class.isAssignableFrom(cls))) {
             return null;
         }
         try {
-            return (CommandWithDtoProcessor) cls.newInstance();
+            return (CommandDtoProcessor) cls.newInstance();
         } catch (final InstantiationException | IllegalAccessException e) {
             return null;
         }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/command/CommandFacetForPropertyAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/command/CommandFacetForPropertyAnnotation.java
index 12971c4..3eb1290 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/command/CommandFacetForPropertyAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/command/CommandFacetForPropertyAnnotation.java
@@ -24,7 +24,7 @@ import org.apache.isis.applib.annotation.CommandExecuteIn;
 import org.apache.isis.applib.annotation.CommandPersistence;
 import org.apache.isis.applib.annotation.CommandReification;
 import org.apache.isis.applib.annotation.Property;
-import org.apache.isis.applib.services.command.CommandWithDtoProcessor;
+import org.apache.isis.applib.services.command.CommandDtoProcessor;
 import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.actions.action.command.CommandFacetFromConfiguration;
@@ -43,9 +43,9 @@ public class CommandFacetForPropertyAnnotation extends CommandFacetAbstract {
         CommandReification commandReification = property != null ? property.command() : CommandReification.AS_CONFIGURED;
         final CommandPersistence commandPersistence = property != null ? property.commandPersistence() : CommandPersistence.PERSISTED;
         final CommandExecuteIn commandExecuteIn = property != null? property.commandExecuteIn() :  CommandExecuteIn.FOREGROUND;
-        final Class<? extends CommandWithDtoProcessor> processorClass =
-                property != null ? property.commandWithDtoProcessor() : null;
-        final CommandWithDtoProcessor processor = (CommandWithDtoProcessor) newProcessorElseNull(processorClass);
+        final Class<? extends CommandDtoProcessor> processorClass =
+                property != null ? property.commandDtoProcessor() : null;
+        final CommandDtoProcessor processor = newProcessorElseNull(processorClass);
 
         if(processor != null) {
             commandReification = CommandReification.ENABLED;
@@ -82,7 +82,7 @@ public class CommandFacetForPropertyAnnotation extends CommandFacetAbstract {
             final ExecuteIn executeIn,
             final Enablement enablement,
             final FacetHolder holder,
-            final CommandWithDtoProcessor processor,
+            final CommandDtoProcessor processor,
             final ServicesInjector servicesInjector) {
         super(persistence, executeIn, enablement, processor, holder, servicesInjector);
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
index 213e047..fb306b6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
@@ -34,7 +34,7 @@ import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.services.bookmark.Bookmark;
-import org.apache.isis.applib.services.command.CommandWithDtoProcessor;
+import org.apache.isis.applib.services.command.CommandDtoProcessor;
 import org.apache.isis.applib.services.grid.GridService;
 import org.apache.isis.applib.services.metamodel.DomainMember;
 import org.apache.isis.applib.services.metamodel.MetaModelService5;
@@ -235,7 +235,7 @@ public class MetaModelServiceDefault implements MetaModelService5 {
     }
 
     @Override
-    public CommandWithDtoProcessor commandWithDtoProcessorFor(final String memberIdentifier) {
+    public CommandDtoProcessor commandDtoProcessorFor(final String memberIdentifier) {
         final ApplicationFeatureId featureId = ApplicationFeatureId
                 .newFeature(ApplicationFeatureType.MEMBER, memberIdentifier);
 
diff --git a/core/schema/src/main/resources/org/apache/isis/schema/common/common-1.1.xsd b/core/schema/src/main/resources/org/apache/isis/schema/common/common-1.1.xsd
index eb61cb1..ac50abd 100644
--- a/core/schema/src/main/resources/org/apache/isis/schema/common/common-1.1.xsd
+++ b/core/schema/src/main/resources/org/apache/isis/schema/common/common-1.1.xsd
@@ -92,8 +92,6 @@
             <xs:element name="mimeType" type="xs:string"/>
             <xs:element name="bytes" type="xs:hexBinary"/>
         </xs:sequence>
-        <xs:attribute name="type" use="required" type="valueType"/>
-        <xs:attribute name="null" use="optional" type="xs:boolean"/>
     </xs:complexType>
 
     <xs:complexType name="clobDto">
@@ -106,8 +104,6 @@
             <xs:element name="mimeType" type="xs:string"/>
             <xs:element name="chars" type="xs:string"/>
         </xs:sequence>
-        <xs:attribute name="type" use="required" type="valueType"/>
-        <xs:attribute name="null" use="optional" type="xs:boolean"/>
     </xs:complexType>
 
     <xs:complexType name="oidsDto">

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