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

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


The following commit(s) were added to refs/heads/main by this push:
     new 7b6a1bf22e5 CAUSEWAY-3883: don't allow 
BackgroundService_IntegTestAbstract to run concurrent (testing)
7b6a1bf22e5 is described below

commit 7b6a1bf22e515b8f5638a5f866c68351607780cf
Author: Andi Huber <[email protected]>
AuthorDate: Thu Jun 26 16:19:28 2025 +0200

    CAUSEWAY-3883: don't allow BackgroundService_IntegTestAbstract to run
    concurrent (testing)
---
 .../commandlog/applib/dom/BackgroundService.java   | 30 +++++++++---------
 .../BackgroundService_IntegTestAbstract.java       | 36 +++++++++++++---------
 2 files changed, 36 insertions(+), 30 deletions(-)

diff --git 
a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/BackgroundService.java
 
b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/BackgroundService.java
index ecc931eb0c2..04571a47f23 100644
--- 
a/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/BackgroundService.java
+++ 
b/extensions/core/commandlog/applib/src/main/java/org/apache/causeway/extensions/commandlog/applib/dom/BackgroundService.java
@@ -20,6 +20,7 @@
 
 import java.sql.Timestamp;
 import java.util.UUID;
+import java.util.concurrent.ForkJoinPool;
 
 import jakarta.inject.Inject;
 
@@ -61,10 +62,7 @@ public class BackgroundService {
      * @see #executeMixin(Class, Object) - to invoke actions that are 
implemented as mixins
      */
     public <T> AsyncProxy<T> execute(final T object) {
-        return wrapperFactory.asyncWrap(object, AsyncControl.defaults()
-                .withNoExecute()
-                .withCheckRules()
-                .listen(new CommandPersistor(commandLogEntryRepository)));
+        return wrapperFactory.asyncWrap(object, 
asyncControl().withCheckRules());
     }
     /**
      * Wraps the domain object in a proxy whereby any actions invoked through 
the proxy will instead be persisted as a
@@ -73,10 +71,7 @@ public <T> AsyncProxy<T> execute(final T object) {
      * @see #executeMixin(Class, Object) - to invoke actions that are 
implemented as mixins
      */
     public <T> AsyncProxy<T> executeSkipRules(final T object) {
-        return wrapperFactory.asyncWrap(object, AsyncControl.defaults()
-                .withNoExecute()
-                .withSkipRules()
-                .listen(new CommandPersistor(commandLogEntryRepository)));
+        return wrapperFactory.asyncWrap(object, 
asyncControl().withSkipRules());
     }
 
     /**
@@ -86,10 +81,7 @@ public <T> AsyncProxy<T> executeSkipRules(final T object) {
      * @see #execute(Object) - to invoke actions that are implemented directly 
within the object
      */
     public <T> AsyncProxy<T> executeMixin(final Class<T> mixinClass, final 
Object mixedIn) {
-        return wrapperFactory.asyncWrapMixin(mixinClass, mixedIn, 
AsyncControl.defaults()
-                .withNoExecute()
-                .withCheckRules()
-                .listen(new CommandPersistor(commandLogEntryRepository)));
+        return wrapperFactory.asyncWrapMixin(mixinClass, mixedIn, 
asyncControl().withCheckRules());
     }
 
     /**
@@ -99,10 +91,16 @@ public <T> AsyncProxy<T> executeMixin(final Class<T> 
mixinClass, final Object mi
      * @see #execute(Object) - to invoke actions that are implemented directly 
within the object
      */
     public <T> AsyncProxy<T> executeMixinSkipRules(final Class<T> mixinClass, 
final Object mixedIn) {
-        return wrapperFactory.asyncWrapMixin(mixinClass, mixedIn, 
AsyncControl.defaults()
-                .withNoExecute()
-                .withSkipRules()
-                .listen(new CommandPersistor(commandLogEntryRepository)));
+        return wrapperFactory.asyncWrapMixin(mixinClass, mixedIn, 
asyncControl().withSkipRules());
+    }
+
+    // -- HELPER
+
+    AsyncControl asyncControl() {
+        return AsyncControl.defaults()
+            .with(ForkJoinPool.commonPool())
+            .withNoExecute()
+            .listen(new CommandPersistor(commandLogEntryRepository));
     }
 
     record CommandPersistor(CommandLogEntryRepository 
commandLogEntryRepository) implements SyncControl.CommandListener {
diff --git 
a/extensions/core/commandlog/applib/src/test/java/org/apache/causeway/extensions/commandlog/applib/integtest/BackgroundService_IntegTestAbstract.java
 
b/extensions/core/commandlog/applib/src/test/java/org/apache/causeway/extensions/commandlog/applib/integtest/BackgroundService_IntegTestAbstract.java
index 5a3e3dce8e4..0190cb6c198 100644
--- 
a/extensions/core/commandlog/applib/src/test/java/org/apache/causeway/extensions/commandlog/applib/integtest/BackgroundService_IntegTestAbstract.java
+++ 
b/extensions/core/commandlog/applib/src/test/java/org/apache/causeway/extensions/commandlog/applib/integtest/BackgroundService_IntegTestAbstract.java
@@ -20,16 +20,16 @@
 
 import java.util.List;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
 
 import jakarta.inject.Inject;
 
 import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.Mockito;
 import org.quartz.JobExecutionContext;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -56,15 +56,26 @@
 
 import lombok.SneakyThrows;
 
-@ExtendWith(MockitoExtension.class)
 public abstract class BackgroundService_IntegTestAbstract extends 
CausewayIntegrationTestAbstract {
 
-    @Mock JobExecutionContext mockQuartzJobExecutionContext;
+    @Inject InteractionService interactionService;
+    @Inject BackgroundService backgroundService;
+    @Inject WrapperFactory wrapperFactory;
+    @Inject CommandLogEntryRepository commandLogEntryRepository;
+    @Inject TransactionService transactionService;
+    @Inject RunBackgroundCommandsJob runBackgroundCommandsJob;
+    @Inject BookmarkService bookmarkService;
+    @Inject CounterRepository<? extends Counter> counterRepository;
+
+    JobExecutionContext mockQuartzJobExecutionContext = 
Mockito.mock(JobExecutionContext.class);
 
     Bookmark bookmark;
 
     protected abstract <T extends Counter> T newCounter(String name);
 
+    /// don't allow these tests to run concurrent
+    private final static ReentrantLock LOCK = new ReentrantLock();
+
     private static boolean prototypingOrig;
 
     @BeforeAll
@@ -80,6 +91,7 @@ static void reset_environment() {
 
     @BeforeEach
     void setup_counter() {
+        LOCK.lock();
 
         transactionService.runTransactional(Propagation.REQUIRES_NEW, () -> {
             counterRepository.removeAll();
@@ -98,6 +110,11 @@ void setup_counter() {
         assertThat(counter.getNum()).isNull();
     }
 
+    @AfterEach
+    void releaseLock() {
+        LOCK.unlock();
+    }
+
     @Test
     void async_using_default_executor_service() {
 
@@ -220,13 +237,4 @@ private void removeAllCommandLogEntriesAndCounters() {
         }).ifFailureFail();
     }
 
-    @Inject InteractionService interactionService;
-    @Inject BackgroundService backgroundService;
-    @Inject WrapperFactory wrapperFactory;
-    @Inject CommandLogEntryRepository commandLogEntryRepository;
-    @Inject TransactionService transactionService;
-    @Inject RunBackgroundCommandsJob runBackgroundCommandsJob;
-    @Inject BookmarkService bookmarkService;
-    @Inject CounterRepository<? extends Counter> counterRepository;
-
 }

Reply via email to