Skip to content

Concurrency 3.1#2577

Open
rzo1 wants to merge 19 commits intomainfrom
concurency
Open

Concurrency 3.1#2577
rzo1 wants to merge 19 commits intomainfrom
concurency

Conversation

@rzo1
Copy link
Copy Markdown
Contributor

@rzo1 rzo1 commented Apr 3, 2026

First version - think we can improve or re-work if needed.

rzo1 added 17 commits April 1, 2026 21:01
… 3.1

Add support for scheduled recurring async methods as defined in Jakarta
Concurrency 3.1. This addresses the largest block of TCK failures (28 tests)
by enabling cron-based scheduling of CDI @asynchronous methods via the new
runAt attribute.

- ScheduleHelper: maps @schedule annotations to API-provided CronTrigger,
  supports composite triggers (multiple schedules) and skipIfLateBy wrapping
- AsynchronousInterceptor: branches on runAt presence — one-shot path
  unchanged, new scheduled path uses ManagedScheduledExecutorService
- ManagedScheduledExecutorServiceImplFactory: adds lookup() with graceful
  fallback matching the ManagedExecutorServiceImplFactory pattern
Implement opt-in virtual thread support (Java 21+) across
ManagedThreadFactory, ManagedExecutorService, and
ManagedScheduledExecutorService as required by Jakarta Concurrency 3.1.

Runtime:
- VirtualThreadHelper: reflection-based Java 21 API access, graceful
  fallback on Java 17 (isSupported check, no multi-release JARs)
- ManagedThreadFactoryImpl: virtual path creates threads that do NOT
  implement ManageableThread (spec 3.4.4)
- All three factory classes accept virtual property

Deployment descriptor + annotation processing:
- Boolean virtual field added to DD model classes in openejb-jee
- Convert*Definitions pass virtual to Resource properties
- AnnotationDeployer reads virtual() from @Managed*Definition annotations

Tests skip gracefully on Java <21 via Assume.assumeTrue.
- ScheduleHelper: remove pass-through toMonths/toDaysOfWeek methods
  and unused DayOfWeek/Month imports
- ManagedScheduledExecutorServiceImplFactory: wire virtual flag into
  fallback thread factory creation, remove unused import
- VirtualThreadHelper: remove unused ofVirtualInterface variable
…duler

Verify that API-provided CronTrigger (a ZonedTrigger) works transparently
with ManagedScheduledExecutorServiceImpl via default bridge methods. Tests
confirm recurring scheduling and LastExecution with ZonedDateTime work
without any implementation changes.
The TCK beans call Asynchronous.Result.getFuture() inside scheduled
methods. The interceptor must call setFuture() before ctx.proceed()
for both void and non-void return types, otherwise getFuture() throws
IllegalStateException. Use Callable path for all scheduled methods
to ensure proper future lifecycle.
…d JNDI

Three fixes for @asynchronous(runAt=@schedule(...)) TCK compliance:

1. Stop trigger loop when method returns non-null value (per spec:
   "the method returns a non-null result value" ends the schedule).
   Uses AtomicReference to cancel ScheduledFuture from inside Callable.

2. Throw IllegalArgumentException for invalid executor JNDI names
   instead of silently falling back to default. Only default names
   get the graceful fallback.

3. Add beans.xml archive processor for Concurrency TCK deployments
   (OWB needs bean-discovery-mode="all" to auto-enable @priority
   interceptors).

4. Add TCK-style unit test covering CompletedResult, IncompleteFuture,
   CompletedExceptionally, VoidReturn, and InvalidJNDIName scenarios.
bean-discovery-mode=all caused deployment failures for some TCK WARs
by scanning too many classes. Switch to annotated mode which is the
CDI 4.0 default and sufficient for discovering annotated beans.
Extend TCK-style test coverage with multipleSchedules (composite
trigger with two @schedule annotations) and ignoresMaxAsync (concurrent
scheduled method invocations). Both pass — remaining TCK failures for
these tests are JNDI scoping issues with java:module/ executor names.
…tors

