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 2022/07/12 14:05:36 UTC

[isis] branch ISIS-3002 updated (40befe9ce8 -> 78ffa60905)

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

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


 discard 40befe9ce8 ISIS-3002: adds jdo impl for ExecutionLogEntry
     new 78ffa60905 ISIS-3002: adds jdo impl for ExecutionLogEntry

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (40befe9ce8)
            \
             N -- N -- N   refs/heads/ISIS-3002 (78ffa60905)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

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


Summary of changes:


[isis] 01/01: ISIS-3002: adds jdo impl for ExecutionLogEntry

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

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

commit 78ffa60905531807cef3273e978e1217678e2d0d
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Tue Jul 12 15:04:52 2022 +0100

    ISIS-3002: adds jdo impl for ExecutionLogEntry
    
    also:
    * adds UUID as type/attribute converter; simplify persistence model for CommandLogEntry and ExecutionLogEntry
    * rationalize imports for both command log and execution log (in modules)
    * copies over some useful scripts
    * adds timeline extension
---
 .../applib/mixins/system/HasInteractionId.java     |  20 +-
 build.sh                                           | 190 ++++++++++++++++++
 dependency-graph.sh                                |  10 +
 examples/demo/domain/pom.xml                       |   2 +-
 examples/demo/pom.xml                              |   2 +-
 .../applib/IsisModuleExtCommandLogApplib.java      |   7 +
 ...mandLogServiceMenu.java => CommandLogMenu.java} |   8 +-
 .../commandlog/applib/dom/CommandLogEntry.java     |  32 +--
 .../applib/dom/CommandLogEntryRepository.java      |  21 +-
 .../commandlog/jdo/IsisModuleExtCommandLogJdo.java |  12 --
 .../commandlog/jdo/dom/CommandLogEntry.java        |  21 +-
 .../jdo/dom/CommandLogEntryRepository.java         |   1 -
 .../commandlog/jpa/IsisModuleExtCommandLogJpa.java |   9 +-
 .../commandlog/jpa/dom/CommandLogEntry.java        |  22 ++-
 .../jpa/dom/CommandLogEntryRepository.java         |   1 -
 .../applib/IsisModuleExtExecutionLogApplib.java    |   9 +
 .../executionlog/applib/app/ExecutionLogMenu.java  |  69 +++++++
 .../executionlog/applib/dom/ExecutionLogEntry.java |  67 ++++---
 .../persistence-jdo/logging-dn-enhance.properties  |  48 +++++
 .../core/executionlog/persistence-jdo/pom.xml      |   6 +-
 .../jdo/IsisModuleExtExecutionLogJdo.java}         |  29 +--
 .../executionlog/jdo/dom/ExecutionLogEntry.java    | 218 +++++++++++++++++++++
 pom.xml                                            |  18 +-
 serve-timeline.sh                                  |   6 +
 24 files changed, 681 insertions(+), 147 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/isis/applib/mixins/system/HasInteractionId.java b/api/applib/src/main/java/org/apache/isis/applib/mixins/system/HasInteractionId.java
index 07b6111480..681b9559e2 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/mixins/system/HasInteractionId.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/mixins/system/HasInteractionId.java
@@ -41,30 +41,18 @@ import org.apache.isis.applib.services.iactn.Interaction;
 public interface HasInteractionId {
 
     @Property(
-            hidden = Where.EVERYWHERE,
-            maxLength = InteractionIdStr.MAX_LENGTH
+            editing = Editing.DISABLED,
+            maxLength = InteractionId.MAX_LENGTH
     )
     @Parameter(
-            maxLength = InteractionIdStr.MAX_LENGTH
-    )
-    @Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE })
-    @Retention(RetentionPolicy.RUNTIME)
-    @interface InteractionIdStr {
-        int MAX_LENGTH = 36;
-        boolean NULLABLE = InteractionId.NULLABLE;
-        String ALLOWS_NULL = InteractionId.ALLOWS_NULL;
-        String NAME = "interactionId";
-    }
-
-
-    @Property(
-            editing = Editing.DISABLED
+            maxLength = InteractionId.MAX_LENGTH
     )
     @java.lang.annotation.Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE })
     @Retention(RetentionPolicy.RUNTIME)
     public @interface InteractionId {
         boolean NULLABLE = false;
         String ALLOWS_NULL = "false";
+        int MAX_LENGTH = 36;
     }
 
 
