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 2026/04/24 15:20:04 UTC

(causeway) branch CAUSEWAY-3989 updated: JDOJPA-300 : runs each replayable command in its own transaction

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

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


The following commit(s) were added to refs/heads/CAUSEWAY-3989 by this push:
     new 8a7673a9b77 JDOJPA-300 : runs each replayable command in its own transaction
8a7673a9b77 is described below

commit 8a7673a9b77ff4f96f384921ffd66b5d4a09766a
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Thu Apr 23 17:02:06 2026 +0100

    JDOJPA-300 : runs each replayable command in its own transaction
---
 .../applib/CausewayModuleExtCommandLogApplib.java       |  5 ++++-
 .../commandlog/applib/dom/replay/ReplayContext.java     |  2 ++
 .../commandlog/applib/dom/replay/ReplayableCommand.java | 17 +++++++++++++----
 3 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/CausewayModuleExtCommandLogApplib.java b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/CausewayModuleExtCommandLogApplib.java
index 4f83a6a5f1f..b7a58b903fe 100644
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/CausewayModuleExtCommandLogApplib.java
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/CausewayModuleExtCommandLogApplib.java
@@ -22,6 +22,7 @@
 import org.apache.causeway.applib.services.command.CommandExecutorService;
 import org.apache.causeway.applib.services.iactnlayer.InteractionService;
 import org.apache.causeway.applib.services.repository.RepositoryService;
+import org.apache.causeway.applib.services.xactn.TransactionService;
 import org.apache.causeway.core.config.util.SpringProfileUtil;
 import org.apache.causeway.extensions.commandlog.applib.app.CommandLogMenu;
 import org.apache.causeway.extensions.commandlog.applib.contributions.HasInteractionId_commandLogEntry;
@@ -145,10 +146,12 @@ public static void honorSystemEnvironment() {
     @Bean ReplayContext replayContext(
             final RepositoryService repositoryService,
             final InteractionService interactionService,
+            final TransactionService transactionService,
             final CommandLogEntryRepository commandLogEntryRepository,
             final CommandExecutorService commandExecutorService,
             final ClockService clockService) {
-        return new ReplayContext(repositoryService, interactionService,
+        return new ReplayContext(
+                repositoryService, interactionService, transactionService,
                 commandLogEntryRepository, commandExecutorService, clockService);
     }
 
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayContext.java b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayContext.java
index 580e2f05ae6..1e739bb56a7 100644
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayContext.java
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayContext.java
@@ -22,6 +22,7 @@
 import org.apache.causeway.applib.services.command.CommandExecutorService;
 import org.apache.causeway.applib.services.iactnlayer.InteractionService;
 import org.apache.causeway.applib.services.repository.RepositoryService;
+import org.apache.causeway.applib.services.xactn.TransactionService;
 import org.apache.causeway.extensions.commandlog.applib.dom.CommandLogEntryRepository;
 
 import lombok.Value;
@@ -34,6 +35,7 @@
 public final class ReplayContext {
         RepositoryService repositoryService;
         InteractionService interactionService;
+        TransactionService transactionService;
         CommandLogEntryRepository commandLogEntryRepository;
         CommandExecutorService commandExecutorService;
         ClockService clockService;
diff --git a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand.java b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand.java
index e2ea51718b0..76696e9112b 100644
--- a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand.java
+++ b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/replay/ReplayableCommand.java
@@ -24,6 +24,7 @@
 import java.util.Comparator;
 import java.util.Optional;
 import java.util.UUID;
+import java.util.concurrent.Callable;
 import java.util.concurrent.Executors;
 
 import javax.inject.Inject;
@@ -46,6 +47,7 @@
 import org.apache.causeway.applib.annotation.SemanticsOf;
 import org.apache.causeway.applib.annotation.Where;
 import org.apache.causeway.applib.jaxb.JavaTimeXMLGregorianCalendarMarshalling;
+import org.apache.causeway.applib.services.bookmark.Bookmark;
 import org.apache.causeway.applib.services.command.CommandExecutorService.InteractionContextPolicy;
 import org.apache.causeway.commons.functional.Try;
 import org.apache.causeway.commons.internal.base._Refs.ObjectReference;
@@ -63,6 +65,8 @@
 import org.apache.causeway.valuetypes.asciidoc.builder.AsciiDocBuilder;
 import org.apache.causeway.valuetypes.asciidoc.builder.AsciiDocFactory;
 
+import org.springframework.transaction.annotation.Propagation;
+
 import lombok.AllArgsConstructor;
 import lombok.Value;
 import lombok.experimental.Accessors;
@@ -343,9 +347,14 @@ Try<ReplayableCommand> tryReplayOrRetry() {
         return commandLogEntry()
             .filter(ReplayableCommand::canReplayOrRetryOrMarkForExclusion)
             .map(commandLogEntry->{
-                var tryResultBookmark = replayContext.commandExecutorService().executeCommand(
-                        InteractionContextPolicy.SWITCH_USER_AND_TIME,
-                        commandLogEntry.getCommandDto());
+                final var commandDto = commandLogEntry.getCommandDto();
+                final var tryResultBookmark = replayContext.transactionService().callTransactional(Propagation.REQUIRES_NEW,
+                        () -> {
+                            final var bookmarkTry = replayContext.commandExecutorService().executeCommand(
+                                    InteractionContextPolicy.SWITCH_USER_AND_TIME,
+                                    commandDto);
+                            return bookmarkTry.valueAsNullableElseFail();
+                        });
 
                 // handle the replay outcome
                 tryResultBookmark.accept(
@@ -355,7 +364,7 @@ Try<ReplayableCommand> tryReplayOrRetry() {
                 invalidateCachedRecord();
 
                 return tryResultBookmark
-                        .mapSuccessAsNullable(__->this);
+                        .mapSuccessAsNullable(__ -> this);
             })
             .orElseGet(()->Try.success(null));
     }