Strip java: prefix in ManagedScheduledExecutorServiceImplFactory.lookup()
fallback path to match how resources are registered via cleanUpName().
Without this, java:module/concurrent/ScheduledExecutorB lookups fail
because the resource is bound as module/concurrent/ScheduledExecutorB.

Add Arquillian test verifying both java:module/ and java:app/ scoped
@ManagedScheduledExecutorDefinition work with scheduled async methods.
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.
…tion

Two fixes for the last Web-profile TCK failures:

1. Context propagation: when executor is a plain MES (not MSES),
   extract the MES's ContextServiceImpl and compose a temporary MSES
   that uses the MES's context service with the default MSES's thread
   pool. This preserves third-party context propagation (e.g. StringContext).

2. Thread pool starvation: replace mses.schedule(Callable, Trigger)
   with a manual trigger loop that schedules directly on the delegate
   ScheduledExecutorService. This avoids TriggerTask's double context
   wrapping and thread consumption between trigger fires.
Per spec, scheduled async methods are not subject to maxAsync
constraints. Use the default MSES's thread pool for the trigger loop
instead of the referenced executor's pool. This prevents thread
starvation when maxAsync threads are busy with blocking tasks.
Replace !eefull with web tag to properly exclude Full/EJB profile
tests. The TCK 3.1.1 uses JUnit 5 @tag annotations: @web has tags
web+platform, @platform has only platform. Filtering on web includes
Core, Standalone, and Web tests while excluding Platform-only (Full).
- Add qualifier field (List<String>) to ContextService, ManagedExecutor,
  ManagedScheduledExecutor, ManagedThreadFactory DD model classes
- Update SXC JAXB accessors to parse <qualifier> and <virtual> XML
  elements (virtual was in the model but missing from SXC parsers)
- Fix NPE in Convert*Definitions when <context-service-ref> is absent
  in deployment descriptor — defaults to java:comp/DefaultContextService
- Add unit tests for null context service fallback and qualifier model
- Add Arquillian test deploying WAR with web.xml containing <virtual>
ForkJoinWorkerThread extends Thread (platform) and cannot be virtual.
Fall back to a platform ManagedForkJoinWorkerThread instead of throwing
UnsupportedOperationException. The TCK expects ForkJoinPool to function
with virtual factories — the worker threads are platform but the pool
still operates correctly.
m>
Register concurrency resources (ManagedExecutorService, ManagedScheduledExecutorService,
ManagedThreadFactory, ContextService) as CDI beans with qualifier support per
Concurrency 3.1 spec Section 5.4.1.

- ConcurrencyCDIExtension: CDI extension that observes AfterBeanDiscovery and creates
  synthetic ApplicationScoped beans for resources with qualifiers. Also registers
  default beans (@Default/@Any) for all four concurrency resource types.
- AnnotationDeployer: Extract qualifiers() from @ManagedExecutorDefinition,
  @ManagedScheduledExecutorDefinition, @ManagedThreadFactoryDefinition,
  @ContextServiceDefinition annotations into JEE model objects.
- Convert*Definitions: Pass Qualifiers as comma-separated Resource property.
- OptimizedLoaderService: Register ConcurrencyCDIExtension alongside JMS2CDIExtension.

TCK Web profile: 196/196 passing (0 failures, 0 errors).
@rzo1 rzo1 requested a review from jungm April 3, 2026 18:45
@rzo1 rzo1 marked this pull request as draft April 3, 2026 18:45
@rzo1 rzo1 changed the title Draft: Concurency 3.1 Draft: Concurrency 3.1 Apr 3, 2026
rzo1 added 2 commits April 3, 2026 21:38
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.
…e headers

Replace ctx.proceed() with direct Method.invoke() in scheduled async
re-executions. InvocationContext's interceptor iterator is single-use,
so re-calling proceed() would bypass TX/security interceptors after
the first scheduled execution. Context propagation is handled by
ContextService.enter/exit.

Also add Apache License headers to TCK resource files to fix RAT check.
@rzo1 rzo1 marked this pull request as ready for review April 4, 2026 18:12
@rzo1 rzo1 changed the title Draft: Concurrency 3.1 Concurrency 3.1 Apr 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant