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/05/07 12:45:57 UTC

isis git commit: ISIS-1370: changing the API for PublisherService, adding default Logging implementation. Adding support for deep XML graphs within InteractionDto.

Repository: isis
Updated Branches:
  refs/heads/ISIS-1291 0fa47c86f -> d50731ca4


ISIS-1370: changing the API for PublisherService, adding default Logging implementation.  Adding support for deep XML graphs within InteractionDto.


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

Branch: refs/heads/ISIS-1291
Commit: d50731ca4aa53933a93cef9ed04678717cb8fdca
Parents: 0fa47c8
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Sat May 7 13:45:38 2016 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Sat May 7 13:45:38 2016 +0100

----------------------------------------------------------------------
 .../isis/applib/services/iactn/Interaction.java |  56 ++++---
 .../services/publish/PublisherService.java      |  12 +-
 .../publish/PublisherServiceLogging.java        |  57 ++++++++
 .../services/publish/PublishingService.java     |   2 +-
 .../isis/schema/utils/InteractionDtoUtils.java  | 145 ++++++++++++-------
 .../schema/utils/MemberExecutionDtoUtils.java   |  66 +++++++++
 .../org/apache/isis/schema/utils/Roundtrip.java |  32 +++-
 ...onInvocationFacetForDomainEventAbstract.java |   2 +-
 ...etterOrClearFacetForDomainEventAbstract.java |   2 +-
 .../InteractionDtoServiceInternalDefault.java   |  25 +---
 .../PublishingServiceInternalDefault.java       |  40 ++---
 .../src/main/webapp/WEB-INF/logging.properties  |   3 +
 12 files changed, 320 insertions(+), 122 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/d50731ca/core/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java b/core/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java
index 8aad3d3..dc59c2f 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java
@@ -75,14 +75,16 @@ public class Interaction implements HasTransactionId {
 
     //region > transactionId (property)
 
+    private UUID transactionId;
+
     @Override
     public UUID getTransactionId() {
-        return null;
+        return transactionId;
     }
 
     @Override
     public void setTransactionId(final UUID transactionId) {
-
+        this.transactionId = transactionId;
     }
     //endregion
 
@@ -273,35 +275,44 @@ public class Interaction implements HasTransactionId {
 
     //region > next (programmatic)
 
-    public enum SequenceName {
+    /**
+     * Enumerates the different reasons why multiple occurrences of a certain type might occur within a single
+     * (top-level) interaction.
+     */
+    public enum Sequence {
 
         /**
+         * Each interaction is either an action invocation or a property edit.  There could be multiple of these,
+         * typically as the result of a nested calls using the {@link WrapperFactory}.  Another reason is
+         * support for bulk action invocations within a single transaction.
+         */
+        INTERACTION,
+        /**
          * &quot;pe&quot; - published event.  For objects: multiple such could be dirtied and thus published as
          * separate events.  For actions invocations/property edits : multiple sub-invocations could occur if sub-invocations are made through the {@link WrapperFactory}.
          */
-        PUBLISHED_EVENT("pe");
+        PUBLISHED_EVENT;
 
-        private final String abbr;
-        SequenceName(final String abbr) {
-            this.abbr = abbr;
+        @Programmatic
+        public String id() {
+            return Interaction.Sequence.class.getName() + "#" + name();
         }
-        public String abbr() { return abbr; }
     }
 
 
-    private final Map<String, AtomicInteger> sequenceByName = Maps.newHashMap();
+    private final Map<String, AtomicInteger> maxBySequence = Maps.newHashMap();
 
     /**
-     * Generates numbers in a named sequence
-     *
-     * @param sequenceAbbr - should be {@link SequenceName#abbr()}.
+     * Generates numbers in a named sequence.  The name of the sequence can be arbitrary, though note that the
+     * framework also uses this capability to generate sequence numbers corresponding to the sequences enumerated by
+     * the {@link Sequence} enum.
      */
     @Programmatic
-    public int next(String sequenceAbbr) {
-        AtomicInteger next = sequenceByName.get(sequenceAbbr);
+    public int next(final String sequenceId) {
+        AtomicInteger next = maxBySequence.get(sequenceId);
         if(next == null) {
             next = new AtomicInteger(0);
-            sequenceByName.put(sequenceAbbr, next);
+            maxBySequence.put(sequenceId, next);
         } else {
             next.incrementAndGet();
         }
@@ -320,19 +331,26 @@ public class Interaction implements HasTransactionId {
 
         private final String memberIdentifier;
         private final Object target;
+        private final Interaction interaction;
         private final InteractionType interactionType;
 
         public Execution(
+                final Interaction interaction,
                 final InteractionType interactionType,
                 final String memberIdentifier,
                 final Object target) {
+            this.interaction = interaction;
             this.interactionType = interactionType;
             this.memberIdentifier = memberIdentifier;
             this.target = target;
         }
         //endregion
 
-        //region > via constructor: interactionType, memberId, target
+        //region > via constructor: interaction, interactionType, memberId, target
+
+        public Interaction getInteraction() {
+            return interaction;
+        }
 
         public InteractionType getInteractionType() {
             return interactionType;
@@ -530,10 +548,11 @@ public class Interaction implements HasTransactionId {
         private final List<Object> args;
 
         public ActionInvocation(
+                final Interaction interaction,
                 final String memberId,
                 final Object target,
                 final List<Object> args) {
-            super(InteractionType.ACTION_INVOCATION, memberId, target);
+            super(interaction, InteractionType.ACTION_INVOCATION, memberId, target);
             this.args = args;
         }
 
@@ -547,10 +566,11 @@ public class Interaction implements HasTransactionId {
         private final Object newValue;
 
         public PropertyModification(
+                final Interaction interaction,
                 final String memberId,
                 final Object target,
                 final Object newValue) {
-            super(InteractionType.PROPERTY_EDIT, memberId, target);
+            super(interaction, InteractionType.PROPERTY_EDIT, memberId, target);
             this.newValue = newValue;
         }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/d50731ca/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
index 6bc5ba7..61d9077 100644
--- 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
@@ -19,18 +19,24 @@
 package org.apache.isis.applib.services.publish;
 
 import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.schema.ixn.v1.InteractionDto;
+import org.apache.isis.applib.services.iactn.Interaction;
 
 /**
  * Replaces {@link PublishingService}.
+ *
+ * <p>
+ *     Note that re-publishing is not
+ * </p>
  */
 public interface PublisherService {
 
     /**
-     * Can also be used for republishing.
+     * Most implementations are expected to use {@link Interaction.Execution#getDto()} to create a serializable
+     * XML representation of the execution.  The easiest way to do this is using {@link org.apache.isis.schema.utils.InteractionDtoUtils#newInteractionDto(Interaction.Execution)}.  There is
+     * some flexibility here, though.
      */
     @Programmatic
-    void publish(final InteractionDto interactionDto);
+    void publish(final Interaction.Execution<?, ?> execution);
 
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/d50731ca/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherServiceLogging.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherServiceLogging.java b/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherServiceLogging.java
new file mode 100644
index 0000000..4bcf958
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/publish/PublisherServiceLogging.java
@@ -0,0 +1,57 @@
+/*
+ *  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 javax.annotation.PostConstruct;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.applib.services.iactn.Interaction;
+import org.apache.isis.schema.ixn.v1.InteractionDto;
+import org.apache.isis.schema.utils.InteractionDtoUtils;
+
+@DomainService(nature = NatureOfService.DOMAIN)
+public class PublisherServiceLogging implements PublisherService {
+
+    private static final Logger LOG = LoggerFactory.getLogger(PublisherServiceLogging.class);
+
+
+    @PostConstruct
+    public void init() {
+    }
+
+    @Override
+    public void publish(final Interaction.Execution<?, ?> execution) {
+
+        if(!LOG.isDebugEnabled()) {
+            return;
+        }
+
+        final InteractionDto interactionDto =
+                InteractionDtoUtils.newInteractionDto(execution, InteractionDtoUtils.Strategy.DEEP);
+
+        LOG.debug(InteractionDtoUtils.toXml(interactionDto));
+
+    }
+
+}
+

http://git-wip-us.apache.org/repos/asf/isis/blob/d50731ca/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 e223d10..52ebd9d 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
@@ -43,7 +43,7 @@ public interface PublishingService {
      * @param metadata
      * @param payload
      *
-     * @deprecated - use instead {@link PublisherService#publish(org.apache.isis.schema.ixn.v1.InteractionDto)}.
+     * @deprecated - use instead {@link PublisherService#publish(org.apache.isis.applib.services.iactn.Interaction.Execution)}.
      */
     @Deprecated
     @Programmatic

http://git-wip-us.apache.org/repos/asf/isis/blob/d50731ca/core/applib/src/main/java/org/apache/isis/schema/utils/InteractionDtoUtils.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/schema/utils/InteractionDtoUtils.java b/core/applib/src/main/java/org/apache/isis/schema/utils/InteractionDtoUtils.java
index b3f3fba..2ed9448 100644
--- a/core/applib/src/main/java/org/apache/isis/schema/utils/InteractionDtoUtils.java
+++ b/core/applib/src/main/java/org/apache/isis/schema/utils/InteractionDtoUtils.java
@@ -40,6 +40,7 @@ import com.google.common.io.Resources;
 
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.bookmark.BookmarkService;
+import org.apache.isis.applib.services.iactn.Interaction;
 import org.apache.isis.schema.cmd.v1.ParamDto;
 import org.apache.isis.schema.cmd.v1.ParamsDto;
 import org.apache.isis.schema.common.v1.InteractionType;
@@ -107,61 +108,114 @@ public final class InteractionDtoUtils {
     }
     //endregion
 
-    //region > newInteractionDto, newInteractionDtoWithActionExecution
+    //region > newInteractionDto
 
-    public static InteractionDto newInteractionDto(final String transactionId) {
-        final InteractionDto interactionDto = new InteractionDto();
+    /**
+     * Encapsulates the mechanism for obtaining a {@link MemberExecutionDto} DTO (XML memento) of the provided
+     * in-memory {@link Interaction.Execution}.
+     */
+    public enum Strategy {
+        FLAT {
 
-        interactionDto.setMajorVersion("1");
-        interactionDto.setMinorVersion("0");
+            @Override
+            public MemberExecutionDto dtoFor(final Interaction.Execution<?, ?> execution) {
+                return execution.getDto();
+            }
+        },
+        DEEP {
+            @Override
+            public MemberExecutionDto dtoFor(final Interaction.Execution<?, ?> execution) {
+                return traverse(execution);
+            }
+
+            private MemberExecutionDto traverse(final Interaction.Execution<?, ?> parentExecution) {
+
+                final MemberExecutionDto parentDto = clone(parentExecution.getDto());
+
+                final List<Interaction.Execution<?, ?>> children = parentExecution.getChildren();
+                for (Interaction.Execution<?, ?> childExecution : children) {
+                    final MemberExecutionDto childDto = clone(childExecution.getDto());
+                    final MemberExecutionDto.ChildExecutions childExecutions =
+                            InteractionDtoUtils.childExecutionsOf(parentDto);
+                    childExecutions.getExecution().add(childDto);
+                    traverse(childExecution);
+                }
+
+                return parentDto;
+            }
+
+            private MemberExecutionDto clone(final MemberExecutionDto memberExecutionDto) {
+                return MemberExecutionDtoUtils.clone(memberExecutionDto);
+            }
+
+            //endregion
+
+        };
+
+
+        public abstract MemberExecutionDto dtoFor(final Interaction.Execution<?, ?> execution);
 
-        interactionDto.setTransactionId(transactionId);
-        return interactionDto;
     }
 
-    public static InteractionDto newInteractionDtoWithActionInvocation(
-            final String transactionId,
-            final int sequence,
-            final Bookmark targetBookmark,
-            final String targetTitle,
-            final String actionIdentifier,
-            final List<ParamDto> parameterDtos,
-            final String user) {
+    private static MemberExecutionDto.ChildExecutions childExecutionsOf(final MemberExecutionDto dto) {
+        MemberExecutionDto.ChildExecutions childExecutions = dto.getChildExecutions();
+        if(childExecutions == null) {
+            childExecutions = new MemberExecutionDto.ChildExecutions();
+            dto.setChildExecutions(childExecutions);
+        }
+        return childExecutions;
+    }
+
+    /**
+     * Creates a {@link InteractionDto} (serializable  to XML) for the provided
+     * {@link Interaction.Execution} (the applib object).
+     */
+    public static InteractionDto newInteractionDto(final Interaction.Execution<?, ?> execution) {
+        return newInteractionDto(execution, Strategy.FLAT);
+    }
 
-        final InteractionDto interactionDto = newInteractionDto(transactionId);
+    /**
+     * Creates a {@link InteractionDto} (serializable  to XML) for the provided
+     * {@link Interaction.Execution} (the applib object).
+     */
+    public static InteractionDto newInteractionDto(
+            final Interaction.Execution<?, ?> execution,
+            final Strategy strategy) {
 
-        final MemberExecutionDto executionDto = newActionInvocation(
-                sequence, targetBookmark, targetTitle,
-                actionIdentifier, parameterDtos,
-                user, transactionId);
+        final MemberExecutionDto memberExecutionDto = strategy.dtoFor(execution);
+        return newInteractionDto(execution, memberExecutionDto);
+    }
 
-        addExecution(interactionDto, executionDto);
+    private static InteractionDto newInteractionDto(
+            final Interaction.Execution<?, ?> execution,
+            final MemberExecutionDto executionDto) {
+        final Interaction interaction = execution.getInteraction();
+        final String transactionId = interaction.getTransactionId().toString();
 
-        return interactionDto;
+        return InteractionDtoUtils.newInteractionDto(transactionId, executionDto);
     }
 
-    public static InteractionDto newInteractionDtoWithPropertyModification(
+    private static InteractionDto newInteractionDto(
             final String transactionId,
-            final int sequence,
-            final Bookmark targetBookmark,
-            final String targetTitle,
-            final String propertyIdentifier,
-            final ValueWithTypeDto newValueDto,
-            final String user
-    ) {
+            final MemberExecutionDto executionDto) {
+        final InteractionDto interactionDto = new InteractionDto();
 
-        final InteractionDto interactionDto = newInteractionDto(transactionId);
+        interactionDto.setMajorVersion("1");
+        interactionDto.setMinorVersion("0");
 
-        final MemberExecutionDto executionDto = newPropertyEdit(
-                sequence, targetBookmark, targetTitle,
-                propertyIdentifier, newValueDto,
-                user, transactionId);
+        interactionDto.setTransactionId(transactionId);
+        interactionDto.setExecution(executionDto);
 
-        addExecution(interactionDto, executionDto);
+        executionDto.setInteractionType(
+                executionDto instanceof ActionInvocationDto
+                        ? InteractionType.ACTION_INVOCATION
+                        : InteractionType.PROPERTY_EDIT);
 
         return interactionDto;
     }
 
+
+
     //endregion
 
     //region > newActionInvocation, newPropertyModification
@@ -241,22 +295,6 @@ public final class InteractionDtoUtils {
 
     //endregion
 
-    //region > addExecution
-
-    public static void addExecution(
-            final InteractionDto interactionDto,
-            final MemberExecutionDto executionDto) {
-        interactionDto.setExecution(executionDto);
-
-        executionDto.setInteractionType(
-                executionDto instanceof ActionInvocationDto
-                        ? InteractionType.ACTION_INVOCATION
-                        : InteractionType.PROPERTY_EDIT);
-    }
-
-
-    //endregion
-
     //region > invocationFor, actionFor, timingsFor
 
     private static ActionInvocationDto actionInvocationFor(final InteractionDto interactionDto) {
@@ -410,7 +448,8 @@ public final class InteractionDtoUtils {
     }
     //endregion
 
-    //region > debugging
+
+    //region > debugging (dump)
     public static void dump(final InteractionDto ixnDto, final PrintStream out) throws JAXBException {
         out.println(toXml(ixnDto));
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/d50731ca/core/applib/src/main/java/org/apache/isis/schema/utils/MemberExecutionDtoUtils.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/schema/utils/MemberExecutionDtoUtils.java b/core/applib/src/main/java/org/apache/isis/schema/utils/MemberExecutionDtoUtils.java
new file mode 100644
index 0000000..f70c2b8
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/schema/utils/MemberExecutionDtoUtils.java
@@ -0,0 +1,66 @@
+/*
+ *  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.StringReader;
+import java.io.StringWriter;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.namespace.QName;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.isis.schema.ixn.v1.MemberExecutionDto;
+
+public final class MemberExecutionDtoUtils {
+
+    public static <T extends MemberExecutionDto> T clone(final T dto) {
+        final Class<T> aClass = (Class)dto.getClass();
+        return clone(dto, aClass);
+    }
+
+    private static <T> T clone(final T dto, final Class<T> dtoClass) {
+        try {
+            JAXBContext jaxbContext = JAXBContext.newInstance(dtoClass);
+
+            final Marshaller marshaller = jaxbContext.createMarshaller();
+
+            final QName name = new QName("", dtoClass.getSimpleName());
+            final JAXBElement<T> jaxbElement = new JAXBElement<>(name, dtoClass, null, dto);
+            final StringWriter stringWriter = new StringWriter();
+
+            marshaller.marshal(jaxbElement, stringWriter);
+
+            final StringReader reader = new StringReader(stringWriter.toString());
+
+            final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+
+            final JAXBElement<T> root = unmarshaller.unmarshal(new StreamSource(reader), dtoClass);
+
+            return root.getValue();
+
+        } catch (JAXBException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d50731ca/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 07a881c..6bfb71c 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
@@ -23,6 +23,7 @@ import java.math.BigInteger;
 import java.sql.Timestamp;
 import java.util.Arrays;
 import java.util.Date;
+import java.util.List;
 import java.util.UUID;
 
 import org.hamcrest.Matchers;
@@ -34,11 +35,13 @@ import org.junit.Test;
 
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.schema.cmd.v1.ParamDto;
+import org.apache.isis.schema.common.v1.InteractionType;
 import org.apache.isis.schema.common.v1.OidDto;
 import org.apache.isis.schema.common.v1.ValueType;
 import org.apache.isis.schema.common.v1.ValueWithTypeDto;
 import org.apache.isis.schema.ixn.v1.ActionInvocationDto;
 import org.apache.isis.schema.ixn.v1.InteractionDto;
+import org.apache.isis.schema.ixn.v1.MemberExecutionDto;
 
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.nullValue;
@@ -47,6 +50,33 @@ import static org.junit.Assert.assertThat;
 
 public class Roundtrip {
 
+    private static InteractionDto newInteractionDtoWithActionInvocation(
+            final String transactionId,
+            final int sequence,
+            final Bookmark targetBookmark,
+            final String targetTitle,
+            final String actionIdentifier,
+            final List<ParamDto> parameterDtos,
+            final String user) {
+
+        final MemberExecutionDto executionDto = InteractionDtoUtils.newActionInvocation(
+                sequence, targetBookmark, targetTitle,
+                actionIdentifier, parameterDtos,
+                user, transactionId);
+
+        final InteractionDto interactionDto = new InteractionDto();
+
+        interactionDto.setMajorVersion("1");
+        interactionDto.setMinorVersion("0");
+
+        interactionDto.setTransactionId(transactionId);
+        interactionDto.setExecution(executionDto);
+
+        executionDto.setInteractionType(InteractionType.ACTION_INVOCATION);
+
+        return interactionDto;
+    }
+
     @Test
     public void happyCase() throws Exception {
 
@@ -59,7 +89,7 @@ public class Roundtrip {
         returnDto.setType(ValueType.BOOLEAN);
         returnDto.setNull(true);
 
-        final InteractionDto interactionDto = InteractionDtoUtils.newInteractionDtoWithActionInvocation(
+        final InteractionDto interactionDto = newInteractionDtoWithActionInvocation(
                 UUID.randomUUID().toString(),
                 1,
                 new Bookmark("CUS", "12345"), "John Customer", "com.mycompany.Customer#placeOrder", Arrays.<ParamDto>asList(),

http://git-wip-us.apache.org/repos/asf/isis/blob/d50731ca/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 555c218..bdaeb92 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
@@ -196,7 +196,7 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
             final List<Object> argumentPojos = ObjectAdapter.Util.unwrap(argumentAdapterList);
 
             final Interaction.ActionInvocation execution =
-                    new Interaction.ActionInvocation(actionId, targetPojo, argumentPojos);
+                    new Interaction.ActionInvocation(interaction, actionId, targetPojo, argumentPojos);
             final Interaction.MemberExecutor<Interaction.ActionInvocation> callable =
                     new Interaction.MemberExecutor<Interaction.ActionInvocation>() {
 

http://git-wip-us.apache.org/repos/asf/isis/blob/d50731ca/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
index 16d0ee7..d6a3fbf 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
@@ -185,7 +185,7 @@ public abstract class PropertySetterOrClearFacetForDomainEventAbstract
             final Object argValue = ObjectAdapter.Util.unwrap(newValueAdapter);
 
             final Interaction.PropertyModification execution =
-                    new Interaction.PropertyModification(propertyId, target, argValue);
+                    new Interaction.PropertyModification(interaction, propertyId, target, argValue);
             final Interaction.MemberExecutor<Interaction.PropertyModification> executor =
                     new Interaction.MemberExecutor<Interaction.PropertyModification>() {
                         @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/d50731ca/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ixn/InteractionDtoServiceInternalDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ixn/InteractionDtoServiceInternalDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ixn/InteractionDtoServiceInternalDefault.java
index a7d0bd7..6cac096 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ixn/InteractionDtoServiceInternalDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ixn/InteractionDtoServiceInternalDefault.java
@@ -29,10 +29,8 @@ import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.bookmark.BookmarkService;
-import org.apache.isis.applib.services.clock.ClockService;
-import org.apache.isis.applib.services.command.Command;
-import org.apache.isis.applib.services.command.CommandContext;
 import org.apache.isis.applib.services.iactn.Interaction;
+import org.apache.isis.applib.services.iactn.InteractionContext;
 import org.apache.isis.applib.services.user.UserService;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.services.command.CommandDtoServiceInternal;
@@ -59,11 +57,10 @@ public class InteractionDtoServiceInternalDefault implements InteractionDtoServi
             final ObjectAdapter targetAdapter,
             final List<ObjectAdapter> argumentAdapters) {
 
-        final Command command = commandContext.getCommand();
-        final UUID transactionId = command.getTransactionId();
+        final Interaction interaction = interactionContext.getInteraction();
+        final UUID transactionId = interaction.getTransactionId();
 
-        final Interaction.SequenceName sequenceName = Interaction.SequenceName.PUBLISHED_EVENT;
-        final int nextEventSequence = command.next(sequenceName.abbr());
+        final int nextEventSequence = interaction.next(Interaction.Sequence.INTERACTION.id());
 
         final Object targetPojo = targetAdapter.getObject();
         final Bookmark targetBookmark = bookmarkService.bookmarkFor(targetPojo);
@@ -109,11 +106,10 @@ public class InteractionDtoServiceInternalDefault implements InteractionDtoServi
             final ObjectAdapter targetAdapter,
             final ObjectAdapter newValueAdapterIfAny) {
 
-        final Command command = commandContext.getCommand();
-        final UUID transactionId = command.getTransactionId();
+        final Interaction interaction = interactionContext.getInteraction();
+        final UUID transactionId = interaction.getTransactionId();
 
-        final Interaction.SequenceName sequenceName = Interaction.SequenceName.PUBLISHED_EVENT;
-        final int nextEventSequence = command.next(sequenceName.abbr());
+        final int nextEventSequence = interaction.next(Interaction.Sequence.INTERACTION.id());
 
         final Object targetPojo = targetAdapter.getObject();
         final Bookmark targetBookmark = bookmarkService.bookmarkFor(targetPojo);
@@ -135,10 +131,8 @@ public class InteractionDtoServiceInternalDefault implements InteractionDtoServi
                 propertyDto.getMemberIdentifier(),
                 newValue, currentUser,
                 transactionIdStr);
-
     }
 
-
     @Inject
     CommandDtoServiceInternal commandDtoServiceInternal;
 
@@ -146,10 +140,7 @@ public class InteractionDtoServiceInternalDefault implements InteractionDtoServi
     private BookmarkService bookmarkService;
 
     @Inject
-    private CommandContext commandContext;
-
-    @Inject
-    private ClockService clockService;
+    private InteractionContext interactionContext;
 
     @Inject
     private UserService userService;

http://git-wip-us.apache.org/repos/asf/isis/blob/d50731ca/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/PublishingServiceInternalDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/PublishingServiceInternalDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/PublishingServiceInternalDefault.java
index d0f1661..d67ae44 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/PublishingServiceInternalDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/publishing/PublishingServiceInternalDefault.java
@@ -40,9 +40,9 @@ import org.apache.isis.applib.annotation.PublishedObject;
 import org.apache.isis.applib.annotation.PublishedObject.ChangeKind;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.clock.ClockService;
-import org.apache.isis.applib.services.command.Command;
 import org.apache.isis.applib.services.command.CommandContext;
 import org.apache.isis.applib.services.iactn.Interaction;
+import org.apache.isis.applib.services.iactn.InteractionContext;
 import org.apache.isis.applib.services.publish.EventMetadata;
 import org.apache.isis.applib.services.publish.EventPayload;
 import org.apache.isis.applib.services.publish.EventType;
@@ -68,9 +68,6 @@ import org.apache.isis.core.runtime.services.enlist.EnlistedObjectsServiceIntern
 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.transaction.IsisTransactionManager;
-import org.apache.isis.schema.ixn.v1.InteractionDto;
-import org.apache.isis.schema.ixn.v1.MemberExecutionDto;
-import org.apache.isis.schema.utils.InteractionDtoUtils;
 
 /**
  * Wrapper around {@link PublishingService}.  Is a no-op if there is no injected service.
@@ -232,11 +229,10 @@ public class PublishingServiceInternalDefault implements PublishingServiceIntern
             returnType = null;
         }
 
-        final Command command = commandContext.getCommand();
+        final Interaction interaction = interactionContext.getInteraction();
 
-        final Interaction.SequenceName sequenceName = Interaction.SequenceName.PUBLISHED_EVENT;
-        final int nextEventSequence = command.next(sequenceName.abbr());
-        final UUID transactionId = command.getTransactionId();
+        final int nextEventSequence = interaction.next(Interaction.Sequence.PUBLISHED_EVENT.id());
+        final UUID transactionId = interaction.getTransactionId();
         final EventMetadata metadata = new EventMetadata(
                 transactionId, nextEventSequence, EventType.ACTION_INVOCATION, currentUser, timestamp, title,
                 actionTargetClass, actionTargetAction, actionTarget, actionMemberIdentifier, parameterNames,
@@ -303,39 +299,26 @@ public class PublishingServiceInternalDefault implements PublishingServiceIntern
             final Bookmark enlistedTarget) {
         final EventType eventType = PublishingServiceInternalDefault.eventTypeFor(changeKind);
 
-        final Command command = commandContext.getCommand();
+        final Interaction interaction = interactionContext.getInteraction();
 
-        final Interaction.SequenceName sequenceName = Interaction.SequenceName.PUBLISHED_EVENT;
-        final int nextEventSequence = command.next(sequenceName.abbr());
-        final UUID transactionId = command.getTransactionId();
+        final int nextEventSequence = interaction.next(Interaction.Sequence.PUBLISHED_EVENT.id());
+        final UUID transactionId = interaction.getTransactionId();
         return new EventMetadata(
                 transactionId, nextEventSequence, eventType, currentUser, timestamp, enlistedTarget.toString(),
                 enlistedAdapterClass, null, enlistedTarget, null, null, null, null);
     }
 
-    private void publishActionToPublisherServices(final Interaction.Execution execution) {
+    private void publishActionToPublisherServices(final Interaction.Execution<?,?> execution) {
 
         if(publisherServices == null || publisherServices.isEmpty()) {
             return;
         }
 
-        //
-        // TODO: this is where we could now stitch together a deep call graph from the execution.getDto()s
-        //
-
-        final MemberExecutionDto executionDto = execution.getDto();
-
-        final String transactionId = commandContext.getCommand().getTransactionId().toString();
-        final InteractionDto interactionDto = InteractionDtoUtils.newInteractionDto(transactionId);
-        InteractionDtoUtils.addExecution(interactionDto, executionDto);
-
-        for (PublisherService publisherService : publisherServices) {
-            publisherService.publish(interactionDto);
+        for (final PublisherService publisherService : publisherServices) {
+            publisherService.publish(execution);
         }
     }
 
-
-
     @Inject
     private List<PublisherService> publisherServices;
 
@@ -352,6 +335,9 @@ public class PublishingServiceInternalDefault implements PublishingServiceIntern
     private CommandContext commandContext;
 
     @Inject
+    private InteractionContext interactionContext;
+
+    @Inject
     private ClockService clockService;
 
     @Inject

http://git-wip-us.apache.org/repos/asf/isis/blob/d50731ca/example/application/simpleapp/webapp/src/main/webapp/WEB-INF/logging.properties
----------------------------------------------------------------------
diff --git a/example/application/simpleapp/webapp/src/main/webapp/WEB-INF/logging.properties b/example/application/simpleapp/webapp/src/main/webapp/WEB-INF/logging.properties
index 941e862..b58eb7a 100644
--- a/example/application/simpleapp/webapp/src/main/webapp/WEB-INF/logging.properties
+++ b/example/application/simpleapp/webapp/src/main/webapp/WEB-INF/logging.properties
@@ -190,6 +190,9 @@ log4j.additivity.org.apache.isis.core.runtime.installers.InstallerLookupDefault=
 log4j.logger.org.apache.shiro.realm.AuthorizingRealm=WARN,Console
 log4j.additivity.log4j.logger.org.apache.shiro.realm.AuthorizingRealm=false
 
+# profiling via PublisherService
+log4j.logger.org.apache.isis.applib.services.publish.PublisherServiceLogging=DEBUG,Console
+log4j.additivity.log4j.logger.org.apache.isis.applib.services.publish.PublisherServiceLogging=false
 
 # Application-specific logging
 log4j.logger.dom.simple.SimpleObject=DEBUG, Stderr