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

rzo1 pushed a commit to branch concurency
in repository https://gitbox.apache.org/repos/asf/tomee.git


The following commit(s) were added to refs/heads/concurency by this push:
     new b4dc7bfe3c Support plain ManagedExecutorService as executor for 
scheduled async
b4dc7bfe3c is described below

commit b4dc7bfe3c1a517e56398ad22839b29e1443dd75
Author: Richard Zowalla <[email protected]>
AuthorDate: Thu Apr 2 16:22:27 2026 +0200

    Support plain ManagedExecutorService as executor for scheduled async
    
    Per spec, @Asynchronous(executor=..., runAt=@Schedule(...)) may reference
    a plain ManagedExecutorService, not just a ManagedScheduledExecutorService.
    When MSES lookup fails, verify the executor exists as MES and fall back to
    the default MSES for scheduling capability.
---
 .../cdi/concurrency/AsynchronousInterceptor.java   | 16 ++++++++++--
 .../AsynchronousScheduledTCKStyleTest.java         | 29 ++++++++++++++++++++++
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/cdi/concurrency/AsynchronousInterceptor.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/cdi/concurrency/AsynchronousInterceptor.java
index 7a2387f4e6..01569d9b5d 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/cdi/concurrency/AsynchronousInterceptor.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/cdi/concurrency/AsynchronousInterceptor.java
@@ -111,11 +111,23 @@ public class AsynchronousInterceptor {
 
     private Object aroundInvokeScheduled(final InvocationContext ctx, final 
Asynchronous asynchronous,
                                           final Schedule[] schedules) throws 
Exception {
-        final ManagedScheduledExecutorService mses;
+        // Per spec, the executor attribute may reference either a 
ManagedScheduledExecutorService
+        // or a plain ManagedExecutorService. When a plain MES is referenced, 
fall back to the
+        // default MSES for scheduling capability (the trigger mechanism 
requires MSES).
+        ManagedScheduledExecutorService mses;
         try {
             mses = 
ManagedScheduledExecutorServiceImplFactory.lookup(asynchronous.executor());
         } catch (final IllegalArgumentException e) {
-            throw new RejectedExecutionException("Cannot lookup 
ManagedScheduledExecutorService", e);
+            // The executor might be a plain ManagedExecutorService — verify 
it exists,
+            // then use the default MSES for scheduling
+            try {
+                
ManagedExecutorServiceImplFactory.lookup(asynchronous.executor());
+                // MES exists — use default MSES for scheduling
+                mses = ManagedScheduledExecutorServiceImplFactory.lookup(
+                        "java:comp/DefaultManagedScheduledExecutorService");
+            } catch (final Exception fallbackEx) {
+                throw new RejectedExecutionException("Cannot lookup executor 
for scheduled async method", e);
+            }
         }
 
         final ZonedTrigger trigger = ScheduleHelper.toTrigger(schedules);
diff --git 
a/container/openejb-core/src/test/java/org/apache/openejb/cdi/concurrency/AsynchronousScheduledTCKStyleTest.java
 
b/container/openejb-core/src/test/java/org/apache/openejb/cdi/concurrency/AsynchronousScheduledTCKStyleTest.java
index b6a5f7555e..49825855f3 100644
--- 
a/container/openejb-core/src/test/java/org/apache/openejb/cdi/concurrency/AsynchronousScheduledTCKStyleTest.java
+++ 
b/container/openejb-core/src/test/java/org/apache/openejb/cdi/concurrency/AsynchronousScheduledTCKStyleTest.java
@@ -195,6 +195,23 @@ public class AsynchronousScheduledTCKStyleTest {
         assertEquals(Integer.valueOf(3), result2);
     }
 
+    /**
+     * TCK: testScheduledAsynchIgnoresMaxAsync (MED-Web variant)
+     * Method with @Asynchronous(executor=MES, runAt=@Schedule) — the executor 
is a plain
+     * ManagedExecutorService, not a ManagedScheduledExecutorService. The 
interceptor
+     * should fall back to the default MSES for scheduling.
+     */
+    @Test
+    public void scheduledWithManagedExecutorServiceExecutor() throws Exception 
{
+        final AtomicInteger counter = new AtomicInteger();
+        // This method references the default MES (not MSES) as executor
+        final CompletableFuture<Integer> future = 
reqBean.scheduledWithMESExecutor(2, counter);
+
+        assertNotNull("Future should be returned even when executor is MES", 
future);
+        final Integer result = future.get(15, TimeUnit.SECONDS);
+        assertEquals("Should complete after 2 runs", Integer.valueOf(2), 
result);
+    }
+
     // --- Bean ---
 
     public enum ReturnType {
@@ -257,6 +274,18 @@ public class AsynchronousScheduledTCKStyleTest {
             return future;
         }
 
+        @Asynchronous(executor = "java:comp/DefaultManagedExecutorService",
+                       runAt = @Schedule(cron = "* * * * * *"))
+        public CompletableFuture<Integer> scheduledWithMESExecutor(final int 
runs, final AtomicInteger counter) {
+            final int count = counter.incrementAndGet();
+            if (count < runs) {
+                return null;
+            }
+            final CompletableFuture<Integer> future = 
Asynchronous.Result.getFuture();
+            future.complete(count);
+            return future;
+        }
+
         @Asynchronous(executor = "java:comp/env/invalid/executor",
                        runAt = @Schedule(cron = "* * * * * *"))
         public CompletableFuture<String> scheduledInvalidExecutor() {

Reply via email to