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 2016/04/19 22:48:09 UTC

[1/3] isis git commit: ISIS-1291: adding design doc

Repository: isis
Updated Branches:
  refs/heads/ISIS-1291 45d306811 -> 0264ec605


ISIS-1291: adding design doc


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/18469933
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/18469933
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/18469933

Branch: refs/heads/ISIS-1291
Commit: 18469933eabbfd1ccf0d492ed751e50554425469
Parents: 45d3068
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Sat Apr 16 09:52:14 2016 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Sat Apr 16 09:52:33 2016 +0100

----------------------------------------------------------------------
 .../pptx/commands-vs-actioninvocationevent.pptx    | Bin 0 -> 70543 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/18469933/adocs/documentation/src/main/pptx/commands-vs-actioninvocationevent.pptx
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/pptx/commands-vs-actioninvocationevent.pptx b/adocs/documentation/src/main/pptx/commands-vs-actioninvocationevent.pptx
new file mode 100644
index 0000000..75f7a79
Binary files /dev/null and b/adocs/documentation/src/main/pptx/commands-vs-actioninvocationevent.pptx differ


[3/3] isis git commit: ISIS-1291: memento xsd schemas + utils; new command memento DTO for Command#memento, updated background service, background execution; new PublisherService

Posted by da...@apache.org.
ISIS-1291: memento xsd schemas + utils; new command memento DTO for Command#memento, updated background service, background execution;  new PublisherService

specifically:
- deleted aim-1.0.xsd, added in aim-2.0.xsd, also cmd-1.0.xsd and updated common-1.0.xsd.
- Updated ActionMementoDtoUtils new CommandMementoDtoUtils and CommandDtoUtils
- moved CommandMementoService to internal SPI, added asCommandMemento, depends on ObjectAction (in order to handle mixin types) and also works on lists of objects (for bulk command/actions)
- ActionInvocationFacet populates the Command#setMemento using CommandMementoDto (legacy behaviour preserved)


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/0264ec60
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/0264ec60
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/0264ec60

Branch: refs/heads/ISIS-1291
Commit: 0264ec60582fa39d312e3ae79b0bb534f0ff9afc
Parents: 1846993
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Tue Apr 19 21:46:03 2016 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Tue Apr 19 21:46:03 2016 +0100

----------------------------------------------------------------------
 .../src/main/asciidoc/schema/aim/aim-1.0.xsd    | 205 -------
 .../src/main/asciidoc/schema/aim/aim.xsd        |  74 ---
 .../background/ActionInvocationMemento.java     |  14 +-
 .../background/BackgroundCommandService.java    |  10 +
 .../background/BackgroundCommandService2.java   |  45 ++
 .../isis/applib/services/bookmark/Bookmark.java |  50 +-
 .../isis/applib/services/command/Command.java   |   4 +-
 .../services/command/CommandMementoService.java |  76 ---
 .../services/publish/PublisherService.java      |  40 ++
 .../services/publish/PublishingService.java     |  10 +-
 .../services/publish/PublishingService2.java    |  34 --
 .../utils/ActionInvocationMementoDtoUtils.java  | 552 +++++++------------
 .../schema/utils/CommandMementoDtoUtils.java    | 263 +++++++++
 .../isis/schema/utils/CommonDtoUtils.java       | 183 ++++++
 .../org/apache/isis/schema/utils/Roundtrip.java |  83 ++-
 .../metamodel/adapter/oid/OidMarshaller.java    |   8 +-
 ...onInvocationFacetForDomainEventAbstract.java |  88 ++-
 .../PropertySetterFacetViaModifyMethod.java     |   4 +-
 .../services/command/CommandMementoService.java |  53 ++
 .../background/BackgroundCommandExecution.java  | 125 ++++-
 .../background/BackgroundServiceDefault.java    |  28 +-
 .../command/CommandMementoServiceDefault.java   |  81 +--
 .../AbstractIsisSessionTemplate.java            |   4 +
 .../apache/isis/schema/aim/aim-2.0-binding.xml  |   2 +-
 .../org/apache/isis/schema/aim/aim-2.0.xsd      |  40 +-
 .../org/apache/isis/schema/cmd/cmd-1.0.xsd      |  39 +-
 .../apache/isis/schema/common/common-1.0.xsd    |  21 +
 27 files changed, 1221 insertions(+), 915 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/adocs/documentation/src/main/asciidoc/schema/aim/aim-1.0.xsd
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/schema/aim/aim-1.0.xsd b/adocs/documentation/src/main/asciidoc/schema/aim/aim-1.0.xsd
deleted file mode 100644
index 9a5c902..0000000
--- a/adocs/documentation/src/main/asciidoc/schema/aim/aim-1.0.xsd
+++ /dev/null
@@ -1,205 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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 agreed to in writing,
-  software distributed under the License is distributed on an
-  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  KIND, either express or implied.  See the License for the
-  specific language governing permissions and limitations
-  under the License.
--->
-<xs:schema targetNamespace="http://isis.apache.org/schema/aim"
-           elementFormDefault="qualified"
-           xmlns:xs="http://www.w3.org/2001/XMLSchema"
-           xmlns="http://isis.apache.org/schema/aim"
-           xmlns:common="http://isis.apache.org/schema/common">
-
-    <xs:import namespace="http://isis.apache.org/schema/common" schemaLocation="../common/common-1.0.xsd"/>
-
-    <xs:element name="actionInvocationMementoDto" type="actionInvocationMementoDto">
-        <xs:annotation>
-            <xs:documentation>Represents v1.1 of this schema.  Changes since v1.0 are the 'majorVersion' and 'minorVersion', the 'mixedIn' element, the 'returned' element.
-            </xs:documentation>
-        </xs:annotation>
-    </xs:element>
-
-    <xs:complexType name="actionInvocationMementoDto">
-        <xs:sequence>
-            <xs:element name="majorVersion" type="xs:string" minOccurs="0" maxOccurs="1" default="1">
-                <xs:annotation>
-                    <xs:documentation>Introduced in v1.1. The major version of the schema that an XML instance was created using.  This element is optional for backward compatibility, but will be populated for any v1.1+ instances of this schema.  If missing, assume '0'.
-                    </xs:documentation>
-                </xs:annotation>
-            </xs:element>
-            <xs:element name="minorVersion" type="xs:string" minOccurs="0" maxOccurs="1" default="1">
-                <xs:annotation>
-                    <xs:documentation>Introduced in v1.1. The minor version of the schema that an XML instance was created using.  This element is optional for backward compatibility, but will be populated for any v1.1+ instances of this schema.  If missing, assume '0'.
-                    </xs:documentation>
-                </xs:annotation>
-            </xs:element>
-            <xs:element name="metadata">
-                <xs:complexType>
-                    <xs:sequence>
-                        <xs:element name="transactionId" type="xs:string">
-                            <xs:annotation>
-                                <xs:documentation>Transaction id that this action was invoked.  Can be used to locate the corresponding Command object (which may have been persisted).  However, there could be many such actions (eg by virtue of WrapperFactory); the 'sequence' is used to provide a unique id for each action invocation.
-                                </xs:documentation>
-                            </xs:annotation>
-                        </xs:element>
-                        <xs:element name="sequence" type="xs:int">
-                            <xs:annotation>
-                                <xs:documentation>The combination of ['transactionId', 'sequence'] is guaranteed to be unique.
-                                </xs:documentation>
-                            </xs:annotation>
-                        </xs:element>
-                        <xs:element name="timestamp" type="xs:dateTime">
-                            <xs:annotation>
-                                <xs:documentation>The point in time that this action was invoked.  See also 'timestampComplete'.
-                                </xs:documentation>
-                            </xs:annotation>
-                        </xs:element>
-                        <xs:element name="timestampComplete" type="xs:dateTime" minOccurs="0" maxOccurs="1">
-                            <xs:annotation>
-                                <xs:documentation>Introduced in v1.1. The point in time that this action completed.  The duration that the action took is the difference between 'timestamp' and 'timestampComplete'.  This element is optional for backward compatibility, but will be populated for any v1.1 instances of this schema.
-                                </xs:documentation>
-                            </xs:annotation>
-                        </xs:element>
-                        <xs:element name="mixinFqClassName" type="xs:string" minOccurs="0" maxOccurs="1">
-                            <xs:annotation>
-                                <xs:documentation>Introduced in v1.1. Populated only for mixin actions, is the fully qualified class name of the mixin type.  This element is optional for backward compatibility, but will be populated for any v1.1+ instances of this schema for to mixin actions.
-                                </xs:documentation>
-                            </xs:annotation>
-                        </xs:element>
-                        <xs:element name="target" type="common:oidDto">
-                            <xs:annotation>
-                                <xs:documentation>For regular actions, represents the entity or view model upon which the action is invoked.  For mixin actions, is the object being mixed-into (the constructor arg to the mixin).  For contributed actions, is the domain service (the contributee object will be one of the action arguments within the payload).  Mixin actions can be determined by the presence of the 'mixinClass' element (v1.1+ instances of the schema).
-                                </xs:documentation>
-                            </xs:annotation>
-                        </xs:element>
-                        <xs:element name="targetClass" type="xs:string">
-                            <xs:annotation>
-                                <xs:documentation>User-friendly representation of the target's class.  For the formal target' type, use the 'target' element (an oidDto)
-                                </xs:documentation>
-                            </xs:annotation>
-                        </xs:element>
-                        <xs:element name="targetAction" type="xs:string">
-                            <xs:annotation>
-                                <xs:documentation>User-friendly representation of the action being invoked.  For the formal action identifier, use the 'actionIdentifier' element.
-                                </xs:documentation>
-                            </xs:annotation>
-                        </xs:element>
-                        <xs:element name="actionIdentifier" type="xs:string">
-                            <xs:annotation>
-                                <xs:documentation>Formal identifier of the action being invoked.
-                                </xs:documentation>
-                            </xs:annotation>
-                        </xs:element>
-                        <xs:element name="user" type="xs:string">
-                            <xs:annotation>
-                                <xs:documentation>The name of the user that invoked this action.  Note that this isn't necessarily the user that initiated the original command; the SudoService may be being used to temporarily switch the effective user.
-                                </xs:documentation>
-                            </xs:annotation>
-                        </xs:element>
-                        <xs:element name="title" type="xs:string">
-                            <xs:annotation>
-                                <xs:documentation>User-friendly title of the 'target' object.
-                                </xs:documentation>
-                            </xs:annotation>
-                        </xs:element>
-                    </xs:sequence>
-                </xs:complexType>
-            </xs:element>
-            <xs:element name="payload">
-                <xs:complexType>
-                    <xs:sequence>
-                        <xs:element name="parameters">
-                            <xs:complexType>
-                                <xs:sequence maxOccurs="unbounded">
-                                    <xs:element name="param" type="paramDto"/>
-                                </xs:sequence>
-                                <xs:attribute name="num" use="required" type="xs:int"/>
-                            </xs:complexType>
-                        </xs:element>
-                        <xs:element name="return" type="common:valueDto" minOccurs="0" maxOccurs="1">
-                            <xs:annotation>
-                                <xs:documentation>Deprecated in v1.1; use the 'returned' element (which also provides the return type) instead.  For v1.1+ instances of this schema (representing a completed action), either both 'return' and 'returned' will be populated, or the 'threw' element will be populated.
-                                </xs:documentation>
-                            </xs:annotation>
-                        </xs:element>
-                        <xs:element name="returned" type="returnDto" minOccurs="0" maxOccurs="1">
-                            <xs:annotation>
-                                <xs:documentation>Introduced in v1.1, replaces the deprecated 'return' element (which exposes the return value, but not the return type).  For v1.1+ instances of this schema (representing a completed action), either both 'return' and 'returned' will be populated, or the 'threw' element will be populated.
-                                </xs:documentation>
-                            </xs:annotation>
-                        </xs:element>
-                        <xs:element name="threw" type="exceptionDto" minOccurs="0" maxOccurs="1">
-                            <xs:annotation>
-                                <xs:documentation>Introduced in v1.1. Captures any exception thrown by an action.  For v1.1+ instances of this schema (representing a completed action), either both 'return' and 'returned' will be populated, or the 'threw' element will be populated.
-                                </xs:documentation>
-                            </xs:annotation>
-                        </xs:element>
-                    </xs:sequence>
-                </xs:complexType>
-            </xs:element>
-            <xs:element name="subActions" type="actionInvocationMementoDto" minOccurs="0" maxOccurs="unbounded">
-                <xs:annotation>
-                    <xs:documentation>Introduced in v1.1. Capture sub-actions (if-any) invoked from this action, for example using the WrapperFactory service.  These therefore define a graph/call-stack of actions.  Note that the subactions will redundantly also specify their majorVersion and minorVersion (the alternative would have required restructuring in such a way as to break backward compatibility).
-                    </xs:documentation>
-                </xs:annotation>
-            </xs:element>
-        </xs:sequence>
-    </xs:complexType>
-
-    <xs:complexType name="paramDto">
-        <xs:annotation>
-            <xs:documentation>The parameter types and values (ie arguments) of action parameters.
-            </xs:documentation>
-        </xs:annotation>
-        <xs:sequence>
-            <xs:element name="value" type="common:valueDto"/>
-        </xs:sequence>
-        <xs:attribute name="parameterName" use="required" type="xs:string"/>
-        <xs:attribute name="parameterType" use="required" type="common:valueType"/>
-        <xs:attribute name="null" use="optional" type="xs:boolean"/>
-    </xs:complexType>
-
-    <xs:complexType name="returnDto">
-        <xs:annotation>
-            <xs:documentation>Introduced in v1.1.  Captures both the value returned of an action, and also the type of that returned value.
-            </xs:documentation>
-        </xs:annotation>
-        <xs:sequence>
-            <xs:element name="value" type="common:valueDto"/>
-        </xs:sequence>
-        <xs:attribute name="returnType" use="required" type="common:valueType"/>
-        <xs:attribute name="null" use="optional" type="xs:boolean"/>
-    </xs:complexType>
-
-    <xs:complexType name="exceptionDto">
-        <xs:annotation>
-            <xs:documentation>Introduced in v1.1, captures any exception thrown by an action invocation.  Use as the xsd:type of the 'threw' element.
-            </xs:documentation>
-        </xs:annotation>
-        <xs:sequence>
-            <xs:element name="message" type="xs:string"/>
-            <xs:element name="stackTrace" type="xs:string">
-                <xs:annotation>
-                    <xs:documentation>A formatted stack trace.  (A future version of the 'exceptionDto' element might refine this to more easily
-                        parseable stack trace elements).
-                    </xs:documentation>
-                </xs:annotation>
-            </xs:element>
-            <xs:element name="causedBy" type="exceptionDto" minOccurs="0" maxOccurs="1"/>
-        </xs:sequence>
-    </xs:complexType>
-
-</xs:schema>

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/adocs/documentation/src/main/asciidoc/schema/aim/aim.xsd
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/schema/aim/aim.xsd b/adocs/documentation/src/main/asciidoc/schema/aim/aim.xsd
deleted file mode 100644
index 749fcd0..0000000
--- a/adocs/documentation/src/main/asciidoc/schema/aim/aim.xsd
+++ /dev/null
@@ -1,74 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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 agreed to in writing,
-  software distributed under the License is distributed on an
-  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  KIND, either express or implied.  See the License for the
-  specific language governing permissions and limitations
-  under the License.
--->
-<xs:schema targetNamespace="http://isis.apache.org/schema/aim"
-           elementFormDefault="qualified"
-           xmlns:xs="http://www.w3.org/2001/XMLSchema"
-           xmlns="http://isis.apache.org/schema/aim"
-           xmlns:common="http://isis.apache.org/schema/common">
-
-    <xs:import namespace="http://isis.apache.org/schema/common" schemaLocation="http://isis.apache.org/schema/common/common-1.0.xsd"/>
-
-    <xs:element name="actionInvocationMementoDto">
-        <xs:complexType>
-            <xs:sequence>
-                <xs:element name="metadata">
-                    <xs:complexType>
-                        <xs:sequence>
-                            <xs:element name="transactionId" type="xs:string"/>
-                            <xs:element name="sequence" type="xs:int"/>
-                            <xs:element name="timestamp" type="xs:dateTime"/>
-                            <xs:element name="target" type="common:oidDto"/>
-                            <xs:element name="targetClass" type="xs:string"/>
-                            <xs:element name="targetAction" type="xs:string"/>
-                            <xs:element name="actionIdentifier" type="xs:string"/>
-                            <xs:element name="user" type="xs:string"/>
-                            <xs:element name="title" type="xs:string"/>
-                        </xs:sequence>
-                    </xs:complexType>
-                </xs:element>
-                <xs:element name="payload">
-                    <xs:complexType>
-                        <xs:sequence>
-                            <xs:element name="parameters">
-                                <xs:complexType>
-                                    <xs:sequence maxOccurs="unbounded">
-                                        <xs:element name="param" type="paramDto"/>
-                                    </xs:sequence>
-                                    <xs:attribute name="num" use="required" type="xs:int"/>
-                                </xs:complexType>
-                            </xs:element>
-                            <xs:element name="return" type="common:valueDto" minOccurs="0" maxOccurs="1"/>
-                        </xs:sequence>
-                    </xs:complexType>
-                </xs:element>
-            </xs:sequence>
-        </xs:complexType>
-    </xs:element>
-
-    <xs:complexType name="paramDto">
-        <xs:sequence>
-            <xs:element name="value" type="common:valueDto"/>
-        </xs:sequence>
-        <xs:attribute name="parameterName" use="required" type="xs:string"/>
-        <xs:attribute name="parameterType" use="required" type="common:valueType"/>
-        <xs:attribute name="null" use="optional" type="xs:boolean"/>
-    </xs:complexType>
-
-</xs:schema>

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/applib/src/main/java/org/apache/isis/applib/services/background/ActionInvocationMemento.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/background/ActionInvocationMemento.java b/core/applib/src/main/java/org/apache/isis/applib/services/background/ActionInvocationMemento.java
index baa4f51..ca476b4 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/background/ActionInvocationMemento.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/background/ActionInvocationMemento.java
@@ -21,6 +21,7 @@ import java.util.List;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.memento.MementoService;
 import org.apache.isis.applib.services.memento.MementoService.Memento;
