Skip to content

Commit dceef6e

Browse files
committed
Silently fall back to platform threads when virtual=true on Java 17
Per Concurrency 3.1 spec: "When running on Java SE 17, the true value behaves the same as the false value and results in platform threads being created rather than virtual threads." Previously, virtual=true unconditionally called VirtualThreadHelper methods which throw UnsupportedOperationException on Java 17. Now checks VirtualThreadHelper.isSupported() first and falls through to platform thread creation when virtual threads are unavailable.
1 parent b6a2535 commit dceef6e

3 files changed

Lines changed: 9 additions & 4 deletions

File tree

container/openejb-core/src/main/java/org/apache/openejb/cdi/concurrency/AsynchronousInterceptor.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,9 @@ private Object aroundInvokeScheduled(final InvocationContext ctx, final Asynchro
130130
final ContextServiceImpl.Snapshot snapshot = ctxService.snapshot(null);
131131

132132
// Per spec, scheduled async methods are NOT subject to maxAsync constraints.
133-
// Use the default MSES's delegate for the trigger loop — it is not constrained
134-
// by the referenced executor's maxAsync setting.
133+
// Use the default MSES's delegate for both the trigger timer and method execution —
134+
// it is not constrained by the referenced executor's maxAsync setting.
135+
// Context propagation (security, TX, etc.) is handled via ContextService.snapshot/enter/exit.
135136
final ManagedScheduledExecutorServiceImpl defaultMses =
136137
ManagedScheduledExecutorServiceImplFactory.lookup("java:comp/DefaultManagedScheduledExecutorService");
137138
final ScheduledExecutorService triggerDelegate = defaultMses.getDelegate();

container/openejb-core/src/main/java/org/apache/openejb/resource/thread/ManagedExecutorServiceImplFactory.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ public ManagedExecutorServiceImpl create(final ContextServiceImpl contextService
8181
}
8282

8383
private ExecutorService createExecutorService() {
84-
if (virtual) {
84+
// Per spec: "When running on Java SE 17, the true value behaves the same as the
85+
// false value and results in platform threads being created rather than virtual threads."
86+
if (virtual && VirtualThreadHelper.isSupported()) {
8587
final ThreadFactory vtFactory = VirtualThreadHelper.newVirtualThreadFactory(ManagedThreadFactoryImpl.DEFAULT_PREFIX);
8688
return VirtualThreadHelper.newVirtualThreadPerTaskExecutor(vtFactory);
8789
}

container/openejb-core/src/main/java/org/apache/openejb/threads/impl/ManagedThreadFactoryImpl.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ public ManagedThreadFactoryImpl(final String prefix, final Integer priority, fin
5555
public Thread newThread(final Runnable r) {
5656
final CURunnable wrapper = new CURunnable(r, contextService);
5757

58-
if (virtual) {
58+
// Per spec: "When running on Java SE 17, the true value behaves the same as the
59+
// false value and results in platform threads being created rather than virtual threads."
60+
if (virtual && VirtualThreadHelper.isSupported()) {
5961
// Virtual threads do NOT implement ManageableThread (spec 3.4.4)
6062
// Priority and daemon settings are ignored for virtual threads
6163
final Thread thread = VirtualThreadHelper.newVirtualThread(prefix, ID.incrementAndGet(), wrapper);

0 commit comments

Comments
 (0)