diff --git a/build.sh b/build.sh
new file mode 100644
index 0000000000..e4acb48cd8
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,190 @@
+#!/usr/bin/env bash
+
+#
+# prereq for '-t' flag
+#
+# git clone https://gitlab.com/ecpnv.devops/infrastructure/maven-timeline.git
+# mvn clean install
+#
+#
+# see serve-timeline.sh to serve up the generated website (requires JDK18)
+#
+
+BASENAME_0=$(basename $0)
+
+usage() {
+ echo ""                                                                                               >&2
+ echo "$BASENAME_0 options:"                                                                           >&2
+ echo ""                                                                                               >&2
+ echo "  -p run 'git pull --ff-only' first"                                                            >&2
+ echo "  -c include 'clean' goal"                                                                      >&2
+ echo "  -s specify settings"                                                                          >&2
+ echo "  -t add '-Dmaven-timeline.version=1.8-SNAPSHOT' for improved timeline output"                  >&2
+ echo "  -y use 'verify' rather than 'install'.  Cannot combine with '-k'"                             >&2
+ echo "  -k use 'package' rather than 'install'.  Does not run integ tests.  Cannot combine with '-y'" >&2
+ echo "  -O do NOT add '-o' (offline) flag, ie bring down any new dependencies"                        >&2
+ echo "  -F do NOT search for Failures and Errors at the end"                                          >&2
+ echo "  -S do NOT print summary or last 50 lines at the end"                                          >&2
+ echo "  -w whatif - don't run the command but do print it out.  Implies -v (verbose)"                 >&2
+ echo "  -v verbose"                                                                                   >&2
+ echo ""                                                                                               >&2
+}
+
+GIT_PULL=false
+CLEAN=false
+SETTINGS=false
+TIMELINE=false
+SKIP_OFFLINE=false
+PACKAGE_ONLY=false
+VERIFY_ONLY=false
+WHATIF=false
+SINGLE_THREADED=false
+SKIP_SEARCH_FOR_FAILURES=false
+SKIP_SUMMARY=false
+VERBOSE=false
+
+MVN_LOG=/tmp/$BASENAME_0.$$.log
+
+while getopts 'prcstlkyOFSwvh' opt
+do
+  case $opt in
+    p) export GIT_PULL=true ;;
+    c) export CLEAN=true ;;
+    s) export SETTINGS=true ;;
+    t) export TIMELINE=true ;;
+    O) export SKIP_OFFLINE=true ;;
+    l) export SINGLE_THREADED=true ;;
+    k) export PACKAGE_ONLY=true ;;
+    y) export VERIFY_ONLY=true ;;
+    F) export SKIP_SEARCH_FOR_FAILURES=true ;;
+    S) export SKIP_SUMMARY=true ;;
+    w) export WHATIF=true ;;
+    v) export VERBOSE=true ;;
+    h) usage
+       exit 1
+       ;;
+    *) echo "unknown option $opt - aborting" >&2
+       usage
+       exit 1
+      ;;
+  esac
+done
+
+shift $((OPTIND-1))
+
+echo ""
+
+if [ "$VERBOSE" = "true" ]; then
+  echo "-p GIT_PULL                 : $GIT_PULL"
+  echo "-c CLEAN                    : $CLEAN"
+  echo "-s SETTINGS                 : $SETTINGS"
+  echo "-t TIMELINE                 : $TIMELINE"
+  echo "-l SINGLE_THREADED          : $SINGLE_THREADED"
+  echo "-k PACKAGE_ONLY             : $PACKAGE_ONLY"
+  echo "-y VERIFY_ONLY              : $VERIFY_ONLY"
+  echo "-O SKIP_OFFLINE             : $SKIP_OFFLINE"
+  echo "-F SKIP_SEARCH_FOR_FAILURES : $SKIP_SEARCH_FOR_FAILURES"
+  echo "-S SKIP_SUMMARY             : $SKIP_SUMMARY"
+  echo "-w WHATIF                   : $WHATIF"
+  echo "-v VERBOSE                  : $VERBOSE"
+  echo ""
+fi
+
+if [ "$PACKAGE_ONLY" = "true" ] && [ "$VERIFY_ONLY" = "true" ]; then
+  echo "$BASENAME_0 : cannot use '-y' and '-k' flags together"  >&2
+  usage
+  exit 1
+fi
+
+
+OPTS=""
+
+if [ "$SETTINGS" = "true" ]; then
+  OPTS="$OPTS -s _pipeline-resources/build/deployable/.m2/settings.xml"
+fi
+
+if [ "$CLEAN" = "true" ]; then
+  OPTS="$OPTS clean"
+fi
+
+if [ "$TIMELINE" = "true" ]; then
+  OPTS="$OPTS -Dmaven-timeline.version=1.8-SNAPSHOT"
+fi
+
+if [ "$SKIP_OFFLINE" = "false" ]; then
+  OPTS="$OPTS -o"
+fi
+
+if [ "$SINGLE_THREADED" = "false" ]; then
+  OPTS="$OPTS -T1C"
+fi
+
+if [ "$PACKAGE_ONLY" = "true" ]; then
+  OPTS="$OPTS package"
+else
+  if [ "$VERIFY_ONLY" = "true" ]; then
+    OPTS="$OPTS verify"
+  else
+    OPTS="$OPTS install"
+  fi
+fi
+
+if [ "$WHATIF" = "true" ]; then
+
+  if [ "$GIT_PULL" = "true" ]; then
+    echo git pull --ff-only
+  fi
+
+  if [ "$VERBOSE" = "true" ]; then
+    echo "mvn $OPTS $* 2>&1 | tee $MVN_LOG "
+  else
+    OPTS="$OPTS --log-file $MVN_LOG"
+    echo mvn $OPTS "$@"
+  fi
+
+
+  if [ "$SKIP_SEARCH_FOR_FAILURES" = "false" ]; then
+    echo "... grep for failures/errors"
+  fi
+
+  if [ "$SKIP_SUMMARY" = "false" ]; then
+    echo "... print summary"
+  fi
+
+
+  echo ""
+else
+
+  if [ "$GIT_PULL" = "true" ]; then
+    git pull --ff-only
+    if [ $? -ne 0 ]; then
+      echo "git pull --ff-only failed; aborting" >&2
+      exit 1
+    fi
+  fi
+
+  if [ "$VERBOSE" = "true" ]; then
+    echo "mvn $OPTS $* 2>&1 | tee $MVN_LOG"
+    mvn $OPTS "$@" 2>&1 | tee $MVN_LOG
+  else
+    OPTS="$OPTS --log-file $MVN_LOG"
+    echo "mvn $OPTS $*"
+    mvn $OPTS "$@"
+  fi
+
+  if [ "$SKIP_SEARCH_FOR_FAILURES" = "false" ]; then
+    grep -in -E 'Failures:\s[1-9]+, Errors: [0-9]+, Skipped: [0-9]+$' -B 20 $MVN_LOG
+    grep -in -E 'Failures:\s[0-9]+, Errors: [1-9]+, Skipped: [0-9]+$' -B 20 $MVN_LOG
+  fi
+
+  if [ "$SKIP_SUMMARY" = "false" ]; then
+    if grep -n "Segment walltime" $MVN_LOG ; then
+      tail -n +$(grep -n "Segment walltime" $MVN_LOG | cut -f1 -d:) $MVN_LOG
+    else
+      tail -n 50 $MVN_LOG
+    fi
+  fi
+fi
+
+
+
diff --git a/dependency-graph.sh b/dependency-graph.sh
new file mode 100644
index 0000000000..443a937d9e
--- /dev/null
+++ b/dependency-graph.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+GRAPHFORMAT=dot
+#GRAPHFORMAT=puml
+#GRAPHFORMAT=text
+mvn com.github.ferstl:depgraph-maven-plugin:aggregate -DgraphFormat=$GRAPHFORMAT
+
+echo "generated:"
+echo "target/dependency-graph.dot"
+echo "target/dependency-graph.png"
\ No newline at end of file
diff --git a/examples/demo/domain/pom.xml b/examples/demo/domain/pom.xml
index 2405ff9707..0c3cdb3cbc 100644
--- a/examples/demo/domain/pom.xml
+++ b/examples/demo/domain/pom.xml
@@ -62,7 +62,7 @@
 
 		<dependency>
 			<groupId>org.apache.isis.extensions</groupId>
-			<artifactId>isis-extensions-exceldownload-ui</artifactId>
+			<artifactId>isis-extensions-exceldownload-wicket-ui</artifactId>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.isis.extensions</groupId>
diff --git a/examples/demo/pom.xml b/examples/demo/pom.xml
index 75873ae884..145b406e6a 100644
--- a/examples/demo/pom.xml
+++ b/examples/demo/pom.xml
@@ -190,7 +190,7 @@
 		</dependency>
 		<dependency>
 			<groupId>org.apache.isis.extensions</groupId>
-			<artifactId>isis-extensions-exceldownload-ui</artifactId>
+			<artifactId>isis-extensions-exceldownload-wicket-ui</artifactId>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.isis.extensions</groupId>
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/IsisModuleExtCommandLogApplib.java b/extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/IsisModuleExtCommandLogApplib.java
index b83122a8f7..21cb86ec76 100644
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/IsisModuleExtCommandLogApplib.java
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/IsisModuleExtCommandLogApplib.java
@@ -22,10 +22,17 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 
 import org.apache.isis.core.config.util.SpringProfileUtil;
+import org.apache.isis.extensions.commandlog.applib.app.CommandLogMenu;
+import org.apache.isis.extensions.commandlog.applib.dom.CommandLogEntry.TableColumnOrderDefault;
+import org.apache.isis.extensions.commandlog.applib.subscriber.CommandSubscriberForCommandLog;
 import org.apache.isis.testing.fixtures.applib.modules.ModuleWithFixtures;
 
 @Configuration
 @Import({
+        // @DomainService's
+        CommandLogMenu.class,
+        CommandSubscriberForCommandLog.class,
+        TableColumnOrderDefault.class,
 })
 public class IsisModuleExtCommandLogApplib
 implements ModuleWithFixtures {
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/app/CommandLogServiceMenu.java b/extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/app/CommandLogMenu.java
similarity index 97%
rename from extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/app/CommandLogServiceMenu.java
rename to extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/app/CommandLogMenu.java
index feda33b913..200f5d9c0d 100644
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/app/CommandLogServiceMenu.java
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/app/CommandLogMenu.java
@@ -47,7 +47,7 @@ import lombok.RequiredArgsConstructor;
 /**
  * @since 2.0 {@index}
  */
-@Named(CommandLogServiceMenu.LOGICAL_TYPE_NAME)
+@Named(CommandLogMenu.LOGICAL_TYPE_NAME)
 @DomainService(
     nature = NatureOfService.VIEW
 )
@@ -57,13 +57,13 @@ import lombok.RequiredArgsConstructor;
 )
 @javax.annotation.Priority(PriorityPrecedence.EARLY)
 @RequiredArgsConstructor(onConstructor_ = { @Inject })