+import org.apache.isis.schema.cmd.v1.CommandMementoDto;
 
 /**
  * A memento for an action invocation, to allow the details of an action invocation
@@ -30,12 +31,21 @@ import org.apache.isis.applib.services.memento.MementoService.Memento;
  * Provided as a mechanism by which implementations of {@link BackgroundService} can 
  * hand-off work to the {@link BackgroundCommandService}.  This is used by the
  * default implementation of <tt>BackgroundServiceDefault</tt> in the <tt>isis-module-background</tt> module.
- * 
+ * </p>
+ *
  * <p>
- * Implementation-wise this is a wrapper around {@link MementoService.Memento}, 
+ * Implementation-wise this is a wrapper around {@link MementoService.Memento},
  * and abstracts away the details of the keys used to store the various pieces of
  * information stored in the underlying memento.
+ * </p>
+ *
+ * <p>
+ * Note that this class - unlike {@link CommandMementoDto} does <i>not</i> support mixins.
+ * </p>
+ *
+ * @deprecated - use {@link CommandMementoDto} instead.
  */
+@Deprecated
 public class ActionInvocationMemento {
 
     private final Memento memento;

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundCommandService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundCommandService.java b/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundCommandService.java
index 6a291c1..919a700 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundCommandService.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundCommandService.java
@@ -34,9 +34,19 @@ import org.apache.isis.applib.services.command.Command;
  * API is through {@link org.apache.isis.applib.services.background.BackgroundService}).  It is therefore
  * annotated with {@link org.apache.isis.applib.annotation.DomainService} so that it is automatically registered as
  * a service.
