You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by da...@apache.org on 2023/03/06 11:41:07 UTC

[causeway] 01/02: CAUSEWAY-3368 : updates docs.

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

danhaywood pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 44965a2cc0d4d311ca8ebe2c85e6b484fcc3d038
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Mon Mar 6 11:35:54 2023 +0000

    CAUSEWAY-3368 : updates docs.
---
 .../pages/index/services/command/Command.adoc      | 29 +++++++++++++++
 .../services/command/CommandExecutorService.adoc   | 24 ++++++------
 .../pages/index/services/iactn/Interaction.adoc    |  2 +-
 .../services/publishing/log/CommandLogger.adoc     |  2 +
 .../services/publishing/spi/CommandSubscriber.adoc | 32 ++++++++++++++--
 .../index/services/repository/EntityState.adoc     |  8 ++--
 .../modules/applib/pages/index/value/Blob.adoc     |  3 ++
 .../modules/commons/pages/index/io/DataSource.adoc | 31 ++++++++++++++++
 .../modules/commons/pages/index/io/HashUtils.adoc  | 40 ++++++++++++++++++++
 .../services/publishing/CommandPublisher.adoc      | 26 ++++++++++++-
 .../commandlog/applib/dom/CommandLogEntry.adoc     |  3 +-
 .../subscriber/CommandSubscriberForCommandLog.adoc |  2 +
 core/adoc/modules/_overview/pages/about.adoc       |  9 +++--
 .../config/pages/sections/causeway.extensions.adoc | 43 +++++++++++++++++++---
 14 files changed, 220 insertions(+), 34 deletions(-)

diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/command/Command.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/command/Command.adoc
index a77f3ee363..dd42252fdf 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/command/Command.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/command/Command.adoc
@@ -17,14 +17,22 @@ That said, if the sub-action is invoked asynchronously (using _WrapperFactory#as
 .Command.java
 ----
 class Command {
+  Command(UUID interactionId)
+  UUID getInteractionId()     // <.>
   String getUsername()     // <.>
   Timestamp getTimestamp()     // <.>
+  CommandDto getCommandDto()     // <.>
   Bookmark getTarget()     // <.>
   String getLogicalMemberIdentifier()     // <.>
   Updater updater()     // <.>
 }
 ----
 
+<.> xref:#getInteractionId_[getInteractionId()]
++
+--
+The unique identifier of this command (inherited from xref:refguide:applib:index/mixins/system/HasInteractionId.adoc[HasInteractionId] )
+--
 <.> xref:#getUsername_[getUsername()]
 +
 --
@@ -35,6 +43,11 @@ The user that created the command.
 --
 The date/time at which this command was created.
 --
+<.> xref:#getCommandDto_[getCommandDto()]
++
+--
+Serializable representation of the action invocation/property edit.
+--
 <.> xref:#getTarget_[getTarget()]
 +
 --
@@ -53,6 +66,15 @@ Derived from _#getCommandDto()_ , holds a string representation of the invoked a
 
 == Members
 
+[#getInteractionId_]
+=== getInteractionId()
+
+The unique identifier of this command (inherited from xref:refguide:applib:index/mixins/system/HasInteractionId.adoc[HasInteractionId] )
+
+In all cases this be the same as the xref:refguide:applib:index/services/iactn/Interaction.adoc[Interaction] that wraps the command, and can be used to correlate also to any audit records ( _org.apache.causeway.applib.services.publishing.spi.EntityPropertyChange_ s resulting from state changes occurring as a consequence of the command.
+
+Note that this is immutable in almost all cases. The one exception is if the Command is being executed through the xref:refguide:applib:index/services/command/CommandExecutorService.adoc[CommandExecutorService] , for example when executing a async action that has been reified into a _CommandDto_ . In such cases, the _CommandExecutorService#executeCommand(CommandDto)_ will _replace_ the original Id with that of the DTO being executed.
+
 [#getUsername_]
 === getUsername()
 
@@ -67,6 +89,13 @@ The date/time at which this command was created.
 
 Derived from _#getCommandDto()_ 's _CommandDto#getTimestamp()_ .
 
+[#getCommandDto_]
+=== getCommandDto()
+
+Serializable representation of the action invocation/property edit.
+
+When the framework sets this (through an internal API), it is expected that the _CommandDto#getUsername() username_ , _CommandDto#getTimestamp() timestamp_ , _CommandDto#getTargets() target(s)_ and _CommandDto#getMember() member_ will be populated. The _#getInteractionId()_ , _#getUsername()_ , _#getTimestamp()_ and _#getTarget()_ are all derived from the provided _CommandDto_ .
+
 [#getTarget_]
 === getTarget()
 
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/command/CommandExecutorService.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/command/CommandExecutorService.adoc
index 5665ff5e77..591fd44c61 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/command/CommandExecutorService.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/command/CommandExecutorService.adoc
@@ -10,9 +10,9 @@ Provides a mechanism to execute a xref:refguide:applib:index/services/command/Co
 ----
 interface CommandExecutorService {
   Try<Bookmark> executeCommand(InteractionContextPolicy interactionContextPolicy, Command command)     // <.>
-  Try<Bookmark> executeCommand(InteractionContextPolicy interactionContextPolicy, CommandDto commandDto, CommandOutcomeHandler outcomeHandler)     // <.>
+  Try<Bookmark> executeCommand(InteractionContextPolicy interactionContextPolicy, CommandDto commandDto)     // <.>
   Try<Bookmark> executeCommand(Command command)     // <.>
-  Try<Bookmark> executeCommand(CommandDto commandDto, CommandOutcomeHandler outcomeHandler)     // <.>
+  Try<Bookmark> executeCommand(CommandDto commandDto)     // <.>
 }
 ----
 
@@ -21,7 +21,7 @@ interface CommandExecutorService {
 --
 Executes the specified xref:refguide:applib:index/services/command/Command.adoc[Command] using the required _InteractionContextPolicy_ , updating the Command (or its persistent equivalent) afterwards (for example, setting its _Command#getCommandDto() commandDto_ field.
 --
-<.> xref:#executeCommand_InteractionContextPolicy_CommandDto_CommandOutcomeHandler[executeCommand(InteractionContextPolicy, CommandDto, CommandOutcomeHandler)]
+<.> xref:#executeCommand_InteractionContextPolicy_CommandDto[executeCommand(InteractionContextPolicy, CommandDto)]
 +
 --
 Executes the specified command (represented as a _CommandDto_ using the required _InteractionContextPolicy_ .
@@ -31,10 +31,10 @@ Executes the specified command (represented as a _CommandDto_ using the required
 --
 As per _#executeCommand(InteractionContextPolicy, Command)_ , with a policy of _InteractionContextPolicy#NO_SWITCH no switch_ .
 --
-<.> xref:#executeCommand_CommandDto_CommandOutcomeHandler[executeCommand(CommandDto, CommandOutcomeHandler)]
+<.> xref:#executeCommand_CommandDto[executeCommand(CommandDto)]
 +
 --
-As per _#executeCommand(InteractionContextPolicy, CommandDto, CommandOutcomeHandler)_ , with a policy of _InteractionContextPolicy#NO_SWITCH no switch_ .
+As per _#executeCommand(InteractionContextPolicy, CommandDto)_ , with a policy of _InteractionContextPolicy#NO_SWITCH no switch_ .
 --
 
 == Members
@@ -44,15 +44,13 @@ As per _#executeCommand(InteractionContextPolicy, CommandDto, CommandOutcomeHand
 
 Executes the specified xref:refguide:applib:index/services/command/Command.adoc[Command] using the required _InteractionContextPolicy_ , updating the Command (or its persistent equivalent) afterwards (for example, setting its _Command#getCommandDto() commandDto_ field.
 
-[#executeCommand_InteractionContextPolicy_CommandDto_CommandOutcomeHandler]
-=== executeCommand(InteractionContextPolicy, CommandDto, CommandOutcomeHandler)
+[#executeCommand_InteractionContextPolicy_CommandDto]
+=== executeCommand(InteractionContextPolicy, CommandDto)
 
 Executes the specified command (represented as a _CommandDto_ using the required _InteractionContextPolicy_ .
 
 IMPORTANT: THIS METHOD HAS SIGNIFICANT SIDE-EFFECTS. Specifically, the xref:refguide:applib:index/services/command/Command.adoc[Command] of the executing thread (obtained using _org.apache.causeway.applib.services.iactn.InteractionProvider_ to obtain the xref:refguide:applib:index/services/iactn/Interaction.adoc[Interaction] , and then _Interaction#getCommand()_ to obtain the xref:refguide:applib:index/services/command/Command.adoc[Command] ) will be UPDATED to hold the _CommandDto_ passed in.
 
-Optionally an xref:refguide:applib:index/services/command/CommandOutcomeHandler.adoc[CommandOutcomeHandler] can be provided to process the result. This is used by the persistent implementations to update their respective persistent equivalents of xref:refguide:applib:index/services/command/Command.adoc[Command] .
-
 [#executeCommand_Command]
 === executeCommand(Command)
 
@@ -60,12 +58,12 @@ As per _#executeCommand(InteractionContextPolicy, Command)_ , with a policy of _
 
 Note that this method updates the Command as a side-effect.
 
-[#executeCommand_CommandDto_CommandOutcomeHandler]
-=== executeCommand(CommandDto, CommandOutcomeHandler)
+[#executeCommand_CommandDto]
+=== executeCommand(CommandDto)
 
-As per _#executeCommand(InteractionContextPolicy, CommandDto, CommandOutcomeHandler)_ , with a policy of _InteractionContextPolicy#NO_SWITCH no switch_ .
+As per _#executeCommand(InteractionContextPolicy, CommandDto)_ , with a policy of _InteractionContextPolicy#NO_SWITCH no switch_ .
 
-Note that this method has significant side-effects.
+IMPORTANT: THIS METHOD HAS SIGNIFICANT SIDE-EFFECTS. Specifically, the xref:refguide:applib:index/services/command/Command.adoc[Command] of the executing thread (obtained using _org.apache.causeway.applib.services.iactn.InteractionProvider_ to obtain the xref:refguide:applib:index/services/iactn/Interaction.adoc[Interaction] , and then _Interaction#getCommand()_ to obtain the xref:refguide:applib:index/services/command/Command.adoc[Command] ) will be UPDATED to hold the _CommandDto_ passed in.
 
 include::hooks/CommandExecutorService_010-implementation.adoc[]
 
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/iactn/Interaction.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/iactn/Interaction.adoc
index 0b1a2d90dd..1cbc65d608 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/iactn/Interaction.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/iactn/Interaction.adoc
@@ -50,7 +50,7 @@ The execution that preceded the current one.
 
 The unique identifier of this interaction (inherited from xref:refguide:applib:index/mixins/system/HasInteractionId.adoc[HasInteractionId] )
 
-This can be used to correlate audit records and transactions happening as a consequence or within the interaction.
+This can be used to correlate to the xref:refguide:applib:index/services/command/Command.adoc[Command] that triggers the interaction, and to audit records ( _org.apache.causeway.applib.services.publishing.spi.EntityPropertyChange_ s that are created as a consequence of the interaction.
 
 [#getCommand_]
 === getCommand()
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/publishing/log/CommandLogger.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/publishing/log/CommandLogger.adoc
index def264b076..30ae96e3d1 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/publishing/log/CommandLogger.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/publishing/log/CommandLogger.adoc
@@ -10,6 +10,8 @@ Simple implementation of xref:refguide:applib:index/services/publishing/spi/Comm
 ----
 class CommandLogger {
   boolean isEnabled()
+  void onReady(Command command)
+  void onStarted(Command command)
   void onCompleted(Command command)
 }
 ----
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/publishing/spi/CommandSubscriber.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/publishing/spi/CommandSubscriber.adoc
index 03e836f6a1..5a86bf77ae 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/publishing/spi/CommandSubscriber.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/publishing/spi/CommandSubscriber.adoc
@@ -9,24 +9,50 @@ Part of the _Publishing SPI_ . A component to receive xref:refguide:applib:index
 .CommandSubscriber.java
 ----
 interface CommandSubscriber {
+  void onReady(Command command)     // <.>
+  void onStarted(Command command)     // <.>
   void onCompleted(Command command)     // <.>
 }
 ----
 
+<.> xref:#onReady_Command[onReady(Command)]
++
+--
+Notifies that the command will be published, and has transitioned to _org.apache.causeway.applib.services.command.Command.CommandPublishingPhase#READY_ .
+--
+<.> xref:#onStarted_Command[onStarted(Command)]
++
+--
+Notifies that the command has started to execute, and has transitioned to _org.apache.causeway.applib.services.command.Command.CommandPublishingPhase#STARTED_ .
+--
 <.> xref:#onCompleted_Command[onCompleted(Command)]
 +
 --
-Notifies that the command has completed.
+Notifies that the command has completed and has transitioned to _org.apache.causeway.applib.services.command.Command.CommandPublishingPhase#COMPLETED_
 --
 
 == Members
 
+[#onReady_Command]
+=== onReady(Command)
+
+Notifies that the command will be published, and has transitioned to _org.apache.causeway.applib.services.command.Command.CommandPublishingPhase#READY_ .
+
+This is an opportunity for implementations to process the command, for example to persist an initial representation of it.
+
+[#onStarted_Command]
+=== onStarted(Command)
+
+Notifies that the command has started to execute, and has transitioned to _org.apache.causeway.applib.services.command.Command.CommandPublishingPhase#STARTED_ .
+
+This is an opportunity for implementations to process the command, for example to update any persisted representation of it.
+
 [#onCompleted_Command]
 === onCompleted(Command)
 
-Notifies that the command has completed.
+Notifies that the command has completed and has transitioned to _org.apache.causeway.applib.services.command.Command.CommandPublishingPhase#COMPLETED_
 
-This is an opportunity for implementations to process the command, for example to persist a representation of it.
+This is an opportunity for implementations to process the command, for example to update any persisted representations of it.
 
 include::hooks/CommandSubscriber_010-implementation.adoc[]
 
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/repository/EntityState.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/repository/EntityState.adoc
index aa22a0e9fe..a299046272 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/repository/EntityState.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/repository/EntityState.adoc
@@ -22,7 +22,7 @@ enum EntityState {
   boolean isAttachedNoOid()     // <.>
   boolean isDetachedCannotReattach()
   boolean isAttachedOrRemoved()     // <.>
-  boolean isSpecicalJpaDetachedWithOid()     // <.>
+  boolean isJpaSpecificDetachedWithOid()     // <.>
   boolean hasOid()
 }
 ----
@@ -88,7 +88,7 @@ Object with this state is an entity that has been removed from the database. Obj
 not supported by JPA
 ====
 --
-<.> xref:#isSpecicalJpaDetachedWithOid_[isSpecicalJpaDetachedWithOid()]
+<.> xref:#isJpaSpecificDetachedWithOid_[isJpaSpecificDetachedWithOid()]
 
 == Members
 
@@ -157,5 +157,5 @@ Only supported by JDO. Will always return false with JPA.
 not supported by JPA
 ====
 
-[#isSpecicalJpaDetachedWithOid_]
-=== isSpecicalJpaDetachedWithOid()
+[#isJpaSpecificDetachedWithOid_]
+=== isJpaSpecificDetachedWithOid()
diff --git a/antora/components/refguide-index/modules/applib/pages/index/value/Blob.adoc b/antora/components/refguide-index/modules/applib/pages/index/value/Blob.adoc
index f950b4f11c..d24349576d 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/value/Blob.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/value/Blob.adoc
@@ -31,6 +31,9 @@ class Blob {
   Blob zip()     // <.>
   Blob zip(String zipEntryNameIfAny)     // <.>
   Blob unZip(CommonMimeType resultingMimeType)
+  Try<HashUtils.Hash> tryHash(HashAlgorithm hashAlgorithm)
+  Try<HashUtils.Hash> tryMd5()
+  String md5Hex()
   boolean equals(Object o)
   int hashCode()
   String toString()
diff --git a/antora/components/refguide-index/modules/commons/pages/index/io/DataSource.adoc b/antora/components/refguide-index/modules/commons/pages/index/io/DataSource.adoc
index 8ba2d04e6e..fe9d0caba9 100644
--- a/antora/components/refguide-index/modules/commons/pages/index/io/DataSource.adoc
+++ b/antora/components/refguide-index/modules/commons/pages/index/io/DataSource.adoc
@@ -19,11 +19,16 @@ interface DataSource {
   Try<Can<String>> tryReadAsLines(Charset charset)     // <.>
   Try<Can<String>> tryReadAsLinesUtf8()     // <.>
   Try<BufferedImage> tryReadAsImage()
+  Try<HashUtils.Hash> tryHash(HashAlgorithm hashAlgorithm)
+  Try<HashUtils.Hash> tryMd5()
+  String md5Hex()
   Try<Void> tryReadAndWrite(DataSink dataSink, int bufferSize)     // <.>
   void pipe(DataSink dataSink, int bufferSize)     // <.>
   DataSource empty()     // <.>
   DataSource ofInputStreamSupplier(ThrowingSupplier<InputStream> inputStreamSupplier)     // <.>
+  DataSource ofInputStreamEagerly(InputStream inputStream)     // <.>
   DataSource ofResource(Class<?> cls, String resourcePath)     // <.>
+  DataSource ofSpringResource(Resource springResource)     // <.>
   DataSource ofFile(File file)     // <.>
   DataSource ofString(String string, Charset charset)     // <.>
   DataSource ofStringUtf8(String string)     // <.>
@@ -91,11 +96,21 @@ Acts as a no-op.
 --
 Creates a xref:refguide:commons:index/io/DataSource.adoc[DataSource] for given InputStream Supplier.
 --
+<.> xref:#ofInputStreamEagerly_InputStream[ofInputStreamEagerly(InputStream)]
++
+--
+Creates a xref:refguide:commons:index/io/DataSource.adoc[DataSource] for given _InputStream_ eagerly. That is, it reads the InputStream into a byte array, which can be later read from repeatedly.
+--
 <.> xref:#ofResource_Class_String[ofResource(Class, String)]
 +
 --
 Creates a xref:refguide:commons:index/io/DataSource.adoc[DataSource] for given resource path relative to _Class_ .
 --
+<.> xref:#ofSpringResource_Resource[ofSpringResource(Resource)]
++
+--
+Creates a xref:refguide:commons:index/io/DataSource.adoc[DataSource] for given Spring _Resource_ .
+--
 <.> xref:#ofFile_File[ofFile(File)]
 +
 --
@@ -191,11 +206,27 @@ Acts as a no-op.
 
 Creates a xref:refguide:commons:index/io/DataSource.adoc[DataSource] for given InputStream Supplier.
 
+[#ofInputStreamEagerly_InputStream]
+=== ofInputStreamEagerly(InputStream)
+
+Creates a xref:refguide:commons:index/io/DataSource.adoc[DataSource] for given _InputStream_ eagerly. That is, it reads the InputStream into a byte array, which can be later read from repeatedly.
+
+If reading from given _InputStream_ throws any exception, it is propagated without catching.
+
 [#ofResource_Class_String]
 === ofResource(Class, String)
 
 Creates a xref:refguide:commons:index/io/DataSource.adoc[DataSource] for given resource path relative to _Class_ .
 
+If any of the args is null (or empty), returns an 'empty' xref:refguide:commons:index/io/DataSource.adoc[DataSource] .
+
+[#ofSpringResource_Resource]
+=== ofSpringResource(Resource)
+
+Creates a xref:refguide:commons:index/io/DataSource.adoc[DataSource] for given Spring _Resource_ .
+
+If the single argument is null, returns an 'empty' xref:refguide:commons:index/io/DataSource.adoc[DataSource] .
+
 [#ofFile_File]
 === ofFile(File)
 
diff --git a/antora/components/refguide-index/modules/commons/pages/index/io/HashUtils.adoc b/antora/components/refguide-index/modules/commons/pages/index/io/HashUtils.adoc
new file mode 100644
index 0000000000..9f8e042354
--- /dev/null
+++ b/antora/components/refguide-index/modules/commons/pages/index/io/HashUtils.adoc
@@ -0,0 +1,40 @@
+= HashUtils
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
+
+Utilities related to byte data hashing algorithms, at least providing MD5.
+
+ConsiderApache Commons Codecfor a more comprehensive suite of digest utilities.
+
+== API
+
+[source,java]
+.HashUtils.java
+----
+class HashUtils {
+  Try<Hash> tryDigest(HashAlgorithm algorithm, byte[] bytes, int buffersize)     // <.>
+  Try<Hash> tryDigest(HashAlgorithm algorithm, DataSource dataSource, int buffersize)     // <.>
+}
+----
+
+<.> xref:#tryDigest_HashAlgorithm_byte_int[tryDigest(HashAlgorithm, byte, int)]
++
+--
+Optimized for when the input byte array is already present in memory.
+--
+<.> xref:#tryDigest_HashAlgorithm_DataSource_int[tryDigest(HashAlgorithm, DataSource, int)]
++
+--
+Optimized for direct _InputStream_ processing, if possible, not reading all data into memory at once.
+--
+
+== Members
+
+[#tryDigest_HashAlgorithm_byte_int]
+=== tryDigest(HashAlgorithm, byte, int)
+
+Optimized for when the input byte array is already present in memory.
+
+[#tryDigest_HashAlgorithm_DataSource_int]
+=== tryDigest(HashAlgorithm, DataSource, int)
+
+Optimized for direct _InputStream_ processing, if possible, not reading all data into memory at once.
diff --git a/antora/components/refguide-index/modules/core/pages/index/metamodel/services/publishing/CommandPublisher.adoc b/antora/components/refguide-index/modules/core/pages/index/metamodel/services/publishing/CommandPublisher.adoc
index 672a71a368..a8f58bbd6b 100644
--- a/antora/components/refguide-index/modules/core/pages/index/metamodel/services/publishing/CommandPublisher.adoc
+++ b/antora/components/refguide-index/modules/core/pages/index/metamodel/services/publishing/CommandPublisher.adoc
@@ -9,19 +9,41 @@ Notifies xref:refguide:applib:index/services/publishing/spi/CommandSubscriber.ad
 .CommandPublisher.java
 ----
 interface CommandPublisher {
+  void ready(Command command)     // <.>
+  void start(Command command)     // <.>
   void complete(Command command)     // <.>
 }
 ----
 
+<.> xref:#ready_Command[ready(Command)]
++
+--
+Notifies all xref:refguide:applib:index/services/publishing/spi/CommandSubscriber.adoc[CommandSubscriber] s (through _CommandSubscriber#onReady(Command)_ ) that the xref:refguide:applib:index/services/command/Command.adoc[Command] has been created/is ready for execution
+--
+<.> xref:#start_Command[start(Command)]
++
+--
+Notifies all xref:refguide:applib:index/services/publishing/spi/CommandSubscriber.adoc[CommandSubscriber] s (through _CommandSubscriber#onStarted(Command)_ ) that the xref:refguide:applib:index/services/command/Command.adoc[Command] has started.
+--
 <.> xref:#complete_Command[complete(Command)]
 +
 --
-"Completes" the command, meaning that all xref:refguide:applib:index/services/publishing/spi/CommandSubscriber.adoc[CommandSubscriber] s are notified throuhg _CommandSubscriber#onCompleted(Command)_ .
+Notifies all xref:refguide:applib:index/services/publishing/spi/CommandSubscriber.adoc[CommandSubscriber] s (through _CommandSubscriber#onCompleted(Command)_ ) that the xref:refguide:applib:index/services/command/Command.adoc[Command] has completed.
 --
 
 == Members
 
+[#ready_Command]
+=== ready(Command)
+
+Notifies all xref:refguide:applib:index/services/publishing/spi/CommandSubscriber.adoc[CommandSubscriber] s (through _CommandSubscriber#onReady(Command)_ ) that the xref:refguide:applib:index/services/command/Command.adoc[Command] has been created/is ready for execution
+
+[#start_Command]
+=== start(Command)
+
+Notifies all xref:refguide:applib:index/services/publishing/spi/CommandSubscriber.adoc[CommandSubscriber] s (through _CommandSubscriber#onStarted(Command)_ ) that the xref:refguide:applib:index/services/command/Command.adoc[Command] has started.
+
 [#complete_Command]
 === complete(Command)
 
-"Completes" the command, meaning that all xref:refguide:applib:index/services/publishing/spi/CommandSubscriber.adoc[CommandSubscriber] s are notified throuhg _CommandSubscriber#onCompleted(Command)_ .
+Notifies all xref:refguide:applib:index/services/publishing/spi/CommandSubscriber.adoc[CommandSubscriber] s (through _CommandSubscriber#onCompleted(Command)_ ) that the xref:refguide:applib:index/services/command/Command.adoc[Command] has completed.
diff --git a/antora/components/refguide-index/modules/extensions/pages/index/commandlog/applib/dom/CommandLogEntry.adoc b/antora/components/refguide-index/modules/extensions/pages/index/commandlog/applib/dom/CommandLogEntry.adoc
index 57039c7dea..773ee8426e 100644
--- a/antora/components/refguide-index/modules/extensions/pages/index/commandlog/applib/dom/CommandLogEntry.adoc
+++ b/antora/components/refguide-index/modules/extensions/pages/index/commandlog/applib/dom/CommandLogEntry.adoc
@@ -15,7 +15,7 @@ class CommandLogEntry {
   public static final String SCHEMA;
   public static final String TABLE;
   CommandLogEntry(CommandDto commandDto, org.apache.causeway.extensions.commandlog.applib.dom.ReplayState replayState, int targetIndex)     // <.>
-  void init(Command command)
+  void sync(Command command)
   void copyOver(CommandDto commandDto, String key, Consumer<String> consume)
   String title()
   ChangeType getType()
@@ -29,7 +29,6 @@ class CommandLogEntry {
   void saveAnalysis(String analysis)
   int compareTo(CommandLogEntry other)
   String toString()
-  CommandOutcomeHandler outcomeHandler()
 }
 ----
 
diff --git a/antora/components/refguide-index/modules/extensions/pages/index/commandlog/applib/subscriber/CommandSubscriberForCommandLog.adoc b/antora/components/refguide-index/modules/extensions/pages/index/commandlog/applib/subscriber/CommandSubscriberForCommandLog.adoc
index 47b5b8d103..35b6bcb74f 100644
--- a/antora/components/refguide-index/modules/extensions/pages/index/commandlog/applib/subscriber/CommandSubscriberForCommandLog.adoc
+++ b/antora/components/refguide-index/modules/extensions/pages/index/commandlog/applib/subscriber/CommandSubscriberForCommandLog.adoc
@@ -10,6 +10,8 @@ Implementation of xref:refguide:applib:index/services/publishing/spi/CommandSubs
 ----
 class CommandSubscriberForCommandLog {
   boolean isEnabled()
+  void onReady(Command command)
+  void onStarted(Command command)
   void onCompleted(Command command)
 }
 ----
diff --git a/core/adoc/modules/_overview/pages/about.adoc b/core/adoc/modules/_overview/pages/about.adoc
index c68afe5350..cae11054d6 100644
--- a/core/adoc/modules/_overview/pages/about.adoc
+++ b/core/adoc/modules/_overview/pages/about.adoc
@@ -1355,6 +1355,7 @@ org.jsoup:jsoup:jar:<managed> +
 org.junit.jupiter:junit-jupiter-api:jar:<managed> +
 org.junit.jupiter:junit-jupiter-engine:jar:<managed> +
 org.junit.jupiter:junit-jupiter-params:jar:<managed> +
+org.projectlombok:lombok:jar:${lombok.version} +
 org.slf4j:slf4j-api:jar:<managed> +
 org.springframework:spring-context:jar:<managed> +
 org.springframework:spring-tx:jar:<managed> +
@@ -1365,7 +1366,7 @@ org.yaml:snakeyaml:jar:<managed> +
 
 .Document Index Entries
 ****
-xref:refguide:commons:index/collections/Can.adoc[Can], xref:refguide:commons:index/collections/Cardinality.adoc[Cardinality], xref:refguide:commons:index/functional/Either.adoc[Either], xref:refguide:commons:index/functional/Railway.adoc[Railway], xref:refguide:commons:index/functional/ThrowingConsumer.adoc[ThrowingConsumer], xref:refguide:commons:index/functional/ThrowingRunnable.adoc[ThrowingRunnable], xref:refguide:commons:index/functional/ThrowingSupplier.adoc[ThrowingSupplier], xref [...]
+xref:refguide:commons:index/collections/Can.adoc[Can], xref:refguide:commons:index/collections/Cardinality.adoc[Cardinality], xref:refguide:commons:index/functional/Either.adoc[Either], xref:refguide:commons:index/functional/Railway.adoc[Railway], xref:refguide:commons:index/functional/ThrowingConsumer.adoc[ThrowingConsumer], xref:refguide:commons:index/functional/ThrowingRunnable.adoc[ThrowingRunnable], xref:refguide:commons:index/functional/ThrowingSupplier.adoc[ThrowingSupplier], xref [...]
 ****
 |===
 
@@ -1819,7 +1820,7 @@ o.a.i.core.runtimeservices.repository.RepositoryServiceDefault +
 o.a.i.core.runtimeservices.routing.RoutingServiceDefault +
 o.a.i.core.runtimeservices.scratchpad.ScratchpadDefault +
 o.a.i.core.runtimeservices.serializing.SerializingAdapterDefault +
-o.a.i.core.runtimeservices.session.InteractionIdGenerator +
+o.a.i.core.runtimeservices.session.InteractionIdGeneratorDefault +
 o.a.i.core.runtimeservices.session.InteractionServiceDefault +
 o.a.i.core.runtimeservices.sitemap.SitemapServiceDefault +
 o.a.i.core.runtimeservices.spring.SpringBeansService +
@@ -4650,6 +4651,7 @@ org.apache.causeway.extensions:causeway-extensions-audittrail-applib:test-jar:<m
 org.apache.causeway.persistence:causeway-persistence-jdo-datanucleus:jar:<managed> +
 org.apache.causeway.testing:causeway-testing-fixtures-applib:jar:<managed> +
 org.apache.causeway.testing:causeway-testing-integtestsupport-applib:jar:<managed> +
+org.datanucleus:javax.jdo:jar:${datanucleus-jdo-api.version} +
 ****
 
 |Apache Causeway Ext - Audit Trail Persistence (using JPA)
@@ -5156,6 +5158,7 @@ o.a.i.extensions.pdfjs.metamodel.facet.PdfJsViewerFacetFromAnnotationFactory$Reg
 ****
 org.apache.causeway.core:causeway-core-metamodel:jar:<managed> +
 org.apache.causeway.extensions:causeway-extensions-pdfjs-applib:jar:<managed> +
+org.apache.causeway.testing:causeway-testing-integtestsupport-applib:jar:<managed> +
 ****
 
 |Apache Causeway Ext - pdf.js Wicket
@@ -6158,7 +6161,7 @@ eg. code mining, automated documentation.
 .Dependencies
 ****
 org.apache.causeway.core:causeway-core-internaltestsupport:jar:${project.version} +
-org.checkerframework:checker-qual:jar:3.31.0 +
+org.checkerframework:checker-qual:jar:3.32.0 +
 org.mapstruct:mapstruct-processor:jar:1.5.3.Final +
 org.projectlombok:lombok:jar:<managed> +
 org.slf4j:slf4j-api:jar:<managed> +
diff --git a/core/config/src/main/adoc/modules/config/pages/sections/causeway.extensions.adoc b/core/config/src/main/adoc/modules/config/pages/sections/causeway.extensions.adoc
index 6d07b923b7..36c994c284 100644
--- a/core/config/src/main/adoc/modules/config/pages/sections/causeway.extensions.adoc
+++ b/core/config/src/main/adoc/modules/config/pages/sections/causeway.extensions.adoc
@@ -12,16 +12,25 @@ include::../section-hooks/causeway.extensions~pre.adoc[]
 |Default
 |Description
 |
-[[causeway.extensions.command-log.publish-policy]]
-causeway.extensions.command-log. +
-publish-policy
+[[causeway.extensions.audit-trail.persist]]
+causeway.extensions.audit-trail. +
+persist
 
 | 
-| Whether commands should be published always, or only if a change in the system's state has been detected.
+| Whether the ``EntityPropertyChangeSubscriber`` implementation provided by this extension (which persists property changes to the audit trail) is enabled or not.
+
+One reason to use this option is if you wish to provide your own implementation that wraps or delegates to the default implementation of ``EntityPropertyChangeSubscriber`` that is provided by the _audittrail_ extension. Because entity property changes are published to _all_ subscribers on the class path, you can disable the default implementation from doing anything using this setting.
+
+
+|
+[[causeway.extensions.command-log.persist]]
+causeway.extensions.command-log. +
+persist
 
-In general, the default of ``PublishPolicy#ALWAYS`` should be used, _unless_ the _Audit Trail_ extension is also in use, which is able to advise on whether the systems state has changed.
+| 
+| Whether the ``CommandSubscriber`` implementation provided by this extension (which persists commands to the command log) is enabled or not.
 
-Put another way, if this policy is set to ``PublishPolicy#ONLY_IF_SYSTEM_CHANGED`` but the _Audit Trail_ extension is _not_ enabled, then nothing will be logged.
+One reason to use this option is if you wish to provide your own implementation that wraps or delegates to the default implementation of ``CommandSubscriber`` that is provided by the _commandlog_ extension. Because commands are published to _all_ subscribers on the class path, you can disable the default implementation from doing anything using this setting.
 
 
 |
@@ -209,6 +218,28 @@ Default is none.
 For more information, check the usage of the ``headers`` init parameter for https://github.com/eBay/cors-filter[EBay CORSFilter].
 
 
+|
+[[causeway.extensions.execution-log.persist]]
+causeway.extensions.execution-log. +
+persist
+
+| 
+| Whether the ``ExecutionSubscriber`` implementation provided by this extension (which persists executions to the execution log) is enabled or not.
+
+One reason to use this option is if you wish to provide your own implementation that wraps or delegates to the default implementation of ``ExecutionSubscriber`` that is provided by the _executionLog_ extension. Because executions are published to _all_ subscribers on the class path, you can disable the default implementation from doing anything using this setting.
+
+
+|
+[[causeway.extensions.execution-outbox.persist]]
+causeway.extensions. +
+execution-outbox.persist
+
+| 
+| Whether the ``ExecutionSubscriber`` implementation provided by this extension (which persists executions to the outbox) is enabled or not.
+
+One reason to use this option is if you wish to provide your own implementation that wraps or delegates to the outbox implementation of ``ExecutionSubscriber`` that is provided by the _executionOutbox_ extension. Because executions are published to _all_ subscribers on the class path, you can disable the outbox implementation from doing anything using this setting.
+
+
 |
 [[causeway.extensions.execution-outbox.rest-api.max-pending]]
 causeway.extensions. +