-public class CommandLogServiceMenu {
+public class CommandLogMenu {
 
     public static final String LOGICAL_TYPE_NAME =
-            IsisModuleExtCommandLogApplib.NAMESPACE + ".CommandLogServiceMenu";
+            IsisModuleExtCommandLogApplib.NAMESPACE + ".CommandLogMenu";
 
     public static abstract class ActionDomainEvent
-        extends IsisModuleExtCommandLogApplib.ActionDomainEvent<CommandLogServiceMenu> { }
+        extends IsisModuleExtCommandLogApplib.ActionDomainEvent<CommandLogMenu> { }
 
 
     final CommandLogEntryRepository<? extends CommandLogEntry> commandLogEntryRepository;
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/dom/CommandLogEntry.java b/extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/dom/CommandLogEntry.java
index 0f7df847c8..6060e15910 100644
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/dom/CommandLogEntry.java
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/dom/CommandLogEntry.java
@@ -112,7 +112,7 @@ implements Comparable<CommandLogEntry>, DomainChangeRecord, HasCommandDto {
 
     @UtilityClass
     public static class Nq {
-        public static final String FIND_BY_INTERACTION_ID_STR = LOGICAL_TYPE_NAME + ".findByInteractionIdStr";
+        public static final String FIND_BY_INTERACTION_ID = LOGICAL_TYPE_NAME + ".findByInteractionId";
         public static final String FIND_BY_PARENT = LOGICAL_TYPE_NAME + ".findByParent";
         public static final String FIND_CURRENT = LOGICAL_TYPE_NAME + ".findCurrent";
         public static final String FIND_COMPLETED = LOGICAL_TYPE_NAME + ".findCompleted";
@@ -140,7 +140,7 @@ implements Comparable<CommandLogEntry>, DomainChangeRecord, HasCommandDto {
      */
     public CommandLogEntry(final Command command) {
 
-        setInteractionIdStr(command.getInteractionId().toString());
+        setInteractionId(command.getInteractionId());
         setUsername(command.getUsername());
         setTimestamp(command.getTimestamp());
 
@@ -170,7 +170,7 @@ implements Comparable<CommandLogEntry>, DomainChangeRecord, HasCommandDto {
             final org.apache.isis.extensions.commandlog.applib.dom.ReplayState replayState,
             final int targetIndex) {
 
-        setInteractionIdStr(commandDto.getInteractionId());
+        setInteractionId(UUID.fromString(commandDto.getInteractionId()));
         setUsername(commandDto.getUser());
         setTimestamp(JavaSqlXMLGregorianCalendarMarshalling.toTimestamp(commandDto.getTimestamp()));
 
@@ -231,30 +231,14 @@ implements Comparable<CommandLogEntry>, DomainChangeRecord, HasCommandDto {
     @Retention(RetentionPolicy.RUNTIME)
     public @interface InteractionId {
         class DomainEvent extends PropertyDomainEvent<UUID> {}
+        int MAX_LENGTH = HasInteractionId.InteractionId.MAX_LENGTH;
+        boolean NULLABLE = HasInteractionId.InteractionId.NULLABLE;
+        String ALLOWS_NULL = HasInteractionId.InteractionId.ALLOWS_NULL;
     }
     @Override
     @InteractionId
-    public UUID getInteractionId() {
-        return UUID.fromString(getInteractionIdStr());
-    }
-
-
-    /**
-     * This is the persistence model for {@link #getInteractionId()}; hidden everywhere.
-     */
-    @HasInteractionId.InteractionIdStr // hidden everywhere
-    @java.lang.annotation.Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE })
-    @Retention(RetentionPolicy.RUNTIME)
-    public @interface InteractionIdStr {
-        int MAX_LENGTH = HasInteractionId.InteractionIdStr.MAX_LENGTH;
-        boolean NULLABLE = HasInteractionId.InteractionIdStr.NULLABLE;
-        String ALLOWS_NULL = HasInteractionId.InteractionIdStr.ALLOWS_NULL;
-        String NAME = HasInteractionId.InteractionIdStr.NAME;
-    }
-    @InteractionIdStr
-    public abstract String getInteractionIdStr();
-    public abstract void setInteractionIdStr(String interactionIdStr);
-
+    public abstract UUID getInteractionId();
+    public abstract void setInteractionId(UUID interactionId);
 
 
     @Property(
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/dom/CommandLogEntryRepository.java b/extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/dom/CommandLogEntryRepository.java
index ffbadfd97c..380831e5c1 100644
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/dom/CommandLogEntryRepository.java
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/isis/extensions/commandlog/applib/dom/CommandLogEntryRepository.java
@@ -42,7 +42,6 @@ import org.apache.isis.applib.services.command.Command;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.services.repository.RepositoryService;
 import org.apache.isis.applib.util.schema.CommandDtoUtils;
-import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.schema.cmd.v2.CommandDto;
 import org.apache.isis.schema.cmd.v2.CommandsDto;
 import org.apache.isis.schema.cmd.v2.MapDto;
@@ -83,8 +82,8 @@ public abstract class CommandLogEntryRepository<C extends CommandLogEntry> {
 
     public Optional<C> findByInteractionId(final UUID interactionId) {
         return repositoryService().firstMatch(
-                Query.named(commandLogClass,  CommandLogEntry.Nq.FIND_BY_INTERACTION_ID_STR)
-                        .withParameter("interactionIdStr", interactionId.toString()));
+                Query.named(commandLogClass,  CommandLogEntry.Nq.FIND_BY_INTERACTION_ID)
+                        .withParameter("interactionId", interactionId));
     }
 
     public List<C> findByParent(final CommandLogEntry parent) {
@@ -277,14 +276,14 @@ public abstract class CommandLogEntryRepository<C extends CommandLogEntry> {
 
         final C commandJdo = factoryService.detachedEntity(commandLogClass);
 
-        commandJdo.setInteractionIdStr(dto.getInteractionId());
+        commandJdo.setInteractionId(UUID.fromString(dto.getInteractionId()));
         commandJdo.setTimestamp(JavaSqlXMLGregorianCalendarMarshalling.toTimestamp(dto.getTimestamp()));
         commandJdo.setUsername(dto.getUser());
 
         commandJdo.setReplayState(ReplayState.PENDING);
 
-        final OidDto firstTarget = dto.getTargets().getOid().get(0);
-        commandJdo.setTarget(Bookmark.forOidDto(firstTarget));
+        val firstTargetOidDto = dto.getTargets().getOid().get(0);
+        commandJdo.setTarget(Bookmark.forOidDto(firstTargetOidDto));
         commandJdo.setCommandDto(dto);
         commandJdo.setLogicalMemberIdentifier(dto.getMember().getLogicalMemberIdentifier());
 
@@ -295,9 +294,9 @@ public abstract class CommandLogEntryRepository<C extends CommandLogEntry> {
 
 
     public List<C> saveForReplay(final CommandsDto commandsDto) {
-        List<CommandDto> commandDto = commandsDto.getCommandDto();
-        List<C> commands = new ArrayList<>();
-        for (final CommandDto dto : commandDto) {
+        val commandDtos = commandsDto.getCommandDto();
+        val commands = new ArrayList<C>();
+        for (val dto : commandDtos) {
             commands.add(saveForReplay(dto));
         }
         return commands;
@@ -329,8 +328,8 @@ public abstract class CommandLogEntryRepository<C extends CommandLogEntry> {
 
 
     private C findByInteractionIdElseNull(final UUID interactionId) {
-        val q = Query.named(commandLogClass, CommandLogEntry.Nq.FIND_BY_INTERACTION_ID_STR)
-                .withParameter("interactionIdStr", interactionId.toString());
+        val q = Query.named(commandLogClass, CommandLogEntry.Nq.FIND_BY_INTERACTION_ID)
+                .withParameter("interactionId", interactionId.toString());
         return repositoryService().uniqueMatch(q).orElse(null);
     }
 
diff --git a/extensions/core/commandlog/persistence-jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/IsisModuleExtCommandLogJdo.java b/extensions/core/commandlog/persistence-jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/IsisModuleExtCommandLogJdo.java
index 47812eae41..555781da2a 100644
--- a/extensions/core/commandlog/persistence-jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/IsisModuleExtCommandLogJdo.java
+++ b/extensions/core/commandlog/persistence-jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/IsisModuleExtCommandLogJdo.java
@@ -18,13 +18,10 @@
  */
 package org.apache.isis.extensions.commandlog.jdo;
 
-import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 
 import org.apache.isis.extensions.commandlog.applib.IsisModuleExtCommandLogApplib;
-import org.apache.isis.extensions.commandlog.applib.subscriber.CommandSubscriberForCommandLog;
-import org.apache.isis.extensions.commandlog.applib.app.CommandLogServiceMenu;
 import org.apache.isis.extensions.commandlog.jdo.dom.CommandLogEntry;
 import org.apache.isis.extensions.commandlog.jdo.dom.CommandLogEntryRepository;
 import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
@@ -38,21 +35,12 @@ import org.apache.isis.testing.fixtures.applib.teardown.jdo.TeardownFixtureJdoAb
         // modules
         IsisModuleExtCommandLogApplib.class,
 
-        // @DomainService's
-        CommandLogServiceMenu.class,
-
         // @Service's
         CommandLogEntryRepository.class,
-        org.apache.isis.extensions.commandlog.applib.dom.CommandLogEntry.TableColumnOrderDefault.class,
-        CommandSubscriberForCommandLog.class,
 
         // entities
         CommandLogEntry.class
 })
-@ComponentScan(
-        basePackageClasses= {
-                IsisModuleExtCommandLogJdo.class
-        })
 public class IsisModuleExtCommandLogJdo {
 
     public static final String NAMESPACE = IsisModuleExtCommandLogApplib.NAMESPACE;
diff --git a/extensions/core/commandlog/persistence-jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/dom/CommandLogEntry.java b/extensions/core/commandlog/persistence-jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/dom/CommandLogEntry.java
index aaf80eef0c..52b444fbb7 100644
--- a/extensions/core/commandlog/persistence-jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/dom/CommandLogEntry.java
+++ b/extensions/core/commandlog/persistence-jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/dom/CommandLogEntry.java
@@ -18,6 +18,8 @@
  */
 package org.apache.isis.extensions.commandlog.jdo.dom;
 
+import java.util.UUID;
+
 import javax.inject.Named;
 import javax.jdo.annotations.Column;
 import javax.jdo.annotations.IdentityType;
@@ -35,10 +37,9 @@ import org.apache.isis.applib.annotation.Editing;
 import org.apache.isis.applib.jaxb.PersistentEntityAdapter;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.command.Command;
-import org.apache.isis.extensions.commandlog.jdo.IsisModuleExtCommandLogJdo;
 import org.apache.isis.schema.cmd.v2.CommandDto;
 
-import static org.apache.isis.extensions.commandlog.applib.dom.CommandLogEntry.*;
+import static org.apache.isis.extensions.commandlog.applib.dom.CommandLogEntry.Nq;
 
 import lombok.Getter;
 import lombok.NoArgsConstructor;
@@ -51,15 +52,15 @@ import lombok.Setter;
 @Indices({
         @Index(name = "Command__startedAt__timestamp__IDX", members = { "startedAt", "timestamp" }),
         @Index(name = "Command__timestamp__IDX", members = { "timestamp" }),
-//        @javax.jdo.annotations.Index(name = "CommandJdo__replayState__timestamp__startedAt_IDX", members = { "replayState", "timestamp", "startedAt"}),
-//        @javax.jdo.annotations.Index(name = "CommandJdo__replayState__startedAt__completedAt_IDX", members = {"startedAt", "replayState", "completedAt"}),
+//        @javax.jdo.annotations.Index(name = "Command__replayState__timestamp__startedAt_IDX", members = { "replayState", "timestamp", "startedAt"}),
+//        @javax.jdo.annotations.Index(name = "Command__replayState__startedAt__completedAt_IDX", members = {"startedAt", "replayState", "completedAt"}),
 })
 @Queries( {
     @Query(
-            name  = Nq.FIND_BY_INTERACTION_ID_STR,
+            name  = Nq.FIND_BY_INTERACTION_ID,
             value = "SELECT "
                   + "  FROM " + CommandLogEntry.FQCN + " "
-                  + " WHERE interactionIdStr == :interactionIdStr "),
+                  + " WHERE interactionId == :interactionId "),
     @Query(
             name  = Nq.FIND_BY_PARENT,
             value = "SELECT "
@@ -229,10 +230,10 @@ extends org.apache.isis.extensions.commandlog.applib.dom.CommandLogEntry {
     }
 
     @PrimaryKey
-    @Column(allowsNull = InteractionIdStr.ALLOWS_NULL, name = InteractionIdStr.NAME, length = InteractionIdStr.MAX_LENGTH)
-    @InteractionIdStr
+    @Column(allowsNull = InteractionId.ALLOWS_NULL, length = InteractionId.MAX_LENGTH)
+    @InteractionId
     @Getter @Setter
-    private String interactionIdStr;
+    private UUID interactionId;
 
 
     @Column(allowsNull = Username.ALLOWS_NULL, length = Username.MAX_LENGTH)
@@ -313,6 +314,4 @@ extends org.apache.isis.extensions.commandlog.applib.dom.CommandLogEntry {
     @Getter @Setter
     private String replayStateFailureReason;
 
-
 }
-
diff --git a/extensions/core/commandlog/persistence-jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/dom/CommandLogEntryRepository.java b/extensions/core/commandlog/persistence-jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/dom/CommandLogEntryRepository.java
index 77561536d7..0e47c7bd00 100644
--- a/extensions/core/commandlog/persistence-jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/dom/CommandLogEntryRepository.java
+++ b/extensions/core/commandlog/persistence-jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/dom/CommandLogEntryRepository.java
@@ -34,7 +34,6 @@ import org.apache.isis.extensions.commandlog.jdo.IsisModuleExtCommandLogJdo;
 @Named(CommandLogEntryRepository.LOGICAL_TYPE_NAME)
 @javax.annotation.Priority(PriorityPrecedence.MIDPOINT)
 @Qualifier("Jdo")
-//@Log4j2
 public class CommandLogEntryRepository
 extends org.apache.isis.extensions.commandlog.applib.dom.CommandLogEntryRepository<CommandLogEntry> {
 
diff --git a/extensions/core/commandlog/persistence-jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/IsisModuleExtCommandLogJpa.java b/extensions/core/commandlog/persistence-jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/IsisModuleExtCommandLogJpa.java
index 1fdbd4ca7a..66ab0eaa20 100644
--- a/extensions/core/commandlog/persistence-jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/IsisModuleExtCommandLogJpa.java
+++ b/extensions/core/commandlog/persistence-jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/IsisModuleExtCommandLogJpa.java
@@ -23,8 +23,6 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 
 import org.apache.isis.extensions.commandlog.applib.IsisModuleExtCommandLogApplib;
-import org.apache.isis.extensions.commandlog.applib.app.CommandLogServiceMenu;
-import org.apache.isis.extensions.commandlog.applib.subscriber.CommandSubscriberForCommandLog;
 import org.apache.isis.extensions.commandlog.jpa.dom.CommandLogEntry;
 import org.apache.isis.extensions.commandlog.jpa.dom.CommandLogEntryRepository;
 
@@ -36,19 +34,14 @@ import org.apache.isis.extensions.commandlog.jpa.dom.CommandLogEntryRepository;
         // modules
         IsisModuleExtCommandLogApplib.class,
 
-        // @DomainService's
-        CommandLogServiceMenu.class,
-
         // @Service's
         CommandLogEntryRepository.class,
-        org.apache.isis.extensions.commandlog.applib.dom.CommandLogEntry.TableColumnOrderDefault.class,
-        CommandSubscriberForCommandLog.class,
 
         // entities
         CommandLogEntry.class
 })
 @EntityScan(basePackageClasses = {
-        CommandLogEntry.class,
+    CommandLogEntry.class,
 })
 public class IsisModuleExtCommandLogJpa {
 
diff --git a/extensions/core/commandlog/persistence-jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/dom/CommandLogEntry.java b/extensions/core/commandlog/persistence-jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/dom/CommandLogEntry.java
index b5f7b56239..6e7008224f 100644
--- a/extensions/core/commandlog/persistence-jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/dom/CommandLogEntry.java
+++ b/extensions/core/commandlog/persistence-jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/dom/CommandLogEntry.java
@@ -18,6 +18,8 @@
  */
 package org.apache.isis.extensions.commandlog.jpa.dom;
 
+import java.util.UUID;
+
 import javax.inject.Named;
 import javax.persistence.Basic;
 import javax.persistence.Column;
@@ -43,6 +45,7 @@ import org.apache.isis.applib.jaxb.PersistentEntityAdapter;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.command.Command;
 import org.apache.isis.persistence.jpa.applib.integration.IsisEntityListener;
+import org.apache.isis.persistence.jpa.integration.typeconverters.applib.IsisBookmarkConverter;
 import org.apache.isis.persistence.jpa.integration.typeconverters.schema.v2.IsisCommandDtoConverter;
 import org.apache.isis.schema.cmd.v2.CommandDto;
 
@@ -63,10 +66,10 @@ import lombok.Setter;
 )
 @NamedQueries({
     @NamedQuery(
-            name  = Nq.FIND_BY_INTERACTION_ID_STR,
+            name  = Nq.FIND_BY_INTERACTION_ID,
             query = "SELECT cl "
                   + "  FROM CommandLogEntry cl "
-                  + " WHERE cl.interactionIdStr = :interactionIdStr"),
+                  + " WHERE cl.interactionId = :interactionId"),
     @NamedQuery(
             name  = Nq.FIND_BY_PARENT,
             query = "SELECT cl "
@@ -219,10 +222,10 @@ public class CommandLogEntry extends org.apache.isis.extensions.commandlog.appli
     }
 
     @Id
-    @Column(nullable = InteractionIdStr.NULLABLE, name = InteractionIdStr.NAME, length = InteractionIdStr.MAX_LENGTH)
-    @InteractionIdStr
+    @Column(nullable = InteractionId.NULLABLE, length = InteractionId.MAX_LENGTH)
+    @InteractionId
     @Getter @Setter
-    private String interactionIdStr;
+    private UUID interactionId;
 
 
     @Column(nullable = Username.NULLABLE, length = Username.MAX_LENGTH)
@@ -237,6 +240,7 @@ public class CommandLogEntry extends org.apache.isis.extensions.commandlog.appli
     private java.sql.Timestamp timestamp;
 
 
+    @Convert(converter = IsisBookmarkConverter.class)
     @Column(nullable = Target.NULLABLE, length = Target.MAX_LENGTH)
     @Target
     @Getter @Setter
@@ -260,9 +264,9 @@ public class CommandLogEntry extends org.apache.isis.extensions.commandlog.appli
     private String logicalMemberIdentifier;
 
 
+    @Convert(converter = IsisCommandDtoConverter.class)
     @Lob @Basic(fetch = FetchType.LAZY)
     @Column(nullable = CommandDtoAnnot.NULLABLE, columnDefinition = "CLOB")
-    @Convert(converter = IsisCommandDtoConverter.class)
     @CommandDtoAnnot
     @Getter @Setter
     private CommandDto commandDto;
@@ -280,6 +284,7 @@ public class CommandLogEntry extends org.apache.isis.extensions.commandlog.appli
     private java.sql.Timestamp completedAt;
 
 
+    @Convert(converter = IsisBookmarkConverter.class)
     @Column(nullable = Result.NULLABLE, length = Result.MAX_LENGTH)
     @Result
     @Getter @Setter
@@ -292,7 +297,8 @@ public class CommandLogEntry extends org.apache.isis.extensions.commandlog.appli
     @Getter @Setter
     private String exception;
 
-    @Column(nullable = ReplayState.NULLABLE, length = ReplayState.MAX_LENGTH) @Enumerated(EnumType.STRING)
+    @Column(nullable = ReplayState.NULLABLE, length = ReplayState.MAX_LENGTH)
+    @Enumerated(EnumType.STRING)
     @ReplayState
     @Getter @Setter
     private org.apache.isis.extensions.commandlog.applib.dom.ReplayState replayState;
@@ -303,6 +309,4 @@ public class CommandLogEntry extends org.apache.isis.extensions.commandlog.appli
     @Getter @Setter
     private String replayStateFailureReason;
 
-
-
 }
diff --git a/extensions/core/commandlog/persistence-jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/dom/CommandLogEntryRepository.java b/extensions/core/commandlog/persistence-jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/dom/CommandLogEntryRepository.java
index b5d2284886..155c66ccfd 100644
--- a/extensions/core/commandlog/persistence-jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/dom/CommandLogEntryRepository.java
+++ b/extensions/core/commandlog/persistence-jpa/src/main/java/org/apache/isis/extensions/commandlog/jpa/dom/CommandLogEntryRepository.java
@@ -65,7 +65,6 @@ import lombok.val;
 @Named(CommandLogEntryRepository.LOGICAL_TYPE_NAME)
 @javax.annotation.Priority(PriorityPrecedence.MIDPOINT)
 @Qualifier("Jpa")
-//@Log4j2
 public class CommandLogEntryRepository
 extends org.apache.isis.extensions.commandlog.applib.dom.CommandLogEntryRepository<CommandLogEntry> {
 
diff --git a/extensions/core/executionlog/applib/src/main/java/org/apache/isis/extensions/executionlog/applib/IsisModuleExtExecutionLogApplib.java b/extensions/core/executionlog/applib/src/main/java/org/apache/isis/extensions/executionlog/applib/IsisModuleExtExecutionLogApplib.java
index ef25c85ea8..f3e5013d31 100644
--- a/extensions/core/executionlog/applib/src/main/java/org/apache/isis/extensions/executionlog/applib/IsisModuleExtExecutionLogApplib.java
+++ b/extensions/core/executionlog/applib/src/main/java/org/apache/isis/extensions/executionlog/applib/IsisModuleExtExecutionLogApplib.java
@@ -22,10 +22,19 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 
 import org.apache.isis.core.config.util.SpringProfileUtil;
+import org.apache.isis.extensions.executionlog.applib.app.ExecutionLogMenu;
+import org.apache.isis.extensions.executionlog.applib.dom.ExecutionLogEntry;
+import org.apache.isis.extensions.executionlog.applib.spiimpl.ExecutionSubscriberForLog;
 import org.apache.isis.testing.fixtures.applib.modules.ModuleWithFixtures;
 
 @Configuration
 @Import({
+        // @DomainService's
+        ExecutionLogMenu.class,
+
+        // @Service's
+        ExecutionSubscriberForLog.class,
+        ExecutionLogEntry.TableColumnOrderDefault.class
 })
 public class IsisModuleExtExecutionLogApplib
 implements ModuleWithFixtures {
diff --git a/extensions/core/executionlog/applib/src/main/java/org/apache/isis/extensions/executionlog/applib/app/ExecutionLogMenu.java b/extensions/core/executionlog/applib/src/main/java/org/apache/isis/extensions/executionlog/applib/app/ExecutionLogMenu.java
new file mode 100644
index 0000000000..646ef37dc1
--- /dev/null
+++ b/extensions/core/executionlog/applib/src/main/java/org/apache/isis/extensions/executionlog/applib/app/ExecutionLogMenu.java
@@ -0,0 +1,69 @@
+/*
+ *  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.extensions.executionlog.applib.app;
+
+import java.time.LocalDate;
+import java.time.ZoneId;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.DomainServiceLayout;
+import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.applib.annotation.PriorityPrecedence;
+import org.apache.isis.applib.services.clock.ClockService;
+import org.apache.isis.extensions.executionlog.applib.IsisModuleExtExecutionLogApplib;
+import org.apache.isis.extensions.executionlog.applib.dom.ExecutionLogEntry;
+import org.apache.isis.extensions.executionlog.applib.dom.ExecutionLogEntryRepository;
+
+import lombok.RequiredArgsConstructor;
+
+/**
+ * @since 2.0 {@index}
+ */
+@Named(ExecutionLogMenu.LOGICAL_TYPE_NAME)
+@DomainService(
+    nature = NatureOfService.VIEW
+)
+@DomainServiceLayout(
+    named = "Activity",
+    menuBar = DomainServiceLayout.MenuBar.SECONDARY
+)
+@javax.annotation.Priority(PriorityPrecedence.EARLY)
+@RequiredArgsConstructor(onConstructor_ = { @Inject })
+public class ExecutionLogMenu {
+
+    public static final String LOGICAL_TYPE_NAME =
+            IsisModuleExtExecutionLogApplib.NAMESPACE + ".ExecutionLogMenu";
+
+    public static abstract class ActionDomainEvent
+        extends IsisModuleExtExecutionLogApplib.ActionDomainEvent<ExecutionLogMenu> { }
+
+
+    final ExecutionLogEntryRepository<? extends ExecutionLogEntry> executionLogEntryRepository;
+    final ClockService clockService;
+
+
+
+    private LocalDate now() {
+        return clockService.getClock().nowAsLocalDate(ZoneId.systemDefault());
+    }
+}
+
diff --git a/extensions/core/executionlog/applib/src/main/java/org/apache/isis/extensions/executionlog/applib/dom/ExecutionLogEntry.java b/extensions/core/executionlog/applib/src/main/java/org/apache/isis/extensions/executionlog/applib/dom/ExecutionLogEntry.java
index 646dd631a2..9fe2367ccc 100644
--- a/extensions/core/executionlog/applib/src/main/java/org/apache/isis/extensions/executionlog/applib/dom/ExecutionLogEntry.java
+++ b/extensions/core/executionlog/applib/src/main/java/org/apache/isis/extensions/executionlog/applib/dom/ExecutionLogEntry.java
@@ -33,6 +33,7 @@ import javax.validation.constraints.Digits;
 
 import org.springframework.stereotype.Service;
 
+import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.annotation.DomainObjectLayout;
 import org.apache.isis.applib.annotation.Editing;
@@ -104,16 +105,25 @@ implements Comparable<ExecutionLogEntry>, DomainChangeRecord, HasInteractionIdAn
     public static class Nq {
     }
 
+    @UtilityClass
+    protected static class Util {
+        public static String abbreviated(String str, int maxLength) {
+            return str != null ? (str.length() < maxLength ? str : str.substring(0, maxLength - 3) + "...") : null;
+        }
+    }
+
+
+
     public ExecutionLogEntry(@NonNull Execution<? extends MemberExecutionDto,?> execution) {
 
-        val interactionIdStr = execution.getInteraction().getInteractionId().toString();
-        setInteractionIdStr(interactionIdStr);
+        val interactionId = execution.getInteraction().getInteractionId();
+        setInteractionId(interactionId);
 
         val memberExecutionDto = execution.getDto();
         setSequence(memberExecutionDto.getSequence());
 
         val interactionDto = new InteractionDto();
-        interactionDto.setInteractionId(interactionIdStr);
+        interactionDto.setInteractionId(interactionId.toString());
         interactionDto.setExecution(memberExecutionDto);
         setInteractionDto(interactionDto);
 
@@ -156,6 +166,14 @@ implements Comparable<ExecutionLogEntry>, DomainChangeRecord, HasInteractionIdAn
     }
 
 
+    /**
+     * The unique identifier (a GUID) of the {@link org.apache.isis.applib.services.iactn.Interaction} in which this execution occurred.
+     *
+     * <p>
+     * The combination of ({@link #getInteractionId() interactionId}, {@link #getSequence() sequence}) makes up the
+     * primary key.
+     * </p>
+     */
     @Property(
             domainEvent = InteractionId.DomainEvent.class
     )
@@ -164,33 +182,25 @@ implements Comparable<ExecutionLogEntry>, DomainChangeRecord, HasInteractionIdAn
     @Retention(RetentionPolicy.RUNTIME)
     public @interface InteractionId {
         class DomainEvent extends PropertyDomainEvent<UUID> {}
+        int MAX_LENGTH = HasInteractionId.InteractionId.MAX_LENGTH;
+        boolean NULLABLE = HasInteractionId.InteractionId.NULLABLE;
+        String ALLOWS_NULL = HasInteractionId.InteractionId.ALLOWS_NULL;
     }
     @Override
     @InteractionId
-    public UUID getInteractionId() {
-        return UUID.fromString(getInteractionIdStr());
-    }
+    public abstract UUID getInteractionId();
+    public abstract void setInteractionId(UUID interactionId);
 
 
 
     /**
-     * This is the persistence model for {@link #getInteractionId()}; hidden everywhere.
+     * The 0-based additional identifier of an execution event within the given {@link #getInteractionId() interaction}.
+     *
+     * <p>
+     * The combination of ({@link #getInteractionId() interactionId}, {@link #getSequence() sequence}) makes up the
+     * primary key.
+     * </p>
      */
-    @HasInteractionId.InteractionIdStr // hidden everywhere
-    @java.lang.annotation.Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE })
-    @Retention(RetentionPolicy.RUNTIME)
-    public @interface InteractionIdStr {
-        int MAX_LENGTH = HasInteractionId.InteractionIdStr.MAX_LENGTH;
-        boolean NULLABLE = HasInteractionId.InteractionIdStr.NULLABLE;
-        String ALLOWS_NULL = HasInteractionId.InteractionIdStr.ALLOWS_NULL;
-        String NAME = HasInteractionId.InteractionIdStr.NAME;
-    }
-    @InteractionIdStr
-    public abstract String getInteractionIdStr();
-    public abstract void setInteractionIdStr(String interactionIdStr);
-
-
-
     @Property(
             domainEvent = Sequence.DomainEvent.class
     )
@@ -218,6 +228,7 @@ implements Comparable<ExecutionLogEntry>, DomainChangeRecord, HasInteractionIdAn
         class DomainEvent extends PropertyDomainEvent<ExecutionLogEntryType> {}
         boolean NULLABLE = false;
         String ALLOWS_NULL = "false";
+        int MAX_LENGTH = 30;
     }
     @ExecutionType
     public abstract ExecutionLogEntryType getExecutionType();
@@ -281,6 +292,14 @@ implements Comparable<ExecutionLogEntry>, DomainChangeRecord, HasInteractionIdAn
 
 
 
+    /**
+     * String representation of the invoked action or edited property.
+     *
+     * <p>
+     * This is the <i>logical</i> member identifier because it does not matter whether the action/property is declared
+     * on the type or is contributed.
+     *
+     */
     @Property(
             domainEvent = LogicalMemberIdentifier.DomainEvent.class,
             editing = Editing.DISABLED
@@ -302,8 +321,6 @@ implements Comparable<ExecutionLogEntry>, DomainChangeRecord, HasInteractionIdAn
 
 
 
-
-
     @Property(
             domainEvent = InteractionDtoAnnot.DomainEvent.class
     )
@@ -337,6 +354,7 @@ implements Comparable<ExecutionLogEntry>, DomainChangeRecord, HasInteractionIdAn
         boolean NULLABLE = false;
         String ALLOWS_NULL = "false";
     }
+    @StartedAt
     public abstract java.sql.Timestamp getStartedAt();
     public abstract void setStartedAt(java.sql.Timestamp startedAt);
 
@@ -357,6 +375,7 @@ implements Comparable<ExecutionLogEntry>, DomainChangeRecord, HasInteractionIdAn
         boolean NULLABLE = false;
         String ALLOWS_NULL = "false";
     }
+    @CompletedAt
     public abstract java.sql.Timestamp getCompletedAt();
     public abstract void setCompletedAt(java.sql.Timestamp completedAt);
 
diff --git a/extensions/core/executionlog/persistence-jdo/logging-dn-enhance.properties b/extensions/core/executionlog/persistence-jdo/logging-dn-enhance.properties
new file mode 100644
index 0000000000..515c2a2966
--- /dev/null
+++ b/extensions/core/executionlog/persistence-jdo/logging-dn-enhance.properties
@@ -0,0 +1,48 @@
+#
+#  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.
+#
+
+log4j.appender.A1=org.apache.log4j.FileAppender
+log4j.appender.A1.File=datanucleus.log
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%d{HH:mm:ss,SSS} (%t) %-5p [%c] - %m%n
+
+
+# overriding all those below... 
+log4j.category.DataNucleus=ERROR
+
+log4j.category.DataNucleus.Persistence=INFO, A1
+log4j.category.DataNucleus.Transaction=INFO, A1
+log4j.category.DataNucleus.Connection=INFO, A1
+log4j.category.DataNucleus.Query=INFO, A1
+log4j.category.DataNucleus.Cache=INFO, A1
+log4j.category.DataNucleus.MetaData=INFO, A1
+log4j.category.DataNucleus.Datastore=INFO, A1
+log4j.category.DataNucleus.Datastore.Schema=INFO, A1
+log4j.category.DataNucleus.Datastore.Persist=INFO, A1
+log4j.category.DataNucleus.Datastore.Retrieve=INFO, A1
+#Log of all 'native' statements sent to the datastore
+log4j.category.DataNucleus.Datastore.Native=INFO, A1 
+log4j.category.DataNucleus.General=INFO, A1
+#All messages relating to object lifecycle changes
+log4j.category.DataNucleus.Lifecycle=INFO, A1
+log4j.category.DataNucleus.ValueGeneration=INFO, A1
+log4j.category.DataNucleus.Enhancer=INFO, A1
+log4j.category.DataNucleus.SchemaTool=INFO, A1
+log4j.category.DataNucleus.JDO=INFO, A1
+ 
\ No newline at end of file
diff --git a/extensions/core/executionlog/persistence-jdo/pom.xml b/extensions/core/executionlog/persistence-jdo/pom.xml
index 0696fc69bb..38db4e80e2 100644
--- a/extensions/core/executionlog/persistence-jdo/pom.xml
+++ b/extensions/core/executionlog/persistence-jdo/pom.xml
@@ -50,7 +50,7 @@
 
 	    <dependency>
 	        <groupId>org.apache.isis.extensions</groupId>
-	        <artifactId>isis-extensions-commandlog-applib</artifactId>
+	        <artifactId>isis-extensions-executionlog-applib</artifactId>
 	    </dependency>
 
         <!-- PERSISTENCE -->
@@ -73,6 +73,10 @@
 			<artifactId>isis-testing-integtestsupport-applib</artifactId>
 			<scope>test</scope>
 		</dependency>
+        <dependency>
+            <groupId>org.apache.isis.extensions</groupId>
+            <artifactId>isis-extensions-executionlog-applib</artifactId>
+        </dependency>
 
     </dependencies>
 
diff --git a/extensions/core/commandlog/persistence-jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/IsisModuleExtCommandLogJdo.java b/extensions/core/executionlog/persistence-jdo/src/main/java/org/apache/isis/extensions/executionlog/jdo/IsisModuleExtExecutionLogJdo.java
similarity index 65%
copy from extensions/core/commandlog/persistence-jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/IsisModuleExtCommandLogJdo.java
copy to extensions/core/executionlog/persistence-jdo/src/main/java/org/apache/isis/extensions/executionlog/jdo/IsisModuleExtExecutionLogJdo.java
index 47812eae41..288bdd2b1f 100644
--- a/extensions/core/commandlog/persistence-jdo/src/main/java/org/apache/isis/extensions/commandlog/jdo/IsisModuleExtCommandLogJdo.java
+++ b/extensions/core/executionlog/persistence-jdo/src/main/java/org/apache/isis/extensions/executionlog/jdo/IsisModuleExtExecutionLogJdo.java
@@ -16,17 +16,15 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.extensions.commandlog.jdo;
+package org.apache.isis.extensions.executionlog.jdo;
 
-import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 
 import org.apache.isis.extensions.commandlog.applib.IsisModuleExtCommandLogApplib;
-import org.apache.isis.extensions.commandlog.applib.subscriber.CommandSubscriberForCommandLog;
-import org.apache.isis.extensions.commandlog.applib.app.CommandLogServiceMenu;
-import org.apache.isis.extensions.commandlog.jdo.dom.CommandLogEntry;
-import org.apache.isis.extensions.commandlog.jdo.dom.CommandLogEntryRepository;
+import org.apache.isis.extensions.executionlog.applib.IsisModuleExtExecutionLogApplib;
+import org.apache.isis.extensions.executionlog.applib.dom.ExecutionLogEntry;
+import org.apache.isis.extensions.executionlog.applib.dom.ExecutionLogEntryRepository;
 import org.apache.isis.testing.fixtures.applib.fixturescripts.FixtureScript;
 import org.apache.isis.testing.fixtures.applib.teardown.jdo.TeardownFixtureJdoAbstract;
 
@@ -36,24 +34,15 @@ import org.apache.isis.testing.fixtures.applib.teardown.jdo.TeardownFixtureJdoAb
 @Configuration
 @Import({
         // modules
-        IsisModuleExtCommandLogApplib.class,
-
-        // @DomainService's
-        CommandLogServiceMenu.class,
+        IsisModuleExtExecutionLogApplib.class,
 
         // @Service's
-        CommandLogEntryRepository.class,
-        org.apache.isis.extensions.commandlog.applib.dom.CommandLogEntry.TableColumnOrderDefault.class,
-        CommandSubscriberForCommandLog.class,
+        ExecutionLogEntryRepository.class,
 
         // entities
-        CommandLogEntry.class
+        ExecutionLogEntry.class
 })
-@ComponentScan(
-        basePackageClasses= {
-                IsisModuleExtCommandLogJdo.class
-        })
-public class IsisModuleExtCommandLogJdo {
+public class IsisModuleExtExecutionLogJdo {
 
     public static final String NAMESPACE = IsisModuleExtCommandLogApplib.NAMESPACE;
     public static final String SCHEMA = IsisModuleExtCommandLogApplib.SCHEMA;
@@ -66,7 +55,7 @@ public class IsisModuleExtCommandLogJdo {
         return new TeardownFixtureJdoAbstract() {
             @Override
             protected void execute(final ExecutionContext executionContext) {
-                deleteFrom(CommandLogEntry.class);
+                deleteFrom(ExecutionLogEntry.class);
             }
         };
     }
diff --git a/extensions/core/executionlog/persistence-jdo/src/main/java/org/apache/isis/extensions/executionlog/jdo/dom/ExecutionLogEntry.java b/extensions/core/executionlog/persistence-jdo/src/main/java/org/apache/isis/extensions/executionlog/jdo/dom/ExecutionLogEntry.java
new file mode 100644
index 0000000000..cc238548f7
--- /dev/null
+++ b/extensions/core/executionlog/persistence-jdo/src/main/java/org/apache/isis/extensions/executionlog/jdo/dom/ExecutionLogEntry.java
@@ -0,0 +1,218 @@
+/*
+ *  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.extensions.executionlog.jdo.dom;
+
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.util.UUID;
+
+import javax.inject.Named;
+import javax.jdo.annotations.Column;
+import javax.jdo.annotations.IdentityType;
+import javax.jdo.annotations.PersistenceCapable;
+import javax.jdo.annotations.Persistent;
+import javax.jdo.annotations.PrimaryKey;
+import javax.jdo.annotations.Queries;
+import javax.jdo.annotations.Query;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.annotation.DomainObject;
+import org.apache.isis.applib.annotation.DomainObjectLayout;
+import org.apache.isis.applib.annotation.Editing;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.annotation.Property;
+import org.apache.isis.applib.annotation.PropertyLayout;
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.jaxb.PersistentEntitiesAdapter;
+import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.applib.util.TitleBuffer;
+import org.apache.isis.extensions.executionlog.applib.IsisModuleExtExecutionLogApplib;
+import org.apache.isis.extensions.executionlog.applib.dom.ExecutionLogEntryPK;
+import org.apache.isis.extensions.executionlog.applib.dom.ExecutionLogEntryType;
+import org.apache.isis.schema.ixn.v2.InteractionDto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@PersistenceCapable(
+        identityType= IdentityType.APPLICATION,
+        schema = "isispublishmq",
+        table="PublishedEvent",
+        objectIdClass= ExecutionLogEntryPK.class)
+@Queries( {
+    @Query(
+            name="findByTransactionId", language="JDOQL",
+            value="SELECT "
+                    + "FROM com.ecpnv.platform.v1.extensions.executionlog.dom.jdo.events.PublishedEvent "
+                    + "WHERE transactionId == :transactionId "
+                    + "ORDER BY timestamp DESC, sequence DESC"),
+    @Query(
+            name="findByTransactionIdAndSequence", language="JDOQL",
+            value="SELECT "
+                    + "FROM com.ecpnv.platform.v1.extensions.executionlog.dom.jdo.events.PublishedEvent "
+                    + "WHERE transactionId == :transactionId "
+                    + "&&    sequence      == :sequence "),
+    @Query(
+            name="findByTargetAndTimestampBetween", language="JDOQL",
+            value="SELECT "
+                    + "FROM com.ecpnv.platform.v1.extensions.executionlog.dom.jdo.events.PublishedEvent "
+                    + "WHERE targetStr == :targetStr "
+                    + "&& timestamp >= :from "
+                    + "&& timestamp <= :to "
+                    + "ORDER BY timestamp DESC, transactionId DESC, sequence DESC"),
+    @Query(
+            name="findByTargetAndTimestampAfter", language="JDOQL",
+            value="SELECT "
+                    + "FROM com.ecpnv.platform.v1.extensions.executionlog.dom.jdo.events.PublishedEvent "
+                    + "WHERE targetStr == :targetStr "
+                    + "&& timestamp >= :from "
+                    + "ORDER BY timestamp DESC, transactionId DESC, sequence DESC"),
+    @Query(
+            name="findByTargetAndTimestampBefore", language="JDOQL",
+            value="SELECT "
+                    + "FROM com.ecpnv.platform.v1.extensions.executionlog.dom.jdo.events.PublishedEvent "
+                    + "WHERE targetStr == :targetStr "
+                    + "&& timestamp <= :to "
+                    + "ORDER BY timestamp DESC, transactionId DESC, sequence DESC"),
+    @Query(
+            name="findByTarget", language="JDOQL",
+            value="SELECT "
+                    + "FROM com.ecpnv.platform.v1.extensions.executionlog.dom.jdo.events.PublishedEvent "
+                    + "WHERE targetStr == :targetStr "
+                    + "ORDER BY timestamp DESC, transactionId DESC, sequence DESC"),
+    @Query(
+            name="findByTimestampBetween", language="JDOQL",
+            value="SELECT "
+                    + "FROM com.ecpnv.platform.v1.extensions.executionlog.dom.jdo.events.PublishedEvent "
+                    + "WHERE timestamp >= :from "
+                    + "&&    timestamp <= :to "
+                    + "ORDER BY timestamp DESC, transactionId DESC, sequence DESC"),
+    @Query(
+            name="findByTimestampAfter", language="JDOQL",
+            value="SELECT "
+                    + "FROM com.ecpnv.platform.v1.extensions.executionlog.dom.jdo.events.PublishedEvent "
+                    + "WHERE timestamp >= :from "
+                    + "ORDER BY timestamp DESC, transactionId DESC, sequence DESC"),
+    @Query(
+            name="findByTimestampBefore", language="JDOQL",
+            value="SELECT "
+                    + "FROM com.ecpnv.platform.v1.extensions.executionlog.dom.jdo.events.PublishedEvent "
+                    + "WHERE timestamp <= :to "
+                    + "ORDER BY timestamp DESC, transactionId DESC, sequence DESC"),
+    @Query(
+            name="find", language="JDOQL",
+            value="SELECT "
+                    + "FROM com.ecpnv.platform.v1.extensions.executionlog.dom.jdo.events.PublishedEvent "
+                    + "ORDER BY timestamp DESC, transactionId DESC, sequence DESC"),
+    @Query(
+            name="findRecentByUser", language="JDOQL",
+            value="SELECT "
+                    + "FROM com.ecpnv.platform.v1.extensions.executionlog.dom.jdo.events.PublishedEvent "
+                    + "WHERE user == :user "
+                    + "ORDER BY timestamp DESC, transactionId DESC, sequence DESC "
+                    + "RANGE 0,30"),
+    @Query(
+            name="findRecentByTarget", language="JDOQL",
+            value="SELECT "
+                    + "FROM com.ecpnv.platform.v1.extensions.executionlog.dom.jdo.events.PublishedEvent "
+                    + "WHERE targetStr == :targetStr "
+                    + "ORDER BY timestamp DESC, transactionId DESC, sequence DESC "
+                    + "RANGE 0,30")
+})
+@Named("isispublishmq.PublishedEvent")
+@DomainObject(
+        editing = Editing.DISABLED
+)
+@XmlJavaTypeAdapter(PersistentEntitiesAdapter.class)
+public class ExecutionLogEntry extends org.apache.isis.extensions.executionlog.applib.dom.ExecutionLogEntry {
+
+
+    @PrimaryKey
+    @InteractionId
+    @Column(allowsNull = InteractionId.ALLOWS_NULL, length=InteractionId.MAX_LENGTH)
+    @Getter @Setter
+    private UUID interactionId;
+
+
+    @PrimaryKey
+    @Sequence
+    @Column(allowsNull = Sequence.ALLOWS_NULL)
+    @Getter @Setter
+    private int sequence;
+
+
+    @Column(allowsNull = ExecutionType.ALLOWS_NULL, length = ExecutionType.MAX_LENGTH)
+    @ExecutionType
+    @Getter @Setter
+    private ExecutionLogEntryType executionType;
+
+
+    @Column(allowsNull = Username.ALLOWS_NULL, length = Username.MAX_LENGTH)
+    @Username
+    @Getter @Setter
+    private String username;
+
+
+    @Persistent
+    @Column(allowsNull = Timestamp.ALLOWS_NULL)
+    @Timestamp
+    @Getter @Setter
+    private java.sql.Timestamp timestamp;
+
+
+    @Persistent
+    @Column(allowsNull = Target.ALLOWS_NULL, length = Target.MAX_LENGTH)
+    @Target
+    @Getter @Setter
+    private Bookmark target;
+
+
+    @Column(allowsNull = LogicalMemberIdentifier.ALLOWS_NULL, length= LogicalMemberIdentifier.MAX_LENGTH)
+    @LogicalMemberIdentifier
+    @Getter
+    private String logicalMemberIdentifier;
+    public void setLogicalMemberIdentifier(final String logicalMemberIdentifier) {
+        this.logicalMemberIdentifier = Util.abbreviated(logicalMemberIdentifier, LogicalMemberIdentifier.MAX_LENGTH);
+    }
+
+
+    @Persistent
+    @Column(allowsNull = InteractionDtoAnnot.ALLOWS_NULL, jdbcType = "CLOB", sqlType = "LONGVARCHAR")
+    @InteractionDtoAnnot
+    @Getter @Setter
+    private InteractionDto interactionDto;
+
+
+    @Persistent
+    @Column(allowsNull = StartedAt.ALLOWS_NULL)
+    @StartedAt
+    @Getter @Setter
+    private java.sql.Timestamp startedAt;
+
+
+    @Persistent
+    @Column(allowsNull = CompletedAt.ALLOWS_NULL)
+    @CompletedAt
+    @Getter @Setter
+    private java.sql.Timestamp completedAt;
+
+
+
+}
diff --git a/pom.xml b/pom.xml
index 027ff9a263..1aa3bdf604 100644
--- a/pom.xml
+++ b/pom.xml
@@ -30,6 +30,8 @@
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <maven.deploy.skip>true</maven.deploy.skip> <!-- don't deploy the aggregator -->
+
+		<maven-timeline.version>1.6</maven-timeline.version>
     </properties>
 
 	<scm>
@@ -39,6 +41,16 @@
 		<tag>HEAD</tag>
 	</scm>
 
+	<build>
+		<extensions>
+			<extension>
+				<groupId>io.takari.maven</groupId>
+				<artifactId>maven-timeline</artifactId>
+				<version>${maven-timeline.version}</version>
+			</extension>
+		</extensions>
+	</build>
+
 	<profiles>
 
 		<!-- ESSENTIAL MODULES -->
@@ -126,7 +138,7 @@
 				<module>tooling</module>
 			</modules>
 		</profile>
-		
+
 		<profile>
 			<id>module-all-except-kroviz</id>
 			<activation>
@@ -137,14 +149,14 @@
 			<modules>
 				<module>antora</module>
 				<module>examples/demo</module>
-				
+
 				<!-- incubator, without kroviz -->
 				<module>incubator/viewers/graphql</module>
 				<module>incubator/viewers/javafx</module>
 				<module>incubator/viewers/vaadin</module>
 				<module>valuetypes/prism/vaadin</module>
 				<module>valuetypes/asciidoc/ui/vaadin</module>
-				
+
 				<module>regressiontests</module>
 				<module>tooling</module>
 			</modules>
diff --git a/serve-timeline.sh b/serve-timeline.sh
new file mode 100644
index 0000000000..2c6b653a09
--- /dev/null
+++ b/serve-timeline.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+#
+# requires JDK 18
+#
+jwebserver -d $(pwd)/target/timeline -b ::
\ No newline at end of file