+ *
+ * <p>
+ *     If an implementation also implements {@link BackgroundCommandService2}, then
+ *     {@link BackgroundCommandService2#schedule(ActionInvocationMemento, Command, String, String, String)} will be
+ *     called rather than {@link BackgroundCommandService#schedule(ActionInvocationMemento, Command, String, String, String)}.
+ * </p>
  */
 public interface BackgroundCommandService {
 
+    /**
+     * @deprecated - replaced by {@link BackgroundCommandService2#schedule(ActionInvocationMemento, Command, String, String, String)}
+     */
+    @Deprecated
     void schedule(
             final ActionInvocationMemento aim, 
             final Command command, 

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundCommandService2.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundCommandService2.java b/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundCommandService2.java
new file mode 100644
index 0000000..fd3a298
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/background/BackgroundCommandService2.java
@@ -0,0 +1,45 @@
+/**
+ *  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 agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.applib.services.background;
+
+import org.apache.isis.applib.services.command.Command;
+import org.apache.isis.schema.cmd.v1.CommandMementoDto;
+
+/**
+ * Persists a {@link org.apache.isis.schema.cmd.v1.CommandMementoDto memento-ized} command such that it can be executed asynchronously,
+ * for example through a Quartz scheduler.
+ *
+ * <p>
+ *     If an implementation of {@link BackgroundCommandService} also implements this interface, then its version of {@link #schedule(ActionInvocationMemento, Command, String, String, String)}  will be used instead.
+ * </p>
+ *
+ */
+public interface BackgroundCommandService2 extends BackgroundCommandService {
+
+    /**
+     * Replaces {@link BackgroundCommandService#schedule(ActionInvocationMemento, Command, String, String, String)}
+     * @param dto
+     * @param command
+     * @param targetClassName
+     * @param targetActionName
+     * @param targetArgs
+     */
+    void schedule(
+            final CommandMementoDto dto,
+            final Command command,
+            final String targetClassName, final String targetActionName, final String targetArgs);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/Bookmark.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/Bookmark.java b/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/Bookmark.java
index 349dd5a..b539a2a 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/Bookmark.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/bookmark/Bookmark.java
@@ -23,6 +23,9 @@ import java.util.Iterator;
 
 import com.google.common.base.Splitter;
 
+import org.apache.isis.schema.common.v1.BookmarkObjectState;
+import org.apache.isis.schema.common.v1.OidDto;
+
 /**
  * String representation of any persistent object managed by the framework.
  * 
@@ -35,14 +38,35 @@ public class Bookmark implements Serializable {
 
     private static final char SEPARATOR = ':';
 
-    public static enum ObjectState {
-        PERSISTENT(""),
-        TRANSIENT("!"), // same as OidMarshaller
-        VIEW_MODEL("*"); // same as OidMarshaller
+    public OidDto toOidDto() {
+        OidDto oidDto = new OidDto();
+        oidDto.setObjectState(getObjectState().toBookmarkState());
+        oidDto.setObjectType(getObjectType());
+        oidDto.setObjectIdentifier(getIdentifier());
+        return oidDto;
+    }
+
+    public static Bookmark from(final OidDto oidDto) {
+        final BookmarkObjectState bookmarkObjectState = oidDto.getObjectState();
+        final ObjectState objectState = ObjectState.from(bookmarkObjectState);
+        final Bookmark bookmark = new Bookmark(objectState.getCode() + oidDto.getObjectType(), oidDto.getObjectIdentifier());
+        return bookmark;
+    }
+
+
+    public enum ObjectState {
+        PERSISTENT("", BookmarkObjectState.PERSISTENT),
+        TRANSIENT("!", BookmarkObjectState.TRANSIENT), // same as OidMarshaller
+        VIEW_MODEL("*", BookmarkObjectState.VIEW_MODEL); // same as OidMarshaller
 
         private final String code;
-        private ObjectState(final String code) {
+        private final BookmarkObjectState bookmarkObjectState;
+
+        ObjectState(
+                final String code,
+                final BookmarkObjectState bookmarkObjectState) {
             this.code = code;
+            this.bookmarkObjectState = bookmarkObjectState;
         }
 
         public boolean isTransient() {
@@ -64,6 +88,22 @@ public class Bookmark implements Serializable {
             if(objectType.startsWith(VIEW_MODEL.code)) return VIEW_MODEL;
             return PERSISTENT;
         }
+
+        public static ObjectState from(final BookmarkObjectState objectState) {
+            switch (objectState) {
+            case PERSISTENT:
+                return ObjectState.PERSISTENT;
+            case TRANSIENT:
+                return ObjectState.TRANSIENT;
+            case VIEW_MODEL:
+                return ObjectState.VIEW_MODEL;
+            }
+            throw new IllegalArgumentException("BookmarkObjectState " + objectState + "' not recognized");
+        }
+
+        public BookmarkObjectState toBookmarkState() {
+            return bookmarkObjectState;
+        }
     }
 
     private final String objectType;

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/applib/src/main/java/org/apache/isis/applib/services/command/Command.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/command/Command.java b/core/applib/src/main/java/org/apache/isis/applib/services/command/Command.java
index 84bd934..77bbbbf 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/command/Command.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/command/Command.java
@@ -60,7 +60,7 @@ public interface Command extends HasTransactionId {
      * The value for {@link #getTargetAction()} if this command represents an edit of an object's property
      * (rather than an action).
      */
-    String TARGET_ACTION_FOR_EDIT = "(edit)";
+    String ACTION_IDENTIFIER_FOR_EDIT = "(edit)";
 
     // //////////////////////////////////////
     // user (property)
@@ -161,7 +161,7 @@ public interface Command extends HasTransactionId {
      * The human-friendly name of the action invoked on the target object.
      *
      * <p>
-     *     If the command represents an edit of a property, then holds the value &quot;{@value TARGET_ACTION_FOR_EDIT}&quot;.
+     *     If the command represents an edit of a property, then holds the value &quot;{@value ACTION_IDENTIFIER_FOR_EDIT}&quot;.
      * </p>
      */
     public abstract String getTargetAction();

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/applib/src/main/java/org/apache/isis/applib/services/command/CommandMementoService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/command/CommandMementoService.java b/core/applib/src/main/java/org/apache/isis/applib/services/command/CommandMementoService.java
deleted file mode 100644
index 590464a..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/command/CommandMementoService.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- *  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 agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package org.apache.isis.applib.services.command;
-
-import java.lang.reflect.Method;
-import java.sql.Timestamp;
-
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.services.background.ActionInvocationMemento;
-import org.apache.isis.applib.services.publish.EventMetadata;
-import org.apache.isis.applib.services.sudo.SudoService;
-import org.apache.isis.applib.services.user.UserService;
-import org.apache.isis.applib.services.wrapper.WrapperFactory;
-import org.apache.isis.schema.aim.v1.ActionInvocationMementoDto;
-
-/**
- * Submit actions to be invoked in the background.
- * 
- * <p>
- * Example usage:
- * <pre>
- * public void submitInvoices() {
- *     for(Customer customer: customerRepository.findCustomersToInvoice()) {
- *         backgroundService.execute(customer).submitInvoice();
- *     }
- * }
- * 
- * &#64;javax.inject.Inject
- * private BackgroundService backgroundService;
- * </pre>
- */
-public interface CommandMementoService {
-
-    @Programmatic
-    ActionInvocationMemento asActionInvocationMemento(Method m, Object domainObject, Object[] args);
-
-    /**
-     * @param command - must represent an action invocation (ie {@link Command#getTargetAction()} does not return {@link Command#TARGET_ACTION_FOR_EDIT}) (else throws exception).
-     * @param currentUser - as provided by {@link UserService} (might change within an action if {@link SudoService} has been used).
-     * @param timestamp - as obtained from clock (might want multiple events to all have the same clock, eg publishing muliple changed objects)
-     * @param sequenceName - to create unique events per {@link Command#getTransactionId()}; see {@link EventMetadata#getId()}.
-     */
-    @Programmatic
-    EventMetadata newEventMetadata(
-            final Command command,
-            final String currentUser,
-            final Timestamp timestamp,
-            final String sequenceName);
-
-    /**
-     * For {@link EventMetadata event}s representing an {@link org.apache.isis.applib.services.publish.EventType#ACTION_INVOCATION action invocation}, converts to an {@link ActionInvocationMementoDto}.
-     *
-     * <p>
-     *     The additional information needed for the {@link ActionInvocationMementoDto DTO} (namely the action arguments and
-     *     result) can be obtained from the thread-local in <tt>ActionInvocationFacet</tt>; this thread-local is reset for
-     *     each action invoked (eg for outer action, or for each sub-action invoked via {@link WrapperFactory}).
-     * </p>
-     */
-    @Programmatic
-    ActionInvocationMementoDto asActionInvocationMementoDto(final EventMetadata metadata);
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherService.java b/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherService.java
new file mode 100644
index 0000000..40660b5
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherService.java
@@ -0,0 +1,40 @@
+/*
+ *  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 agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib.services.publish;
+
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.schema.aim.v2.ActionInvocationMementoDto;
+
+/**
+ * Replaces {@link PublishingService}.
+ */
+public interface PublisherService {
+
+    @Programmatic
+    void publish(final ActionInvocationMementoDto aimDto);
+
+    /**
+     * To support implementations that allow the republishing of commands, eg onto an JMS message bus.
+     */
+    @Programmatic
+    void republish(final ActionInvocationMementoDto aimDto);
+    
+}
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublishingService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublishingService.java b/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublishingService.java
index a5f4277..0f7939b 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublishingService.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublishingService.java
@@ -21,6 +21,7 @@ package org.apache.isis.applib.services.publish;
 
 import org.apache.isis.applib.annotation.Hidden;
 import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.schema.aim.v2.ActionInvocationMementoDto;
 
 /**
  * Will be called whenever an publishable entity has changed its state, or an published action has been invoked.
@@ -39,7 +40,14 @@ import org.apache.isis.applib.annotation.Programmatic;
  * To use either service, must include on the classpath and also register the service (eg in <tt>isis.properties</tt>).
  */
 public interface PublishingService {
-    
+
+    /**
+     * @param metadata
+     * @param payload
+     *
+     * @deprecated - use instead {@link PublisherService#publish(ActionInvocationMementoDto)}.
+     */
+    @Deprecated
     @Programmatic
     void publish(EventMetadata metadata, EventPayload payload);
     

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublishingService2.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublishingService2.java b/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublishingService2.java
deleted file mode 100644
index 61ffed6..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublishingService2.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *  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 agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.isis.applib.services.publish;
-
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.schema.aim.v1.ActionInvocationMementoDto;
-
-public interface PublishingService2 extends PublishingService {
-
-    /**
-     * To support implementations that allow the republishing of commands, eg onto an JMS message bus.
-     */
-    @Programmatic
-    void republish(final ActionInvocationMementoDto aimDto);
-    
-}
-
-

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/applib/src/main/java/org/apache/isis/schema/utils/ActionInvocationMementoDtoUtils.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/schema/utils/ActionInvocationMementoDtoUtils.java b/core/applib/src/main/java/org/apache/isis/schema/utils/ActionInvocationMementoDtoUtils.java
index 3f6db44..f8287b9 100644
--- a/core/applib/src/main/java/org/apache/isis/schema/utils/ActionInvocationMementoDtoUtils.java
+++ b/core/applib/src/main/java/org/apache/isis/schema/utils/ActionInvocationMementoDtoUtils.java
@@ -38,8 +38,6 @@ import javax.xml.bind.JAXBException;
 import javax.xml.bind.Marshaller;
 import javax.xml.bind.Unmarshaller;
 
-import com.google.common.base.Function;
-import com.google.common.base.Strings;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.io.Resources;
@@ -50,33 +48,23 @@ import org.joda.time.LocalDateTime;
 import org.joda.time.LocalTime;
 
 import org.apache.isis.applib.services.bookmark.Bookmark;
-import org.apache.isis.schema.aim.v1.ActionInvocationMementoDto;
-import org.apache.isis.schema.aim.v1.ParamDto;
-import org.apache.isis.schema.common.v1.BookmarkObjectState;
+import org.apache.isis.applib.services.bookmark.BookmarkService;
+import org.apache.isis.schema.aim.v2.ActionInvocationDto;
+import org.apache.isis.schema.aim.v2.ActionInvocationMementoDto;
+import org.apache.isis.schema.aim.v2.ReturnDto;
+import org.apache.isis.schema.cmd.v1.ActionDto;
+import org.apache.isis.schema.cmd.v1.ParamDto;
 import org.apache.isis.schema.common.v1.OidDto;
+import org.apache.isis.schema.common.v1.PeriodDto;
 import org.apache.isis.schema.common.v1.ValueDto;
 import org.apache.isis.schema.common.v1.ValueType;
 import org.apache.isis.schema.utils.jaxbadapters.JavaSqlTimestampXmlGregorianCalendarAdapter;
-import org.apache.isis.schema.utils.jaxbadapters.JodaDateTimeXMLGregorianCalendarAdapter;
-import org.apache.isis.schema.utils.jaxbadapters.JodaLocalDateTimeXMLGregorianCalendarAdapter;
-import org.apache.isis.schema.utils.jaxbadapters.JodaLocalDateXMLGregorianCalendarAdapter;
-import org.apache.isis.schema.utils.jaxbadapters.JodaLocalTimeXMLGregorianCalendarAdapter;
 
 public final class ActionInvocationMementoDtoUtils {
 
-    //region > static
-    private static final Function<ParamDto, String> PARAM_DTO_TO_NAME = new Function<ParamDto, String>() {
-        @Override public String apply(final ParamDto input) {
-            return input.getParameterName();
-        }
-    };
-    private static final Function<ParamDto, ValueType> PARAM_DTO_TO_TYPE = new Function<ParamDto, ValueType>() {
-        @Override public ValueType apply(final ParamDto input) {
-            return input.getParameterType();
-        }
-    };
-    private static JAXBContext jaxbContext;
-    private static JAXBContext getJaxbContext() {
+    //region > marshalling
+    static JAXBContext jaxbContext;
+    static JAXBContext getJaxbContext() {
         if(jaxbContext == null) {
             try {
                 jaxbContext = JAXBContext.newInstance(ActionInvocationMementoDto.class);
@@ -86,225 +74,216 @@ public final class ActionInvocationMementoDtoUtils {
         }
         return jaxbContext;
     }
-    //endregion
 
-    public static ActionInvocationMementoDto newDto() {
-        return new ActionInvocationMementoDto();
+    public static ActionInvocationMementoDto fromXml(final Reader reader) {
+        try {
+            final Unmarshaller un = getJaxbContext().createUnmarshaller();
+            return (ActionInvocationMementoDto) un.unmarshal(reader);
+        } catch (JAXBException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static ActionInvocationMementoDto fromXml(final String xml) {
+        return fromXml(new StringReader(xml));
+    }
+
+    public static ActionInvocationMementoDto fromXml(
+            final Class<?> contextClass,
+            final String resourceName,
+            final Charset charset) throws IOException {
+        final URL url = Resources.getResource(contextClass, resourceName);
+        final String s = Resources.toString(url, charset);
+        return fromXml(new StringReader(s));
+    }
+
+    public static String toXml(final ActionInvocationMementoDto aimDto) {
+        final CharArrayWriter caw = new CharArrayWriter();
+        toXml(aimDto, caw);
+        return caw.toString();
+    }
+
+    public static void toXml(final ActionInvocationMementoDto aimDto, final Writer writer) {
+        try {
+            final Marshaller m = getJaxbContext().createMarshaller();
+            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+            m.marshal(aimDto, writer);
+        } catch (JAXBException e) {
+            throw new RuntimeException(e);
+        }
     }
+    //endregion
 
     //region > actionIdentifier, target
 
-    public static void setMetadata(
-            final ActionInvocationMementoDto aim,
+    public static ActionInvocationMementoDto newDto(
             final UUID transactionId,
             final int sequence,
-            final Timestamp timestamp,
-            final String targetClass,
-            final String targetAction,
             final String actionIdentifier,
-            final String targetObjectType,
-            final String targetObjectIdentifier,
+            final Bookmark targetBookmark,
             final String title,
-            final String user) {
-        ActionInvocationMementoDto.Metadata metadata = aim.getMetadata();
-        if(metadata == null) {
-            metadata = new ActionInvocationMementoDto.Metadata();
-            aim.setMetadata(metadata);
-        }
+            final String user,
+            final Timestamp timestamp) {
+
+        final ActionInvocationMementoDto aim = new ActionInvocationMementoDto();
+
+        aim.setMajorVersion("2");
+        aim.setMinorVersion("0");
 
-        metadata.setTransactionId(transactionId.toString());
-        metadata.setSequence(sequence);
-        metadata.setTimestamp(JavaSqlTimestampXmlGregorianCalendarAdapter.print(timestamp));
+        aim.setTransactionId(transactionId.toString());
 
-        metadata.setTargetClass(targetClass);
-        metadata.setTargetAction(targetAction);
-        metadata.setActionIdentifier(actionIdentifier);
+        ActionInvocationDto invocation = invocationFor(aim);
+
+        invocation.setSequence(sequence);
+        invocation.setId(aim.getTransactionId() + "." + invocation.getSequence());
 
         final OidDto target = new OidDto();
-        target.setObjectType(targetObjectType);
-        target.setObjectIdentifier(targetObjectIdentifier);
-        metadata.setTarget(target);
+        target.setObjectType(targetBookmark.getObjectType());
+        target.setObjectIdentifier(target.getObjectIdentifier());
+        invocation.setTarget(target);
+
+        invocation.setTitle(title);
+        invocation.setUser(user);
 
-        metadata.setTitle(title);
-        metadata.setUser(user);
-   }
+        ActionDto action = actionFor(invocation);
+        action.setActionIdentifier(actionIdentifier);
 
+        PeriodDto timings = timingsFor(invocation);
+        timings.setStart(JavaSqlTimestampXmlGregorianCalendarAdapter.print(timestamp));
+
+        return aim;
+    }
 
     //endregion
 
-    //region > addArgValue, addArgReference
-    public static boolean addArgValue(
-            final ActionInvocationMementoDto aim,
-            final String parameterName,
-            final Class<?> parameterType,
-            final Object arg) {
+    //region > invocationFor, actionFor, timingsFor
 
-        ParamDto paramDto = null;
-        if(parameterType == String.class) {
-            paramDto = newParamDto(aim, parameterName, ValueType.STRING, arg);
-        } else
-        if(parameterType == byte.class || parameterType == Byte.class) {
-            paramDto = newParamDto(aim, parameterName, ValueType.BYTE, arg);
-        } else
-        if(parameterType == short.class || parameterType == Short.class) {
-            paramDto = newParamDto(aim, parameterName, ValueType.SHORT, arg);
-        }else
-        if(parameterType == int.class || parameterType == Integer.class) {
-            paramDto = newParamDto(aim, parameterName, ValueType.INT, arg);
-        }else
-        if(parameterType == long.class || parameterType == Long.class) {
-            paramDto = newParamDto(aim, parameterName, ValueType.LONG, arg);
-        }else
-        if(parameterType == char.class || parameterType == Character.class) {
-            paramDto = newParamDto(aim, parameterName, ValueType.CHAR, arg);
-        }else
-        if(parameterType == boolean.class || parameterType == Boolean.class) {
-            paramDto = newParamDto(aim, parameterName, ValueType.BOOLEAN, arg);
-        }else
-        if(parameterType == float.class || parameterType == Float.class) {
-            paramDto = newParamDto(aim, parameterName, ValueType.FLOAT, arg);
-        }else
-        if(parameterType == double.class || parameterType == Double.class) {
-            paramDto = newParamDto(aim, parameterName, ValueType.DOUBLE, arg);
-        }else
-        if(parameterType == BigInteger.class) {
-            paramDto = newParamDto(aim, parameterName, ValueType.BIG_INTEGER, arg);
-        }else
-        if(parameterType == BigDecimal.class) {
-            paramDto = newParamDto(aim, parameterName, ValueType.BIG_DECIMAL, arg);
-        }else
-        if(parameterType == DateTime.class) {
-            paramDto = newParamDto(aim, parameterName, ValueType.JODA_DATE_TIME, arg);
-        }else
-        if(parameterType == LocalDateTime.class) {
-            paramDto = newParamDto(aim, parameterName, ValueType.JODA_LOCAL_DATE_TIME, arg);
-        }else
-        if(parameterType == LocalDate.class) {
-            paramDto = newParamDto(aim, parameterName, ValueType.JODA_LOCAL_DATE, arg);
-        }else
-        if(parameterType == LocalTime.class) {
-            paramDto = newParamDto(aim, parameterName, ValueType.JODA_LOCAL_TIME, arg);
+    private static ActionInvocationDto invocationFor(
+            final ActionInvocationMementoDto aim) {
+        ActionInvocationDto invocation = aim.getInvocation();
+        if(invocation == null) {
+            invocation = new ActionInvocationDto();
+            aim.setInvocation(invocation);
         }
+        return invocation;
+    }
 
-        if(paramDto != null) {
-            final ValueDto valueDto = valueDtoFor(paramDto);
-            setValue(valueDto, parameterType, arg);
-            return true;
+    private static ActionDto actionFor(final ActionInvocationDto invocation) {
+        ActionDto action = invocation.getAction();
+        if(action == null) {
+            action = new ActionDto();
+            invocation.setAction(action);
         }
-
-        // none of the supported value types
-        return false;
+        return action;
     }
 
-
-    public static void addArgReference(
-            final ActionInvocationMementoDto aim,
-            final String parameterName,
-            final Bookmark bookmark) {
-        final ParamDto paramDto = newParamDto(aim, parameterName, ValueType.REFERENCE, bookmark);
-        final ValueDto valueDto = valueDtoFor(paramDto);
-        OidDto argValue = asOidDto(bookmark);
-        valueDto.setReference(argValue);
+    private static List<ParamDto> parametersFor(final ActionInvocationMementoDto aim) {
+        return parametersFor(invocationFor(aim));
     }
 
-
-    private static OidDto asOidDto(final Bookmark reference) {
-        OidDto argValue;
-        if(reference != null) {
-            argValue = new OidDto();
-            argValue.setObjectType(reference.getObjectType());
-            argValue.setObjectState(bookmarkObjectStateOf(reference));
-            argValue.setObjectIdentifier(reference.getIdentifier());
-        } else {
-            argValue = null;
-        }
-        return argValue;
+    private static List<ParamDto> parametersFor(final ActionInvocationDto invocationDto) {
+        final ActionDto actionDto = actionFor(invocationDto);
+        return actionDto.getParameters();
     }
 
-    private static BookmarkObjectState bookmarkObjectStateOf(final Bookmark reference) {
-        switch(reference.getObjectState()) {
-        case PERSISTENT: return BookmarkObjectState.PERSISTENT;
-        case TRANSIENT: return BookmarkObjectState.TRANSIENT;
-        case VIEW_MODEL: return BookmarkObjectState.VIEW_MODEL;
+    private static PeriodDto timingsFor(final ActionInvocationDto invocation) {
+        PeriodDto timings = invocation.getTimings();
+        if(timings == null) {
+            timings = new PeriodDto();
+            invocation.setTimings(timings);
         }
-        throw new IllegalArgumentException(String.format("reference.objectState '%s' not recognized", reference.getObjectState()));
+        return timings;
     }
 
-    private static ParamDto newParamDto(
+    //endregion
+
+    //region > addParamArg
+
+    public static void addParamArg(
             final ActionInvocationMementoDto aim,
             final String parameterName,
-            final ValueType parameterType, final Object value) {
-        final ActionInvocationMementoDto.Payload.Parameters params = getParametersHolderAutoCreate(aim);
-        final ParamDto paramDto = newParamDto(parameterName, parameterType);
-        paramDto.setNull(value == null);
-        addParamNum(params, paramDto);
-        return paramDto;
-    }
+            final Class<?> parameterType,
+            final Object arg,
+            final BookmarkService bookmarkService) {
 
-    // lazily creates if required
-    private static ValueDto valueDtoFor(final ParamDto paramDto) {
-        ValueDto valueDto = paramDto.getValue();
-        if(valueDto == null) {
-            valueDto = new ValueDto();
-        }
-        paramDto.setValue(valueDto);
-        return valueDto;
+        final List<ParamDto> params = parametersFor(aim);
+        CommandMementoDtoUtils.addParamArg(params, parameterName, parameterType, arg, bookmarkService);
     }
 
-    private static ParamDto newParamDto(final String parameterName, final ValueType parameterType) {
-        final ParamDto argDto = new ParamDto();
-        argDto.setParameterName(parameterName);
-        argDto.setParameterType(parameterType);
-        return argDto;
-    }
+    //region > addReturn
 
-    //endregion
+    /**
+     *
+     * @param aim
+     * @param returnType - to determine the value type (if any)
+     * @param result - either a value type (possibly boxed primitive), or a reference type
+     * @param bookmarkService - used if not a value type
+     */
+    public static void addReturn(
+            final ActionInvocationMementoDto aim,
+            final Class<?> returnType,
+            final Object result,
+            final BookmarkService bookmarkService) {
+        boolean isValueType = ActionInvocationMementoDtoUtils.addReturnValue(aim, returnType, result);
+        if(!isValueType) {
+            ActionInvocationMementoDtoUtils.addReturnReference(aim, bookmarkService.bookmarkFor(result));
+        }
+    }
 
-    //region > addReturnValue, addReturnReference
     public static boolean addReturnValue(
             final ActionInvocationMementoDto aim,
             final Class<?> returnType,
             final Object returnVal) {
-        final ValueDto valueDto = returnValueDtoFor(aim);
-        return setValue(valueDto, returnType, returnVal);
+        final ReturnDto returnDto = returnValueDtoFor(aim);
+        return setValue(returnDto, returnType, returnVal);
     }
 
     public static void addReturnReference(
             final ActionInvocationMementoDto aim,
             final Bookmark bookmark) {
-        final ValueDto valueDto = returnValueDtoFor(aim);
-        OidDto argValue = asOidDto(bookmark);
-        valueDto.setReference(argValue);
+        final ReturnDto returnedDto = returnValueDtoFor(aim);
+        OidDto oidDto = CommonDtoUtils.asOidDto(bookmark);
+        ValueDto value = new ValueDto();
+        value.setReference(oidDto);
+        returnedDto.setValue(value);
+        returnedDto.setReturnType(ValueType.REFERENCE);
+    }
+
+    private static ReturnDto returnValueDtoFor(final ActionInvocationMementoDto aim) {
+        ActionInvocationDto invocationDto = invocationFor(aim);
+        ReturnDto returned = invocationDto.getReturned();
+        if(returned == null) {
+            returned = new ReturnDto();
+            invocationDto.setReturned(returned);
+        }
+        return returned;
     }
 
     //endregion
 
 
-
-
-    //region > getNumberOfParameters, getParameters, getParameterNames, getParameterTypes
-    public static int getNumberOfParameters(final ActionInvocationMementoDto aim) {
-        final ActionInvocationMementoDto.Payload.Parameters params = getParametersHolderElseThrow(aim);
-        if(params == null) {
-            return 0;
-        }
-        return params.getNum();
-    }
+    //region > getParameters, getParameterNames, getParameterTypes
     public static List<ParamDto> getParameters(final ActionInvocationMementoDto aim) {
-        final ActionInvocationMementoDto.Payload.Parameters params = getParametersHolderElseThrow(aim);
+        final List<ParamDto> params = parametersFor(aim);
         final int parameterNumber = getNumberOfParameters(aim);
         final List<ParamDto> paramDtos = Lists.newArrayList();
         for (int i = 0; i < parameterNumber; i++) {
-            final ParamDto paramDto = params.getParam().get(i);
+            final ParamDto paramDto = params.get(i);
             paramDtos.add(paramDto);
         }
         return Collections.unmodifiableList(paramDtos);
     }
+
+    private static int getNumberOfParameters(final ActionInvocationMementoDto aim) {
+        final List<ParamDto> params = parametersFor(aim);
+        return params != null ? params.size() : 0;
+    }
+
     public static List<String> getParameterNames(final ActionInvocationMementoDto aim) {
-        return immutableList(Iterables.transform(getParameters(aim), PARAM_DTO_TO_NAME));
+        return immutableList(Iterables.transform(getParameters(aim), CommonDtoUtils.PARAM_DTO_TO_NAME));
     }
     public static List<ValueType> getParameterTypes(final ActionInvocationMementoDto aim) {
-        return immutableList(Iterables.transform(getParameters(aim), PARAM_DTO_TO_TYPE));
+        return immutableList(Iterables.transform(getParameters(aim), CommonDtoUtils.PARAM_DTO_TO_TYPE));
     }
     //endregion
 
@@ -318,17 +297,17 @@ public final class ActionInvocationMementoDtoUtils {
         return parameters.get(paramNum);
     }
 
-    public static ValueDto getParameterValue(final ActionInvocationMementoDto aim, final int paramNum) {
+    public static ValueDto getParameterArg(final ActionInvocationMementoDto aim, final int paramNum) {
         final ParamDto paramDto = getParameter(aim, paramNum);
-        return valueDtoFor(paramDto);
+        return CommandMementoDtoUtils.argumentFor(paramDto);
     }
 
 
     public static String getParameterName(final ActionInvocationMementoDto aim, final int paramNum) {
-        return PARAM_DTO_TO_NAME.apply(getParameter(aim, paramNum));
+        return CommonDtoUtils.PARAM_DTO_TO_NAME.apply(getParameter(aim, paramNum));
     }
     public static ValueType getParameterType(final ActionInvocationMementoDto aim, final int paramNum) {
-        return PARAM_DTO_TO_TYPE.apply(getParameter(aim, paramNum));
+        return CommonDtoUtils.PARAM_DTO_TO_TYPE.apply(getParameter(aim, paramNum));
     }
     public static boolean isNull(final ActionInvocationMementoDto aim, int paramNum) {
         final ParamDto paramDto = getParameter(aim, paramNum);
@@ -342,217 +321,75 @@ public final class ActionInvocationMementoDtoUtils {
         if(paramDto.isNull()) {
             return null;
         }
-        final ValueDto valueDto = valueDtoFor(paramDto);
+        final ValueDto valueDto = CommandMementoDtoUtils.argumentFor(paramDto);
         final ValueType parameterType = paramDto.getParameterType();
-        switch(parameterType) {
-        case STRING:
-            return (T) valueDto.getString();
-        case BYTE:
-            return (T) valueDto.getByte();
-        case SHORT:
-            return (T) valueDto.getShort();
-        case INT:
-            return (T) valueDto.getInt();
-        case LONG:
-            return (T) valueDto.getLong();
-        case FLOAT:
-            return (T) valueDto.getFloat();
-        case DOUBLE:
-            return (T) valueDto.getDouble();
-        case BOOLEAN:
-            return (T) valueDto.isBoolean();
-        case CHAR:
-            final String aChar = valueDto.getChar();
-            if(Strings.isNullOrEmpty(aChar)) { return null; }
-            return (T) (Object)aChar.charAt(0);
-        case BIG_DECIMAL:
-            return (T) valueDto.getBigDecimal();
-        case BIG_INTEGER:
-            return (T) valueDto.getBigInteger();
-        case JODA_DATE_TIME:
-            return (T) JodaDateTimeXMLGregorianCalendarAdapter.parse(valueDto.getDateTime());
-        case JODA_LOCAL_DATE:
-            return (T) JodaLocalDateXMLGregorianCalendarAdapter.parse(valueDto.getLocalDate());
-        case JODA_LOCAL_DATE_TIME:
-            return (T) JodaLocalDateTimeXMLGregorianCalendarAdapter.parse(valueDto.getLocalDateTime());
-        case JODA_LOCAL_TIME:
-            return (T) JodaLocalTimeXMLGregorianCalendarAdapter.parse(valueDto.getLocalTime());
-        case REFERENCE:
-            return (T) valueDto.getReference();
-        }
-        throw new IllegalStateException("Parameter type was not recognised (possible bug)");
-    }
-    //endregion
-
-    //region > marshalling
-    public static ActionInvocationMementoDto fromXml(Reader reader) {
-        Unmarshaller un = null;
-        try {
-            un = getJaxbContext().createUnmarshaller();
-            return (ActionInvocationMementoDto) un.unmarshal(reader);
-        } catch (JAXBException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static ActionInvocationMementoDto fromXml(
-            final Class<?> contextClass,
-            final String resourceName,
-            final Charset charset) throws IOException {
-        final URL url = Resources.getResource(contextClass, resourceName);
-        final String s = Resources.toString(url, charset);
-        return fromXml(new StringReader(s));
-    }
-
-    public static String toXml(final ActionInvocationMementoDto aim) {
-        final CharArrayWriter caw = new CharArrayWriter();
-        toXml(aim, caw);
-        return caw.toString();
+        return CommonDtoUtils.getValue(valueDto, parameterType);
     }
 
-    public static void toXml(final ActionInvocationMementoDto aim, final Writer writer) {
-        Marshaller m = null;
-        try {
-            m = getJaxbContext().createMarshaller();
-            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
-            m.marshal(aim, writer);
-        } catch (JAXBException e) {
-            throw new RuntimeException(e);
-        }
-    }
-    //endregion
-
-    //region > debugging
-    public static void dump(final ActionInvocationMementoDto aim, final PrintStream out) throws JAXBException {
-        out.println(toXml(aim));
-    }
     //endregion
 
-    //region > helpers
-    private static void addParamNum(final ActionInvocationMementoDto.Payload.Parameters params, final ParamDto arg) {
-        params.getParam().add(arg);
-        Integer num = params.getNum();
-        if(num == null) {
-            num = 0;
-        }
-        params.setNum(num +1);
-    }
 
-    private static ActionInvocationMementoDto.Payload.Parameters getParametersHolderElseThrow(final ActionInvocationMementoDto aim) {
-        final ActionInvocationMementoDto.Payload payload = getPayloadElseThrow(aim);
-        final ActionInvocationMementoDto.Payload.Parameters parameters = payload.getParameters();
-        if(parameters == null) {
-            throw new IllegalStateException("No parameters have been added");
-        }
-        return parameters;
+    private static <T> List<T> immutableList(final Iterable<T> iterable) {
+        return Collections.unmodifiableList(Lists.newArrayList(iterable));
     }
 
-    private static ActionInvocationMementoDto.Payload.Parameters getParametersHolderAutoCreate(final ActionInvocationMementoDto aim) {
-        final ActionInvocationMementoDto.Payload payload = getPayloadAutoCreate(aim);
-        ActionInvocationMementoDto.Payload.Parameters params = payload.getParameters();
-        if(params == null) {
-            params = new ActionInvocationMementoDto.Payload.Parameters();
-            payload.setParameters(params);
-        }
-        return params;
+    private static boolean setValue(
+            final ReturnDto returnDto,
+            final Class<?> type,
+            final Object val) {
+        ValueDto valueDto = new ValueDto();
+        returnDto.setValue(valueDto);
+        setValueType(returnDto, type);
+        return CommonDtoUtils.setValue(valueDto, type, val);
     }
 
-    private static ValueDto returnValueDtoFor(final ActionInvocationMementoDto aim) {
-        final ActionInvocationMementoDto.Payload payload = getPayloadAutoCreate(aim);
-        ValueDto valueDto = payload.getReturn();
-        if(valueDto == null) {
-            valueDto = new ValueDto();
-            payload.setReturn(valueDto);
-        }
-        return valueDto;
-    }
-
-    private static ActionInvocationMementoDto.Payload getPayloadAutoCreate(final ActionInvocationMementoDto aim) {
-        ActionInvocationMementoDto.Payload payload = aim.getPayload();
-        if(payload == null) {
-            payload = new ActionInvocationMementoDto.Payload();
-            aim.setPayload(payload);
-        }
-        return payload;
-    }
-
-    private static ActionInvocationMementoDto.Payload getPayloadElseThrow(final ActionInvocationMementoDto aim) {
-        ActionInvocationMementoDto.Payload payload = aim.getPayload();
-        if(payload == null) {
-            throw new IllegalStateException("No payload has been added");
-        }
-        return payload;
-    }
-
-    private static <T> List<T> immutableList(final Iterable<T> transform) {
-        return Collections.unmodifiableList(
-                Lists.newArrayList(
-                        transform
-                )
-        );
-    }
-
-
-    private static boolean setValue(final ValueDto valueDto, final Class<?> type, final Object returnVal) {
+    private static boolean setValueType(
+            final ReturnDto returnDto,
+            final Class<?> type) {
         if(type == String.class) {
-            final String argValue = (String) returnVal;
-            valueDto.setString(argValue);
+            returnDto.setReturnType(ValueType.STRING);
         } else
         if(type == byte.class || type == Byte.class) {
-            final Byte argValue = (Byte) returnVal;
-            valueDto.setByte(argValue);
+            returnDto.setReturnType(ValueType.BYTE);
         } else
         if(type == short.class || type == Short.class) {
-            final Short argValue = (Short) returnVal;
-            valueDto.setShort(argValue);
+            returnDto.setReturnType(ValueType.SHORT);
         }else
         if(type == int.class || type == Integer.class) {
-            final Integer argValue = (Integer) returnVal;
-            valueDto.setInt(argValue);
+            returnDto.setReturnType(ValueType.INT);
         }else
         if(type == long.class || type == Long.class) {
-            final Long argValue = (Long) returnVal;
-            valueDto.setLong(argValue);
+            returnDto.setReturnType(ValueType.LONG);
         }else
         if(type == char.class || type == Character.class) {
-            final Character argValue = (Character) returnVal;
-            valueDto.setChar("" + argValue);
+            returnDto.setReturnType(ValueType.CHAR);
         }else
         if(type == boolean.class || type == Boolean.class) {
-            final Boolean argValue = (Boolean) returnVal;
-            valueDto.setBoolean(argValue);
+            returnDto.setReturnType(ValueType.BOOLEAN);
         }else
         if(type == float.class || type == Float.class) {
-            final Float argValue = (Float) returnVal;
-            valueDto.setFloat(argValue);
+            returnDto.setReturnType(ValueType.FLOAT);
         }else
         if(type == double.class || type == Double.class) {
-            final Double argValue = (Double) returnVal;
-            valueDto.setDouble(argValue);
+            returnDto.setReturnType(ValueType.DOUBLE);
         }else
         if(type == BigInteger.class) {
-            final BigInteger argValue = (BigInteger) returnVal;
-            valueDto.setBigInteger(argValue);
+            returnDto.setReturnType(ValueType.BIG_INTEGER);
         }else
         if(type == BigDecimal.class) {
-            final BigDecimal argValue = (BigDecimal) returnVal;
-            valueDto.setBigDecimal(argValue);
+            returnDto.setReturnType(ValueType.BIG_DECIMAL);
         }else
         if(type == DateTime.class) {
-            final DateTime argValue = (DateTime) returnVal;
-            valueDto.setDateTime(JodaDateTimeXMLGregorianCalendarAdapter.print(argValue));
+            returnDto.setReturnType(ValueType.JODA_DATE_TIME);
         }else
         if(type == LocalDateTime.class) {
-            final LocalDateTime argValue = (LocalDateTime) returnVal;
-            valueDto.setLocalDateTime(JodaLocalDateTimeXMLGregorianCalendarAdapter.print(argValue));
+            returnDto.setReturnType(ValueType.JODA_LOCAL_DATE_TIME);
         }else
         if(type == LocalDate.class) {
-            final LocalDate argValue = (LocalDate) returnVal;
-            valueDto.setLocalDate(JodaLocalDateXMLGregorianCalendarAdapter.print(argValue));
+            returnDto.setReturnType(ValueType.JODA_LOCAL_DATE);
         }else
         if(type == LocalTime.class) {
-            final LocalTime argValue = (LocalTime) returnVal;
-            valueDto.setLocalTime(JodaLocalTimeXMLGregorianCalendarAdapter.print(argValue));
+            returnDto.setReturnType(ValueType.JODA_LOCAL_TIME);
         }else
         {
             // none of the supported value types
@@ -561,6 +398,13 @@ public final class ActionInvocationMementoDtoUtils {
         return true;
     }
 
+
+    //endregion
+
+    //region > debugging
+    public static void dump(final ActionInvocationMementoDto aim, final PrintStream out) throws JAXBException {
+        out.println(toXml(aim));
+    }
     //endregion
 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/applib/src/main/java/org/apache/isis/schema/utils/CommandMementoDtoUtils.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/schema/utils/CommandMementoDtoUtils.java b/core/applib/src/main/java/org/apache/isis/schema/utils/CommandMementoDtoUtils.java
new file mode 100644
index 0000000..5719d97
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/schema/utils/CommandMementoDtoUtils.java
@@ -0,0 +1,263 @@
+/*
+ *  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 agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.schema.utils;
+
+import java.io.CharArrayWriter;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.Writer;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.UUID;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import com.google.common.io.Resources;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.joda.time.LocalDateTime;
+import org.joda.time.LocalTime;
+
+import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.applib.services.bookmark.BookmarkService;
+import org.apache.isis.schema.cmd.v1.ActionDto;
+import org.apache.isis.schema.cmd.v1.CommandMementoDto;
+import org.apache.isis.schema.cmd.v1.ParamDto;
+import org.apache.isis.schema.common.v1.OidDto;
+import org.apache.isis.schema.common.v1.ValueDto;
+import org.apache.isis.schema.common.v1.ValueType;
+
+public final class CommandMementoDtoUtils {
+
+    //region > marshalling
+    static JAXBContext jaxbContext;
+    static JAXBContext getJaxbContext() {
+        if(jaxbContext == null) {
+            try {
+                jaxbContext = JAXBContext.newInstance(CommandMementoDto.class);
+            } catch (JAXBException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        return jaxbContext;
+    }
+
+    public static CommandMementoDto fromXml(final Reader reader) {
+        try {
+            final Unmarshaller un = getJaxbContext().createUnmarshaller();
+            return (CommandMementoDto) un.unmarshal(reader);
+        } catch (JAXBException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static CommandMementoDto fromXml(final String xml) {
+        return fromXml(new StringReader(xml));
+    }
+
+    public static CommandMementoDto fromXml(
+            final Class<?> contextClass,
+            final String resourceName,
+            final Charset charset) throws IOException {
+        final URL url = Resources.getResource(contextClass, resourceName);
+        final String s = Resources.toString(url, charset);
+        return fromXml(new StringReader(s));
+    }
+
+    public static String toXml(final CommandMementoDto aimDto) {
+        final CharArrayWriter caw = new CharArrayWriter();
+        toXml(aimDto, caw);
+        return caw.toString();
+    }
+
+    public static void toXml(final CommandMementoDto aimDto, final Writer writer) {
+        try {
+            final Marshaller m = getJaxbContext().createMarshaller();
+            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+            m.marshal(aimDto, writer);
+        } catch (JAXBException e) {
+            throw new RuntimeException(e);
+        }
+    }
+    //endregion
+
+    public static CommandMementoDto newDto(
+            final UUID transactionId, final String user) {
+        CommandMementoDto dto = new CommandMementoDto();
+
+        dto.setMajorVersion("1");
+        dto.setMinorVersion("0");
+
+        dto.setTransactionId(transactionId.toString());
+
+        ActionDto actionDto = new ActionDto();
+        dto.setAction(actionDto);
+
+
+        dto.setUser(user);
+
+        return dto;
+    }
+
+
+    static ValueDto argumentFor(final ParamDto paramDto) {
+        ValueDto valueDto = paramDto.getArgument();
+        if(valueDto == null) {
+            valueDto = new ValueDto();
+            paramDto.setArgument(valueDto);
+        }
+        return valueDto;
+    }
+
+    /**
+     *
+     * @param params
+     * @param parameterName
+     * @param parameterType - to determine the value type (if any)
+     * @param arg - either a value type (possibly boxed primitive), or a reference type
+     * @param bookmarkService - used if not a value type
+     */
+    public static void addParamArg(
+            final List<ParamDto> params,
+            final String parameterName,
+            final Class<?> parameterType,
+            final Object arg,
+            final BookmarkService bookmarkService) {
+        boolean isValueType = addParamArgValue(params, parameterName, parameterType, arg);
+        if(!isValueType) {
+            addParamArgReference(
+                    params, parameterName,
+                    arg instanceof Bookmark
+                            ? (Bookmark)arg
+                            : bookmarkService.bookmarkFor(arg));
+        }
+    }
+
+    private static boolean addParamArgValue(
+            final List<ParamDto> params,
+            final String parameterName,
+            final Class<?> parameterType, final Object arg) {
+        ParamDto paramDto = null;
+        if(parameterType == String.class) {
+            paramDto = newParamDto(params, parameterName, ValueType.STRING, arg);
+        } else
+        if(parameterType == byte.class || parameterType == Byte.class) {
+            paramDto = newParamDto(params, parameterName, ValueType.BYTE, arg);
+        } else
+        if(parameterType == short.class || parameterType == Short.class) {
+            paramDto = newParamDto(params, parameterName, ValueType.SHORT, arg);
+        }else
+        if(parameterType == int.class || parameterType == Integer.class) {
+            paramDto = newParamDto(params, parameterName, ValueType.INT, arg);
+        }else
+        if(parameterType == long.class || parameterType == Long.class) {
+            paramDto = newParamDto(params, parameterName, ValueType.LONG, arg);
+        }else
+        if(parameterType == char.class || parameterType == Character.class) {
+            paramDto = newParamDto(params, parameterName, ValueType.CHAR, arg);
+        }else
+        if(parameterType == boolean.class || parameterType == Boolean.class) {
+            paramDto = newParamDto(params, parameterName, ValueType.BOOLEAN, arg);
+        }else
+        if(parameterType == float.class || parameterType == Float.class) {
+            paramDto = newParamDto(params, parameterName, ValueType.FLOAT, arg);
+        }else
+        if(parameterType == double.class || parameterType == Double.class) {
+            paramDto = newParamDto(params, parameterName, ValueType.DOUBLE, arg);
+        }else
+        if(parameterType == BigInteger.class) {
+            paramDto = newParamDto(params, parameterName, ValueType.BIG_INTEGER, arg);
+        }else
+        if(parameterType == BigDecimal.class) {
+            paramDto = newParamDto(params, parameterName, ValueType.BIG_DECIMAL, arg);
+        }else
+        if(parameterType == DateTime.class) {
+            paramDto = newParamDto(params, parameterName, ValueType.JODA_DATE_TIME, arg);
+        }else
+        if(parameterType == LocalDateTime.class) {
+            paramDto =
+                    newParamDto(params, parameterName, ValueType.JODA_LOCAL_DATE_TIME, arg);
+        }else
+        if(parameterType == LocalDate.class) {
+            paramDto = newParamDto(params, parameterName, ValueType.JODA_LOCAL_DATE, arg);
+        }else
+        if(parameterType == LocalTime.class) {
+            paramDto = newParamDto(params, parameterName, ValueType.JODA_LOCAL_TIME, arg);
+        }
+
+        if(paramDto != null) {
+            final ValueDto valueDto = argumentFor(paramDto);
+
+            CommonDtoUtils.setValue(valueDto, parameterType, arg);
+            return true;
+        }
+
+        // none of the supported value types
+        return false;
+    }
+
+    private static void addParamArgReference(
+            final List<ParamDto> params,
+            final String parameterName,
+            final Bookmark bookmark) {
+        final ParamDto paramDto =
+                newParamDto(params, parameterName, ValueType.REFERENCE, bookmark);
+        final ValueDto valueDto = argumentFor(paramDto);
+        OidDto argValue = CommonDtoUtils.asOidDto(bookmark);
+        valueDto.setReference(argValue);
+    }
+
+    private static ParamDto newParamDto(
+            final List<ParamDto> params,
+            final String parameterName,
+            final ValueType parameterType,
+            final Object value) {
+        final ParamDto paramDto = newParamDto(parameterName, parameterType);
+        paramDto.setNull(value == null);
+        params.add(paramDto);
+        return paramDto;
+    }
+
+    private static ParamDto newParamDto(
+            final String parameterName,
+            final ValueType parameterType) {
+        final ParamDto argDto = new ParamDto();
+        argDto.setParameterName(parameterName);
+        argDto.setParameterType(parameterType);
+        return argDto;
+    }
+
+    public static Object paramArgOf(final ParamDto paramDto) {
+        if(paramDto.isNull()) {
+            return null;
+        }
+        final ValueType parameterType = paramDto.getParameterType();
+        final ValueDto argument = paramDto.getArgument();
+        return CommonDtoUtils.getValue(argument, parameterType);
+    }
+
+}


[2/3] isis git commit: ISIS-1291: memento xsd schemas + utils; new command memento DTO for Command#memento, updated background service, background execution; new PublisherService

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/applib/src/main/java/org/apache/isis/schema/utils/CommonDtoUtils.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/schema/utils/CommonDtoUtils.java b/core/applib/src/main/java/org/apache/isis/schema/utils/CommonDtoUtils.java
new file mode 100644
index 0000000..41f102f
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/schema/utils/CommonDtoUtils.java
@@ -0,0 +1,183 @@
+/*
+ *  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 agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.schema.utils;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import javax.annotation.Nullable;
+
+import com.google.common.base.Function;
+import com.google.common.base.Strings;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.joda.time.LocalDateTime;
+import org.joda.time.LocalTime;
+
+import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.schema.cmd.v1.ParamDto;
+import org.apache.isis.schema.common.v1.OidDto;
+import org.apache.isis.schema.common.v1.ValueDto;
+import org.apache.isis.schema.common.v1.ValueType;
+import org.apache.isis.schema.utils.jaxbadapters.JodaDateTimeXMLGregorianCalendarAdapter;
+import org.apache.isis.schema.utils.jaxbadapters.JodaLocalDateTimeXMLGregorianCalendarAdapter;
+import org.apache.isis.schema.utils.jaxbadapters.JodaLocalDateXMLGregorianCalendarAdapter;
+import org.apache.isis.schema.utils.jaxbadapters.JodaLocalTimeXMLGregorianCalendarAdapter;
+
+public final class CommonDtoUtils {
+
+    public static final Function<OidDto, String> OID_DTO_2_STR = new Function<OidDto, String>() {
+        @Nullable @Override
+        public String apply(final OidDto oidDto) {
+            final Bookmark bookmark = Bookmark.from(oidDto);
+            return bookmark.toString();
+        }
+    };
+
+    public static final Function<ParamDto, String> PARAM_DTO_TO_NAME = new Function<ParamDto, String>() {
+        @Override public String apply(final ParamDto paramDto) {
+            return paramDto.getParameterName();
+        }
+    };
+    public static final Function<ParamDto, ValueType> PARAM_DTO_TO_TYPE = new Function<ParamDto, ValueType>() {
+        @Override public ValueType apply(final ParamDto paramDto) {
+            return paramDto.getParameterType();
+        }
+    };
+
+    public static boolean setValue(
+            final ValueDto valueDto,
+            final Class<?> type,
+            final Object val) {
+        if(type == String.class) {
+            final String argValue = (String) val;
+            valueDto.setString(argValue);
+        } else
+        if(type == byte.class || type == Byte.class) {
+            final Byte argValue = (Byte) val;
+            valueDto.setByte(argValue);
+        } else
+        if(type == short.class || type == Short.class) {
+            final Short argValue = (Short) val;
+            valueDto.setShort(argValue);
+        }else
+        if(type == int.class || type == Integer.class) {
+            final Integer argValue = (Integer) val;
+            valueDto.setInt(argValue);
+        }else
+        if(type == long.class || type == Long.class) {
+            final Long argValue = (Long) val;
+            valueDto.setLong(argValue);
+        }else
+        if(type == char.class || type == Character.class) {
+            final Character argValue = (Character) val;
+            valueDto.setChar("" + argValue);
+        }else
+        if(type == boolean.class || type == Boolean.class) {
+            final Boolean argValue = (Boolean) val;
+            valueDto.setBoolean(argValue);
+        }else
+        if(type == float.class || type == Float.class) {
+            final Float argValue = (Float) val;
+            valueDto.setFloat(argValue);
+        }else
+        if(type == double.class || type == Double.class) {
+            final Double argValue = (Double) val;
+            valueDto.setDouble(argValue);
+        }else
+        if(type == BigInteger.class) {
+            final BigInteger argValue = (BigInteger) val;
+            valueDto.setBigInteger(argValue);
+        }else
+        if(type == BigDecimal.class) {
+            final BigDecimal argValue = (BigDecimal) val;
+            valueDto.setBigDecimal(argValue);
+        }else
+        if(type == DateTime.class) {
+            final DateTime argValue = (DateTime) val;
+            valueDto.setDateTime(JodaDateTimeXMLGregorianCalendarAdapter.print(argValue));
+        }else
+        if(type == LocalDateTime.class) {
+            final LocalDateTime argValue = (LocalDateTime) val;
+            valueDto.setLocalDateTime(JodaLocalDateTimeXMLGregorianCalendarAdapter.print(argValue));
+        }else
+        if(type == LocalDate.class) {
+            final LocalDate argValue = (LocalDate) val;
+            valueDto.setLocalDate(JodaLocalDateXMLGregorianCalendarAdapter.print(argValue));
+        }else
+        if(type == LocalTime.class) {
+            final LocalTime argValue = (LocalTime) val;
+            valueDto.setLocalTime(JodaLocalTimeXMLGregorianCalendarAdapter.print(argValue));
+        }else
+        {
+            // none of the supported value types
+            return false;
+        }
+        return true;
+    }
+
+    public static <T> T getValue(
+            final ValueDto valueDto,
+            final ValueType valueType) {
+        switch(valueType) {
+        case STRING:
+            return (T) valueDto.getString();
+        case BYTE:
+            return (T) valueDto.getByte();
+        case SHORT:
+            return (T) valueDto.getShort();
+        case INT:
+            return (T) valueDto.getInt();
+        case LONG:
+            return (T) valueDto.getLong();
+        case FLOAT:
+            return (T) valueDto.getFloat();
+        case DOUBLE:
+            return (T) valueDto.getDouble();
+        case BOOLEAN:
+            return (T) valueDto.isBoolean();
+        case CHAR:
+            final String aChar = valueDto.getChar();
+            if(Strings.isNullOrEmpty(aChar)) { return null; }
+            return (T) (Object)aChar.charAt(0);
+        case BIG_DECIMAL:
+            return (T) valueDto.getBigDecimal();
+        case BIG_INTEGER:
+            return (T) valueDto.getBigInteger();
+        case JODA_DATE_TIME:
+            return (T) JodaDateTimeXMLGregorianCalendarAdapter.parse(valueDto.getDateTime());
+        case JODA_LOCAL_DATE:
+            return (T) JodaLocalDateXMLGregorianCalendarAdapter.parse(valueDto.getLocalDate());
+        case JODA_LOCAL_DATE_TIME:
+            return (T) JodaLocalDateTimeXMLGregorianCalendarAdapter.parse(valueDto.getLocalDateTime());
+        case JODA_LOCAL_TIME:
+            return (T) JodaLocalTimeXMLGregorianCalendarAdapter.parse(valueDto.getLocalTime());
+        case REFERENCE:
+            return (T) valueDto.getReference();
+        }
+        throw new IllegalStateException("Value type was not recognised (possible bug)");
+    }
+
+    public static OidDto asOidDto(final Bookmark reference) {
+        return reference != null ? reference.toOidDto() : null;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/applib/src/test/java/org/apache/isis/schema/utils/Roundtrip.java
----------------------------------------------------------------------
diff --git a/core/applib/src/test/java/org/apache/isis/schema/utils/Roundtrip.java b/core/applib/src/test/java/org/apache/isis/schema/utils/Roundtrip.java
index bc8a44d..5be8a88 100644
--- a/core/applib/src/test/java/org/apache/isis/schema/utils/Roundtrip.java
+++ b/core/applib/src/test/java/org/apache/isis/schema/utils/Roundtrip.java
@@ -30,7 +30,7 @@ import org.joda.time.LocalTime;
 import org.junit.Test;
 
 import org.apache.isis.applib.services.bookmark.Bookmark;
-import org.apache.isis.schema.aim.v1.ActionInvocationMementoDto;
+import org.apache.isis.schema.aim.v2.ActionInvocationMementoDto;
 import org.apache.isis.schema.common.v1.OidDto;
 import org.apache.isis.schema.common.v1.ValueType;
 
@@ -45,63 +45,60 @@ public class Roundtrip {
     public void happyCase() throws Exception {
 
         // given
-        final ActionInvocationMementoDto aim = ActionInvocationMementoDtoUtils.newDto();
-
-        ActionInvocationMementoDtoUtils.setMetadata(
-                aim,
+        final ActionInvocationMementoDto aim = ActionInvocationMementoDtoUtils.newDto(
                 UUID.randomUUID(),
                 1,
-                new java.sql.Timestamp(new java.util.Date().getTime()),
-                "com.mycompany.myapp.Customer", "placeOrder", "com.mycompany.myapp.Customer#placeOrder",
-                "CUS", "12345", "John Customer", "freddyUser");
+                "com.mycompany.myapp.Customer#placeOrder",
+                new Bookmark("CUS", "12345"), "John Customer", "freddyUser",
+                new java.sql.Timestamp(new java.util.Date().getTime()));
 
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "aString", String.class, "Fred");
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "nullString", String.class, (String) null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "aString", String.class, "Fred", null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "nullString", String.class, (String) null, null);
 
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "aByte", Byte.class, (Byte) (byte) 123);
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "nullByte", Byte.class, (Byte) null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "aByte", Byte.class, (Byte) (byte) 123, null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "nullByte", Byte.class, (Byte) null, null);
 
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "aShort", Short.class, (Short) (short) 32123);
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "nullShort", Short.class, (Short) null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "aShort", Short.class, (Short) (short) 32123, null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "nullShort", Short.class, (Short) null, null);
 
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "anInt", Integer.class, 123454321);
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "nullInt", Integer.class, (Integer) null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "anInt", Integer.class, 123454321, null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "nullInt", Integer.class, (Integer) null, null);
 
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "aLong", Long.class, 1234567654321L);
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "nullLong", Long.class, (Long) null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "aLong", Long.class, 1234567654321L, null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "nullLong", Long.class, (Long) null, null);
 
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "aFloat", Float.class, 12345.6789F);
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "nullFloat", Float.class, (Float) null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "aFloat", Float.class, 12345.6789F, null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "nullFloat", Float.class, (Float) null, null);
 
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "aDouble", Double.class, 12345678.90123);
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "nullDouble", Double.class, (Double) null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "aDouble", Double.class, 12345678.90123, null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "nullDouble", Double.class, (Double) null, null);
 
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "aBoolean", Boolean.class, true);
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "nullBoolean", Boolean.class, (Boolean) null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "aBoolean", Boolean.class, true, null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "nullBoolean", Boolean.class, (Boolean) null, null);
 
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "aChar", Character.class, 'x');
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "nullChar", Character.class, (Character) null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "aChar", Character.class, 'x', null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "nullChar", Character.class, (Character) null, null);
 
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "aBigInteger", java.math.BigInteger.class, new java.math.BigInteger("12345678901234567890"));
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "nullBigInteger", java.math.BigInteger.class, (java.math.BigInteger) null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "aBigInteger", java.math.BigInteger.class, new java.math.BigInteger("12345678901234567890"), null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "nullBigInteger", java.math.BigInteger.class, (java.math.BigInteger) null, null);
 
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "aBigDecimal", java.math.BigDecimal.class, new java.math.BigDecimal("12345678901234567890"));
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "nullBigDecimal", java.math.BigDecimal.class, (java.math.BigDecimal) null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "aBigDecimal", java.math.BigDecimal.class, new java.math.BigDecimal("12345678901234567890"), null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "nullBigDecimal", java.math.BigDecimal.class, (java.math.BigDecimal) null, null);
 
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "aJodaDateTime", org.joda.time.DateTime.class, new org.joda.time.DateTime(2015, 5, 23, 9, 54, 1));
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "nullJodaDateTime", org.joda.time.DateTime.class, (org.joda.time.DateTime) null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "aJodaDateTime", org.joda.time.DateTime.class, new org.joda.time.DateTime(2015, 5, 23, 9, 54, 1), null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "nullJodaDateTime", org.joda.time.DateTime.class, (org.joda.time.DateTime) null, null);
 
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "aJodaLocalDate", org.joda.time.LocalDate.class, new org.joda.time.LocalDate(2015, 5, 23));
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "nullJodaLocalDate", org.joda.time.LocalDate.class, (org.joda.time.LocalDate) null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "aJodaLocalDate", org.joda.time.LocalDate.class, new org.joda.time.LocalDate(2015, 5, 23), null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "nullJodaLocalDate", org.joda.time.LocalDate.class, (org.joda.time.LocalDate) null, null);
 
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "aJodaLocalDateTime", org.joda.time.LocalDateTime.class, new org.joda.time.LocalDateTime(2015, 5, 23, 9, 54, 1));
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "nullJodaLocalDateTime", org.joda.time.LocalDateTime.class, (org.joda.time.LocalDateTime) null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "aJodaLocalDateTime", org.joda.time.LocalDateTime.class, new org.joda.time.LocalDateTime(2015, 5, 23, 9, 54, 1), null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "nullJodaLocalDateTime", org.joda.time.LocalDateTime.class, (org.joda.time.LocalDateTime) null, null);
 
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "aJodaLocalTime", org.joda.time.LocalTime.class, new org.joda.time.LocalTime(9, 54, 1));
-        ActionInvocationMementoDtoUtils.addArgValue(aim, "nullJodaLocalTime", org.joda.time.LocalTime.class, (org.joda.time.LocalTime) null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "aJodaLocalTime", org.joda.time.LocalTime.class, new org.joda.time.LocalTime(9, 54, 1), null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "nullJodaLocalTime", org.joda.time.LocalTime.class, (org.joda.time.LocalTime) null, null);
 
-        ActionInvocationMementoDtoUtils.addArgReference(aim, "aReference", new Bookmark("ORD", "12345"));
-        ActionInvocationMementoDtoUtils.addArgReference(aim, "nullReference", null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "aReference", null, new Bookmark("ORD", "12345"), null);
+        ActionInvocationMementoDtoUtils.addParamArg(aim, "nullReference", null, null, null);
 
 
         // when
@@ -115,9 +112,9 @@ public class Roundtrip {
 
 
         // then
-        assertThat(recreated.getMetadata().getActionIdentifier(), Matchers.is(aim.getMetadata().getActionIdentifier()));
-        assertThat(recreated.getMetadata().getTarget().getObjectType(), Matchers.is(aim.getMetadata().getTarget().getObjectType()));
-        assertThat(recreated.getMetadata().getTarget().getObjectIdentifier(), Matchers.is(aim.getMetadata().getTarget().getObjectIdentifier()));
+        assertThat(recreated.getInvocation().getAction().getActionIdentifier(), Matchers.is(aim.getInvocation().getAction().getActionIdentifier()));
+        assertThat(recreated.getInvocation().getTarget().getObjectType(), Matchers.is(aim.getInvocation().getTarget().getObjectType()));
+        assertThat(recreated.getInvocation().getTarget().getObjectIdentifier(), Matchers.is(aim.getInvocation().getTarget().getObjectIdentifier()));
 
 
         int param = 0;

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/OidMarshaller.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/OidMarshaller.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/OidMarshaller.java
index ae26640..a2535ec 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/OidMarshaller.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/oid/OidMarshaller.java
@@ -27,6 +27,7 @@ import com.google.common.base.Splitter;
 import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 
+import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.core.metamodel.adapter.oid.Oid.State;
 import org.apache.isis.core.metamodel.adapter.version.Version;
 import org.apache.isis.core.metamodel.spec.ObjectSpecId;
@@ -82,11 +83,14 @@ import org.apache.isis.core.metamodel.spec.ObjectSpecId;
 public class OidMarshaller {
 
     //region > public constants
-    public static final String VIEWMODEL_INDICATOR = "*";
+    public static final String VIEWMODEL_INDICATOR =
+            Bookmark.ObjectState.VIEW_MODEL.getCode(); // "*"
     //endregion
 
     //region > private constants
-    private static final String TRANSIENT_INDICATOR = "!";
+    private static final String TRANSIENT_INDICATOR =
+            Bookmark.ObjectState.TRANSIENT.getCode() ; // "!"
+
 	private static final String SEPARATOR = ":";
 	private static final String SEPARATOR_NESTING = "~";
 	private static final String SEPARATOR_COLLECTION = "$";

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
index 790ff8c..6199504 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
@@ -42,10 +42,11 @@ import org.apache.isis.applib.services.background.ActionInvocationMemento;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.command.Command;
 import org.apache.isis.applib.services.command.CommandContext;
-import org.apache.isis.applib.services.command.CommandMementoService;
+import org.apache.isis.core.metamodel.services.command.CommandMementoService;
 import org.apache.isis.applib.services.command.spi.CommandService;
 import org.apache.isis.applib.services.eventbus.AbstractDomainEvent;
 import org.apache.isis.applib.services.eventbus.ActionDomainEvent;
+import org.apache.isis.applib.services.jaxb.JaxbService;
 import org.apache.isis.applib.services.queryresultscache.QueryResultsCache;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider;
@@ -75,6 +76,8 @@ import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.specloader.ReflectiveActionException;
 import org.apache.isis.core.metamodel.transactions.TransactionState;
 import org.apache.isis.core.metamodel.transactions.TransactionStateProvider;
+import org.apache.isis.schema.cmd.v1.CommandMementoDto;
+import org.apache.isis.schema.utils.CommandMementoDtoUtils;
 
 public abstract class ActionInvocationFacetForDomainEventAbstract
         extends ActionInvocationFacetAbstract
@@ -193,7 +196,7 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
             final ObjectAdapter[] arguments,
             final InteractionInitiatedBy interactionInitiatedBy) {
 
-        final CommandContext commandContext = getServicesInjector().lookupService(CommandContext.class);
+        final CommandContext commandContext = getCommandContext();
         final Command command = commandContext != null ? commandContext.getCommand() : null;
 
         // ... post the executing event
@@ -281,10 +284,8 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
             final ObjectAdapter targetAdapter,
             final ObjectAdapter[] arguments) {
 
-
         try {
 
-
             final Object[] executionParameters = new Object[arguments.length];
             for (int i = 0; i < arguments.length; i++) {
                 executionParameters[i] = unwrap(arguments[i]);
@@ -294,7 +295,7 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
 
             final BulkFacet bulkFacet = getFacetHolder().getFacet(BulkFacet.class);
             if (bulkFacet != null) {
-                final ActionInvocationContext actionInvocationContext = getServicesInjector().lookupService(ActionInvocationContext.class);
+                final ActionInvocationContext actionInvocationContext = getActionInvocationContext();
                 if (actionInvocationContext != null &&
                     actionInvocationContext.getInvokedOn() == null) {
 
@@ -302,7 +303,7 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
                     actionInvocationContext.setDomainObjects(Collections.singletonList(targetPojo));
                 }
 
-                final Bulk.InteractionContext bulkInteractionContext = getServicesInjector().lookupService(Bulk.InteractionContext.class);
+                final Bulk.InteractionContext bulkInteractionContext = getBulkInteractionContext();
 
                 if (bulkInteractionContext != null &&
                         bulkInteractionContext.getInvokedAs() == null) {
@@ -326,7 +327,7 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
                     command.setTarget(targetBookmark);
                 }
 
-                if("(edit)".equals(command.getMemberIdentifier())) {
+                if(Command.ACTION_IDENTIFIER_FOR_EDIT.equals(command.getMemberIdentifier())) {
                     // special case for edit properties
                 } else {
 
@@ -339,18 +340,34 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
                     if(command.getMemento() == null) {
                         // similarly, guard here to deal with subsequent contributed/mixin actions.
 
-                        final CommandMementoService commandMementoService = getServicesInjector().lookupService(CommandMementoService.class);
-                        if(commandMementoService != null) {
-                            final Object targetObject = unwrap(targetAdapter);
-                            final Object[] args = CommandUtil.objectsFor(arguments);
-                            final ActionInvocationMemento aim = commandMementoService.asActionInvocationMemento(method, targetObject, args);
+                        final CommandMementoService commandMementoService = getCommandMementoService();
+
+                        final Object targetObject = unwrap(targetAdapter);
+                        final Object[] args = CommandUtil.objectsFor(arguments);
+
+                        final CommandMementoDto dto = commandMementoService.asCommandMemento(
+                                Collections.singletonList(targetAdapter),
+                                owningAction, arguments);
 
+                        if(dto != null) {
+                            // the default implementation will always return a dto.  The guard is to allow
+                            // for the default implementation to be replaced with a version that returns null
+                            // allowing a fallback to the original API (using ActionInvocationMemento rather than
+                            // CommandMementoDto).
+                            final String mementoXml = CommandMementoDtoUtils.toXml(dto);
+                            command.setMemento(mementoXml);
+                        } else {
+
+                            // fallback to old behaviour
+                            ActionInvocationMemento aim = commandMementoService
+                                    .asActionInvocationMemento(method, targetObject, args);
                             if(aim != null) {
                                 command.setMemento(aim.asMementoString());
+
                             } else {
+                                String actionIdentifier = owningAction.getIdentifier().toClassAndNameIdentityString();
                                 throw new IsisException(
-                                        "Unable to build memento for action " +
-                                                owningAction.getIdentifier().toClassAndNameIdentityString());
+                                        "Unable to build memento for action " + actionIdentifier);
                             }
                         }
                     }
@@ -375,7 +392,7 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
                 command.getExecuteIn() == org.apache.isis.applib.annotation.Command.ExecuteIn.BACKGROUND) {
 
                 // persist command so can be this command can be in the 'background'
-                final CommandService commandService = getServicesInjector().lookupService(CommandService.class);
+                final CommandService commandService = getCommandService();
                 if(commandService.persistIfPossible(command)) {
                     // force persistence, then return the command itself.
                     final ObjectAdapter resultAdapter = getAdapterManager().adapterFor(command);
@@ -399,9 +416,8 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
 
             Object result;
             if(cacheable) {
-                final QueryResultsCache queryResultsCache = getServicesInjector().lookupService(QueryResultsCache.class);
-                final Object[] targetPojoPlusExecutionParameters = ArrayExtensions
-                        .appendT(executionParameters, targetPojo);
+                final QueryResultsCache queryResultsCache = getQueryResultsCache();
+                final Object[] targetPojoPlusExecutionParameters = ArrayExtensions.appendT(executionParameters, targetPojo);
                 result = queryResultsCache.execute(new Callable<Object>() {
                     @Override
                     public Object call() throws Exception {
@@ -494,8 +510,6 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
         }
     }
 
-
-
     private static Object unwrap(final ObjectAdapter adapter) {
         return adapter == null ? null : adapter.getObject();
     }
@@ -506,10 +520,44 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
     }
 
 
+
+    // /////////////////////////////////////////////////////////
+    // Dependencies (looked up)
+    // /////////////////////////////////////////////////////////
+
+    private CommandContext getCommandContext() {
+        return lookupService(CommandContext.class);
+    }
+
+    private QueryResultsCache getQueryResultsCache() {
+        return lookupService(QueryResultsCache.class);
+    }
+
+    private CommandService getCommandService() {
+        return lookupService(CommandService.class);
+    }
+
+    private CommandMementoService getCommandMementoService() {
+        return lookupService(CommandMementoService.class);
+    }
+
+    private Bulk.InteractionContext getBulkInteractionContext() {
+        return lookupService(Bulk.InteractionContext.class);
+    }
+
+    private ActionInvocationContext getActionInvocationContext() {
+        return lookupService(ActionInvocationContext.class);
+    }
+
+    private <T> T lookupService(final Class<T> serviceClass) {
+        return getServicesInjector().lookupService(serviceClass);
+    }
+
     // /////////////////////////////////////////////////////////
     // Dependencies (from constructor)
     // /////////////////////////////////////////////////////////
 
+
     private AdapterManager getAdapterManager() {
         return adapterManager;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/modify/PropertySetterFacetViaModifyMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/modify/PropertySetterFacetViaModifyMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/modify/PropertySetterFacetViaModifyMethod.java
index 2230d38..9339274 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/modify/PropertySetterFacetViaModifyMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/update/modify/PropertySetterFacetViaModifyMethod.java
@@ -74,8 +74,8 @@ public class PropertySetterFacetViaModifyMethod extends PropertySetterFacetAbstr
 
             command.setTarget(CommandUtil.bookmarkFor(targetAdapter));
             command.setTargetClass(CommandUtil.targetClassNameFor(targetAdapter));
-            command.setTargetAction(Command.TARGET_ACTION_FOR_EDIT);
-            command.setMemberIdentifier(Command.TARGET_ACTION_FOR_EDIT);
+            command.setTargetAction(Command.ACTION_IDENTIFIER_FOR_EDIT);
+            command.setMemberIdentifier(Command.ACTION_IDENTIFIER_FOR_EDIT);
 
             command.setExecuteIn(org.apache.isis.applib.annotation.Command.ExecuteIn.FOREGROUND);
             command.setPersistence(org.apache.isis.applib.annotation.Command.Persistence.IF_HINTED);

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/command/CommandMementoService.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/command/CommandMementoService.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/command/CommandMementoService.java
new file mode 100644
index 0000000..acbec29
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/command/CommandMementoService.java
@@ -0,0 +1,53 @@
+/**
+ *  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 agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.core.metamodel.services.command;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.background.ActionInvocationMemento;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.schema.cmd.v1.CommandMementoDto;
+
+/**
+ * Used to create mementos of a command, such that it can be persisted and then executed either immediately (ie invoke
+ * in the foreground) or deferred (ie invoke in the background at some later time).
+ */
+public interface CommandMementoService {
+
+    /**
+     * Note that this method (more precisely, {@link ActionInvocationMemento}) does <i>not</i> support mixins.
+     *
+     * @deprecated - use {@link #asCommandMemento(List, ObjectAction, ObjectAdapter[])} instead.
+     */
+    @Deprecated
+    @Programmatic
+    ActionInvocationMemento asActionInvocationMemento(Method m, Object domainObject, Object[] args);
+
+    /**
+     * The default implementation returns a non-null value.  If a custom implementation returns <tt>null</tt>, then
+     * the framework will fall back to using the deprecated {@link #asActionInvocationMemento(Method, Object, Object[])}.
+     */
+    @Programmatic
+    CommandMementoDto asCommandMemento(
+            final List<ObjectAdapter> targetAdapters,
+            final ObjectAction objectAction,
+            final ObjectAdapter[] argAdapters);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundCommandExecution.java
----------------------------------------------------------------------
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 09f1b2a..79c2ab8 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
@@ -18,7 +18,9 @@ package org.apache.isis.core.runtime.services.background;
 
 import java.util.List;
 
+import com.google.common.base.Function;
 import com.google.common.base.Throwables;
+import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
 import org.apache.isis.applib.clock.Clock;
@@ -28,6 +30,7 @@ import org.apache.isis.applib.services.bookmark.BookmarkService;
 import org.apache.isis.applib.services.command.Command;
 import org.apache.isis.applib.services.command.Command.Executor;
 import org.apache.isis.applib.services.command.CommandContext;
+import org.apache.isis.applib.services.jaxb.JaxbService;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.oid.RootOid;
 import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
@@ -40,6 +43,11 @@ 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.schema.cmd.v1.ActionDto;
+import org.apache.isis.schema.cmd.v1.CommandMementoDto;
+import org.apache.isis.schema.cmd.v1.ParamDto;
+import org.apache.isis.schema.common.v1.OidDto;
+import org.apache.isis.schema.utils.CommandMementoDtoUtils;
 
 /**
  * Intended to be used as a base class for executing queued up {@link Command background action}s.
@@ -89,42 +97,101 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
         transactionManager.executeWithinTransaction(new TransactionalClosure() {
             @Override
             public void execute() {
+
                 commandContext.setCommand(command);
-                try {
+                final String memento = command.getMemento();
+                final boolean legacy = memento.startsWith("<memento");
 
+                try {
                     command.setStartedAt(Clock.getTimeAsJavaSqlTimestamp());
                     command.setExecutor(Executor.BACKGROUND);
 
-                    final String memento = command.getMemento();
-                    final ActionInvocationMemento aim = new ActionInvocationMemento(mementoService, memento);
+                    if(legacy) {
 
-                    final String actionId = aim.getActionId();
+                        final ActionInvocationMemento aim = new ActionInvocationMemento(mementoService, memento);
 
-                    final Bookmark targetBookmark = aim.getTarget();
-                    final Object targetObject = bookmarkService.lookup(targetBookmark);
+                        final String actionId = aim.getActionId();
 
-                    final ObjectAdapter targetAdapter = adapterFor(targetObject);
-                    final ObjectSpecification specification = targetAdapter.getSpecification();
+                        final Bookmark targetBookmark = aim.getTarget();
+                        final Object targetObject = bookmarkService.lookup(targetBookmark);
 
-                    final ObjectAction objectAction = findAction(specification, actionId);
-                    if(objectAction == null) {
-                        throw new Exception("Unknown action '" + actionId + "'");
-                    }
+                        final ObjectAdapter targetAdapter = adapterFor(targetObject);
+                        final ObjectSpecification specification = targetAdapter.getSpecification();
+
+                        final ObjectAction objectAction = findAction(specification, actionId);
+                        if(objectAction == null) {
+                            throw new Exception("Unknown action '" + actionId + "'");
+                        }
+
+                        final ObjectAdapter[] argAdapters = argAdaptersFor(aim);
+                        final ObjectAdapter resultAdapter = objectAction.execute(
+                                targetAdapter, argAdapters, InteractionInitiatedBy.FRAMEWORK);
+                        if(resultAdapter != null) {
+                            Bookmark resultBookmark = CommandUtil.bookmarkFor(resultAdapter);
+                            command.setResult(resultBookmark);
+                        }
+
+                    } else {
 
-                    final ObjectAdapter[] argAdapters = argAdaptersFor(aim);
-                    final ObjectAdapter resultAdapter = objectAction.execute(
-                            targetAdapter, argAdapters, InteractionInitiatedBy.FRAMEWORK);
-                    if(resultAdapter != null) {
-                        Bookmark resultBookmark = CommandUtil.bookmarkFor(resultAdapter);
-                        command.setResult(resultBookmark);
+                        final CommandMementoDto dto = jaxbService.fromXml(CommandMementoDto.class, memento);
+                        final ActionDto actionDto = dto.getAction();
+                        final String actionId = actionDto.getActionIdentifier();
+
+                        final List<OidDto> targetOidDtos = dto.getTargets();
+                        for (OidDto targetOidDto : targetOidDtos) {
+
+                            final Bookmark bookmark = Bookmark.from(targetOidDto);
+                            final Object targetObject = bookmarkService.lookup(bookmark);
+
+                            final ObjectAdapter targetAdapter = adapterFor(targetObject);
+                            final String mixinFqClassName = actionDto.getMixinFqClassName();
+
+                            final ObjectAction objectAction =
+                                    findObjectAction(mixinFqClassName, targetAdapter, actionId);
+
+                            final ObjectAdapter[] argAdapters = argAdaptersFor(dto);
+                            objectAction.execute(
+                                    targetAdapter, argAdapters, InteractionInitiatedBy.FRAMEWORK);
+
+                            // no longer capture the result, because there may be many
+                            // (should be done by auditing/profiling instead).
+                        }
                     }
 
                 } catch (Exception e) {
-                    command.setException(Throwables.getStackTraceAsString(e));
+                    if(legacy) {
+                        command.setException(Throwables.getStackTraceAsString(e));
+                    } else {
+                        // no longer capture any exceptions, could be bulk action.
+                        // (should be done by auditing/profiling instead).
+                    }
                 } finally {
+                    // decided to keep this, even though really this
+                    // should be the responsibility of auditing/profiling
                     command.setCompletedAt(Clock.getTimeAsJavaSqlTimestamp());
                 }
             }
+
+            private ObjectAction findObjectAction(
+                    final String mixinFqClassName,
+                    final ObjectAdapter targetAdapter,
+                    final String actionId) throws Exception {
+
+                final ObjectAction objectAction;
+                if(mixinFqClassName != null) {
+                    final ObjectSpecification mixinSpec = getSpecificationLoader()
+                            .loadSpecification(mixinFqClassName);
+                    objectAction = mixinSpec.getObjectAction(actionId);
+                } else {
+                    final ObjectSpecification specification = targetAdapter.getSpecification();
+
+                    objectAction = findAction(specification, actionId);
+                }
+                if(objectAction == null) {
+                    throw new Exception("Unknown action '" + actionId + "'");
+                }
+                return objectAction;
+            }
         });
     }
 
@@ -163,12 +230,30 @@ public abstract class BackgroundCommandExecution extends AbstractIsisSessionTemp
         }
     }
 
-    
+    private ObjectAdapter[] argAdaptersFor(final CommandMementoDto dto) {
+        final List<ParamDto> params = dto.getAction().getParameters();
+        final List<ObjectAdapter> args = Lists.newArrayList(
+                Iterables.transform(params, new Function<ParamDto, ObjectAdapter>() {
+                    @Override
+                    public ObjectAdapter apply(final ParamDto paramDto) {
+                        final Object arg = CommandMementoDtoUtils.paramArgOf(paramDto);
+                        return adapterFor(arg);
+                    }
+                })
+        );
+        return args.toArray(new ObjectAdapter[]{});
+    }
+
+
+
     // //////////////////////////////////////
 
     @javax.inject.Inject
     private BookmarkService bookmarkService;
 
     @javax.inject.Inject
+    private JaxbService jaxbService;
+
+    @javax.inject.Inject
     private CommandContext commandContext;
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundServiceDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundServiceDefault.java
index f00ff3d..0c2badc 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundServiceDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundServiceDefault.java
@@ -17,17 +17,19 @@
 package org.apache.isis.core.runtime.services.background;
 
 import java.lang.reflect.Method;
+import java.util.Collections;
 
 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.background.ActionInvocationMemento;
 import org.apache.isis.applib.services.background.BackgroundCommandService;
+import org.apache.isis.applib.services.background.BackgroundCommandService2;
 import org.apache.isis.applib.services.background.BackgroundService;
 import org.apache.isis.applib.services.bookmark.BookmarkService;
 import org.apache.isis.applib.services.command.Command;
 import org.apache.isis.applib.services.command.CommandContext;
-import org.apache.isis.applib.services.command.CommandMementoService;
+import org.apache.isis.core.metamodel.services.command.CommandMementoService;
 import org.apache.isis.core.commons.ensure.Ensure;
 import org.apache.isis.core.commons.exceptions.IsisException;
 import org.apache.isis.core.commons.lang.ArrayExtensions;
@@ -42,6 +44,7 @@ import org.apache.isis.core.metamodel.specloader.classsubstitutor.JavassistEnhan
 import org.apache.isis.core.metamodel.specloader.specimpl.dflt.ObjectSpecificationDefault;
 import org.apache.isis.core.runtime.services.memento.MementoServiceDefault;
 import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.schema.cmd.v1.CommandMementoDto;
 
 import javassist.util.proxy.MethodFilter;
 import javassist.util.proxy.MethodHandler;
@@ -164,15 +167,34 @@ public class BackgroundServiceDefault implements BackgroundService {
 
                 final String targetClassName = CommandUtil.targetClassNameFor(targetAdapter);
                 final String targetActionName = CommandUtil.targetActionNameFor(action);
-                final String targetArgs = CommandUtil.argDescriptionFor(action, adaptersFor(args));
+                final ObjectAdapter[] argAdapters = adaptersFor(args);
+                final String targetArgs = CommandUtil.argDescriptionFor(action, argAdapters);
 
                 final Command command = commandContext.getCommand();
 
+                if(backgroundCommandService instanceof BackgroundCommandService2) {
+                    final BackgroundCommandService2 backgroundCommandService2 =
+                            (BackgroundCommandService2) backgroundCommandService;
+
+                    final CommandMementoDto dto = commandMementoService
+                            .asCommandMemento(Collections.singletonList(targetAdapter), action, argAdapters);
+
+                    if(dto != null) {
+                        // the default implementation returns a non-null value.  This guard is to allow a different
+                        // implementation to be configured that returns null, thereby falling through to the
+                        // original behaviour (of using ActionInvocationMemento instead of CommandMementoDto).
+                        backgroundCommandService2.schedule(dto, command, targetClassName, targetActionName, targetArgs);
+
+                        return null;
+                    }
+                }
+
+                // fallback
                 final ActionInvocationMemento aim = commandMementoService
                         .asActionInvocationMemento(proxyMethod, domainObject, args);
 
                 backgroundCommandService.schedule(aim, command, targetClassName, targetActionName, targetArgs);
-                
+
                 return null;
             }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/runtime/src/main/java/org/apache/isis/core/runtime/services/command/CommandMementoServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/command/CommandMementoServiceDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/command/CommandMementoServiceDefault.java
index 5b6399f..1f09abb 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/command/CommandMementoServiceDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/command/CommandMementoServiceDefault.java
@@ -17,7 +17,6 @@
 package org.apache.isis.core.runtime.services.command;
 
 import java.lang.reflect.Method;
-import java.sql.Timestamp;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
@@ -33,24 +32,22 @@ import org.apache.isis.applib.services.background.ActionInvocationMemento;
 import org.apache.isis.applib.services.background.BackgroundCommandService;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.bookmark.BookmarkService;
-import org.apache.isis.applib.services.command.Command;
-import org.apache.isis.applib.services.command.CommandMementoService;
-import org.apache.isis.applib.services.publish.EventMetadata;
-import org.apache.isis.core.commons.ensure.Ensure;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
 import org.apache.isis.core.metamodel.facets.actions.action.invocation.CommandUtil;
+import org.apache.isis.core.metamodel.services.command.CommandMementoService;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 import org.apache.isis.core.metamodel.specloader.specimpl.dflt.ObjectSpecificationDefault;
 import org.apache.isis.core.runtime.services.memento.MementoServiceDefault;
 import org.apache.isis.core.runtime.system.context.IsisContext;
-import org.apache.isis.schema.aim.v1.ActionInvocationMementoDto;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.CoreMatchers.nullValue;
+import org.apache.isis.schema.cmd.v1.ActionDto;
+import org.apache.isis.schema.cmd.v1.CommandMementoDto;
+import org.apache.isis.schema.utils.CommandMementoDtoUtils;
 
 /**
  * Depends on an implementation of {@link BackgroundCommandService} to
@@ -103,9 +100,13 @@ public class CommandMementoServiceDefault implements CommandMementoService {
 
     // //////////////////////////////////////
 
+    @Deprecated
     @Programmatic
     @Override
-    public ActionInvocationMemento asActionInvocationMemento(Method method, Object domainObject, Object[] args) {
+    public ActionInvocationMemento asActionInvocationMemento(
+            final Method method,
+            final Object domainObject,
+            final Object[] args) {
         
         final ObjectSpecificationDefault targetObjSpec = getJavaSpecificationOfOwningClass(method);
         final ObjectMember member = targetObjSpec.getMember(method);
@@ -137,47 +138,51 @@ public class CommandMementoServiceDefault implements CommandMementoService {
         return aim;
     }
 
+    @Override
+    public CommandMementoDto asCommandMemento(
+            final List<ObjectAdapter> targetAdapters,
+            final ObjectAction objectAction,
+            final ObjectAdapter[] argAdapters) {
+
+        final CommandMementoDto dto = new CommandMementoDto();
+        dto.setMajorVersion("1");
+        dto.setMinorVersion("0");
+
+        for (ObjectAdapter targetAdapter : targetAdapters) {
+            final RootOid rootOid = (RootOid) targetAdapter.getOid();
+            final Bookmark bookmark = rootOid.asBookmark();
+            dto.getTargets().add(bookmark.toOidDto());
+        }
 
-    /**
-     * Not API
-     */
-    ActionInvocationMemento newActionInvocationMemento(String mementoStr) {
-        return new ActionInvocationMemento(mementoService, mementoStr);
-    }
+        final ActionDto actionDto = new ActionDto();
+        dto.setAction(actionDto);
 
-    // //////////////////////////////////////
+        final String actionIdentifier = CommandUtil.actionIdentifierFor(objectAction);
+        actionDto.setActionIdentifier(actionIdentifier);
 
-    @Override
-    public EventMetadata newEventMetadata(
-            final Command command,
-            final String currentUser, final Timestamp timestamp, final String sequenceName) {
-
-        if(command.getTargetAction().equals(Command.TARGET_ACTION_FOR_EDIT)) {
-            throw new IllegalArgumentException(String.format(
-                    "EventMetadata can only be created for commands that represent actions, not property edits; object: %s, member: %s",
-                    command.getTarget(), command.getMemberIdentifier()));
+        List<ObjectActionParameter> actionParameters = objectAction.getParameters();
+        for (int paramNum = 0; paramNum < actionParameters.size(); paramNum++) {
+            final ObjectActionParameter actionParameter = actionParameters.get(paramNum);
+            final String parameterName = actionParameter.getName();
+            final Class<?> paramType = actionParameter.getSpecification().getCorrespondingClass();
+            ObjectAdapter argAdapter = argAdapters[paramNum];
+            final Object arg = argAdapter != null? argAdapter.getObject(): null;
+            CommandMementoDtoUtils.addParamArg(actionDto.getParameters(), parameterName, paramType, arg, bookmarkService);
         }
+        actionDto.setMixinFqClassName(null);
 
-        throw new RuntimeException("not yet implemented");
-    }
-
-    @Override
-    public ActionInvocationMementoDto asActionInvocationMementoDto(
-            final EventMetadata metadata) {
-        throw new RuntimeException("not yet implemented");
+        dto.setTransactionId(UUID.randomUUID().toString());
+        return dto;
     }
 
 
     // //////////////////////////////////////
 
+
     @javax.inject.Inject
     private BookmarkService bookmarkService;
 
 
-    private void ensureDependenciesInjected() {
-        Ensure.ensureThatState(this.bookmarkService, is(not(nullValue())), "BookmarkService domain service must be configured");
-    }
-
     // //////////////////////////////////////
 
     protected SpecificationLoaderSpi getSpecificationLoader() {

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/runtime/src/main/java/org/apache/isis/core/runtime/sessiontemplate/AbstractIsisSessionTemplate.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/sessiontemplate/AbstractIsisSessionTemplate.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/sessiontemplate/AbstractIsisSessionTemplate.java
index 5a18234..fa7b036 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/sessiontemplate/AbstractIsisSessionTemplate.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/sessiontemplate/AbstractIsisSessionTemplate.java
@@ -20,6 +20,7 @@ import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.spec.SpecificationLoader;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 import org.apache.isis.core.runtime.system.session.IsisSession;
@@ -101,5 +102,8 @@ public abstract class AbstractIsisSessionTemplate {
         return getPersistenceSession();
     }
 
+    protected SpecificationLoader getSpecificationLoader() {
+        return IsisContext.getSpecificationLoader();
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/schema/src/main/resources/org/apache/isis/schema/aim/aim-2.0-binding.xml
----------------------------------------------------------------------
diff --git a/core/schema/src/main/resources/org/apache/isis/schema/aim/aim-2.0-binding.xml b/core/schema/src/main/resources/org/apache/isis/schema/aim/aim-2.0-binding.xml
index a5c8e82..c8cf1ed 100644
--- a/core/schema/src/main/resources/org/apache/isis/schema/aim/aim-2.0-binding.xml
+++ b/core/schema/src/main/resources/org/apache/isis/schema/aim/aim-2.0-binding.xml
@@ -26,7 +26,7 @@
             we don't include the minor version, because the
             generated Java class will be backwards compatible
             -->
-            <jaxb:package name="org.apache.isis.schema.aim.v1"/>
+            <jaxb:package name="org.apache.isis.schema.aim.v2"/>
         </jaxb:schemaBindings>
     </jaxb:bindings>
     <!-- since aim-2.0.xsd does an xs:import of common-1.0.xsd, we need to specify common's package bindings -->

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/schema/src/main/resources/org/apache/isis/schema/aim/aim-2.0.xsd
----------------------------------------------------------------------
diff --git a/core/schema/src/main/resources/org/apache/isis/schema/aim/aim-2.0.xsd b/core/schema/src/main/resources/org/apache/isis/schema/aim/aim-2.0.xsd
index be7f442..ce1bfed 100644
--- a/core/schema/src/main/resources/org/apache/isis/schema/aim/aim-2.0.xsd
+++ b/core/schema/src/main/resources/org/apache/isis/schema/aim/aim-2.0.xsd
@@ -37,15 +37,15 @@
 
     <xs:complexType name="actionInvocationMementoDto">
         <xs:sequence>
-            <xs:element name="majorVersion" type="xs:string" minOccurs="0" maxOccurs="1" default="1">
+            <xs:element name="majorVersion" type="xs:string" minOccurs="0" maxOccurs="1" default="2">
                 <xs:annotation>
-                    <xs:documentation>The major version of the schema that an XML instance was created using.  This element is optional for backward compatibility, but will be populated for any v1.1+ instances of this schema.  If missing, assume '0'.
+                    <xs:documentation>The major version of the schema that an XML instance was created using.
                     </xs:documentation>
                 </xs:annotation>
             </xs:element>
-            <xs:element name="minorVersion" type="xs:string" minOccurs="0" maxOccurs="1" default="1">
+            <xs:element name="minorVersion" type="xs:string" minOccurs="0" maxOccurs="1" default="0">
                 <xs:annotation>
-                    <xs:documentation>Introduced in v1.1. The minor version of the schema that an XML instance was created using.  This element is optional for backward compatibility, but will be populated for any v1.1+ instances of this schema.  If missing, assume '0'.
+                    <xs:documentation>The minor version of the schema that an XML instance was created using.
                     </xs:documentation>
                 </xs:annotation>
             </xs:element>
@@ -56,9 +56,9 @@
                 </xs:annotation>
             </xs:element>
             <xs:element name="invocation" type="actionInvocationDto"/>
-            <xs:element name="subActions" type="actionInvocationDto" minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="subInvocations" type="actionInvocationDto" minOccurs="0" maxOccurs="unbounded">
                 <xs:annotation>
-                    <xs:documentation>Introduced in v1.1. Capture sub-actions (if-any) invoked from this action, for example using the WrapperFactory service.  These therefore define a graph/call-stack of actions.  Note that the subactions will redundantly also specify their majorVersion and minorVersion (the alternative would have required restructuring in such a way as to break backward compatibility).
+                    <xs:documentation>Capture invocations of any other actions invoked from this action, using the WrapperFactory service.  These therefore define a graph/call-stack of actions.  Note that the subactions will redundantly also specify their majorVersion and minorVersion (the alternative would have required restructuring in such a way as to break backward compatibility).
                     </xs:documentation>
                 </xs:annotation>
             </xs:element>
@@ -67,28 +67,32 @@
 
     <xs:complexType name="actionInvocationDto">
         <xs:sequence>
-            <xs:element name="sequence" type="xs:int">
+            <xs:element name="id" type="xs:string">
                 <xs:annotation>
-                    <xs:documentation>The combination of ['transactionId', 'sequence'] is guaranteed to be unique.
+                    <xs:documentation>Unique identifier for this action invocation in the format &quot;transactionId.sequence&quot;.
                     </xs:documentation>
                 </xs:annotation>
             </xs:element>
-            <xs:element name="specification" type="cmd:specificationDto"/>
-            <xs:element name="user" type="xs:string">
+            <xs:element name="sequence" type="xs:int">
                 <xs:annotation>
-                    <xs:documentation>The name of the user that invoked this action.  Note that this isn't necessarily the user that initiated the original command; the SudoService may be being used to temporarily switch the effective user.
+                    <xs:documentation>Action invocation within this transaction/command.
                     </xs:documentation>
                 </xs:annotation>
             </xs:element>
-            <xs:element name="timestampStart" type="xs:dateTime">
+            <xs:element name="target" type="common:oidDto" minOccurs="1" maxOccurs="1">
                 <xs:annotation>
-                    <xs:documentation>The point in time that this action was invoked.  See also 'timestampComplete'.
+                    <xs:documentation>For regular actions, represents the entity or view model upon which the action is to be invoked.  For mixin actions, is the object being mixed-into (the constructor arg to the mixin).  For contributed actions, is the domain service (the contributee object will be one of the action arguments within the payload).  Mixin actions can be determined by the presence of the 'mixinFqClassName' element.
                     </xs:documentation>
                 </xs:annotation>
             </xs:element>
-            <xs:element name="timestampComplete" type="xs:dateTime" minOccurs="0" maxOccurs="1">
+            <xs:element name="action" type="cmd:actionDto">
                 <xs:annotation>
-                    <xs:documentation>Introduced in v1.1. The point in time that this action completed.  The duration that the action took is the difference between 'timestamp' and 'timestampComplete'.  This element is optional for backward compatibility, but will be populated for any v1.1 instances of this schema.
+                    <xs:documentation>The action and arguments to be invoked on the target object.</xs:documentation>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="user" type="xs:string">
+                <xs:annotation>
+                    <xs:documentation>The name of the user that invoked this action.  Note that this isn't necessarily the user that initiated the original command; the SudoService may be being used to temporarily switch the effective user.
                     </xs:documentation>
                 </xs:annotation>
             </xs:element>
@@ -98,6 +102,12 @@
                     </xs:documentation>
                 </xs:annotation>
             </xs:element>
+            <xs:element name="timings" type="common:periodDto">
+                <xs:annotation>
+                    <xs:documentation>Captures the time taken to invoke the action.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:element>
             <xs:choice>
                 <xs:element name="returned" type="returnDto" minOccurs="0" maxOccurs="1">
                     <xs:annotation>

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/schema/src/main/resources/org/apache/isis/schema/cmd/cmd-1.0.xsd
----------------------------------------------------------------------
diff --git a/core/schema/src/main/resources/org/apache/isis/schema/cmd/cmd-1.0.xsd b/core/schema/src/main/resources/org/apache/isis/schema/cmd/cmd-1.0.xsd
index 60add44..75b9479 100644
--- a/core/schema/src/main/resources/org/apache/isis/schema/cmd/cmd-1.0.xsd
+++ b/core/schema/src/main/resources/org/apache/isis/schema/cmd/cmd-1.0.xsd
@@ -52,7 +52,17 @@
                     </xs:documentation>
                 </xs:annotation>
             </xs:element>
-            <xs:element name="specification" type="specificationDto"/>
+            <xs:element name="targets" type="common:oidDto" minOccurs="1" maxOccurs="unbounded">
+                <xs:annotation>
+                    <xs:documentation>For regular actions, represents the entity/entities or view model(s) upon which the action is to be invoked.  For mixin actions, is the object(s) being mixed-into (the constructor arg to the mixin).  For contributed actions, is the domain service (the contributee object will be one of the action arguments within the payload).  Note that this means that bulk contributed actions cannot be reified as a memento (for this use case, implement as a mixin action instead).  Mixin actions can be determined by the presence of the 'mixinFqClassName' element.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="action" type="actionDto">
+                <xs:annotation>
+                    <xs:documentation>The action and arguments to be invoked on the target object(s).</xs:documentation>
+                </xs:annotation>
+            </xs:element>
             <xs:element name="user" type="xs:string">
                 <xs:annotation>
                     <xs:documentation>The name of the user that initiated/created this command.
@@ -62,18 +72,12 @@
         </xs:sequence>
     </xs:complexType>
 
-    <xs:complexType name="specificationDto">
+    <xs:complexType name="actionDto">
         <xs:annotation>
-            <xs:documentation>Captures the information required to be able to invoke an action on an object(s).  In particular, identifies the the target object(s), the action to be invoked, whether that action is a mixin, and also the arguments for the parameters of said action.
+            <xs:documentation>Captures the information required to be able to invoke an action on the target(s).  In particular, identifies the action to be invoked, whether that action is a mixin, and also the arguments for the parameters of said action.  Note that the targets are not part of this structure so that it can be reused between cmd and aim schemas (the former of which can relate to multiple targets, the latter always to a single target).
             </xs:documentation>
         </xs:annotation>
         <xs:sequence>
-            <xs:element name="target" type="common:oidDto" minOccurs="1" maxOccurs="unbounded">
-                <xs:annotation>
-                    <xs:documentation>For regular actions, represents the entity/entities or view model(s) upon which the action is to be invoked.  For mixin actions, is the object(s) being mixed-into (the constructor arg to the mixin).  For contributed actions, is the domain service (the contributee object will be one of the action arguments within the payload).  Note that tis means that bulk contributed actions cannot be reified as a memento (for this use case, implement as a mixin action instead).  Mixin actions can be determined by the presence of the 'mixinFqClassName' element.
-                    </xs:documentation>
-                </xs:annotation>
-            </xs:element>
             <xs:element name="mixinFqClassName" type="xs:string" minOccurs="0" maxOccurs="1">
                 <xs:annotation>
                     <xs:documentation>Populated only for mixin actions, is the fully qualified class name of the mixin type.
@@ -86,14 +90,9 @@
                     </xs:documentation>
                 </xs:annotation>
             </xs:element>
-            <xs:element name="parameters">
-                <xs:complexType>
-                    <xs:sequence maxOccurs="unbounded">
-                        <xs:element name="param" type="paramDto"/>
-                    </xs:sequence>
-                    <xs:attribute name="num" use="required" type="xs:int"/>
-                </xs:complexType>
-            </xs:element>
+            <xs:sequence minOccurs="0" maxOccurs="unbounded">
+                <xs:element name="parameters" type="paramDto"/>
+            </xs:sequence>
         </xs:sequence>
     </xs:complexType>
 
@@ -103,7 +102,11 @@
             </xs:documentation>
         </xs:annotation>
         <xs:sequence>
-            <xs:element name="value" type="common:valueDto"/>
+            <xs:element name="argument" type="common:valueDto">
+                <xs:annotation>
+                    <xs:documentation>The argument value of this parameter.</xs:documentation>
+                </xs:annotation>
+            </xs:element>
         </xs:sequence>
         <xs:attribute name="parameterName" use="required" type="xs:string"/>
         <xs:attribute name="parameterType" use="required" type="common:valueType"/>

http://git-wip-us.apache.org/repos/asf/isis/blob/0264ec60/core/schema/src/main/resources/org/apache/isis/schema/common/common-1.0.xsd
----------------------------------------------------------------------
diff --git a/core/schema/src/main/resources/org/apache/isis/schema/common/common-1.0.xsd b/core/schema/src/main/resources/org/apache/isis/schema/common/common-1.0.xsd
index 4bc5fa9..fe2ac8f 100644
--- a/core/schema/src/main/resources/org/apache/isis/schema/common/common-1.0.xsd
+++ b/core/schema/src/main/resources/org/apache/isis/schema/common/common-1.0.xsd
@@ -94,5 +94,26 @@
         </xs:restriction>
     </xs:simpleType>
 
+    <xs:complexType name="periodDto">
+        <xs:annotation>
+            <xs:documentation>Captures a period of time, eg for capturing metrics/timings.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:sequence>
+            <xs:element name="start" type="xs:dateTime">
+                <xs:annotation>
+                    <xs:documentation>The point in time that this period of time started.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="complete" type="xs:dateTime" minOccurs="0" maxOccurs="1">
+                <xs:annotation>
+                    <xs:documentation>The point in time that this period of time completed.  The duration is the difference between 'start' and 'complete'.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+
 
 </xs:schema>