Skip to content

build(java): Java 25 for Micronaut libs, Java 17 elsewhere; drop virtual-thread default; fix api leak#94

Merged
pditommaso merged 5 commits into
masterfrom
build/java-25-release-targeting
Jul 24, 2026
Merged

build(java): Java 25 for Micronaut libs, Java 17 elsewhere; drop virtual-thread default; fix api leak#94
pditommaso merged 5 commits into
masterfrom
build/java-25-release-targeting

Conversation

@pditommaso

@pditommaso pditommaso commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Split bytecode targeting so libseqera artifacts stay loadable where they are actually consumed, plus two related fixes:

1. Split Java targeting: 25 for Micronaut libs, 17 for the rest

Plain libraries (consumed by the Nextflow Java 17 runtime) compile with --release 17 for javac (which also caps the API surface to the Java 17 stdlib) and source/target 17 for Groovy, set once in java-library-conventions. Micronaut-based libraries target Java 25 via micronaut-library-conventions: they run only on the Java 25 service runtime (Platform, Wave — the whole stack is being aligned on Java 25). The build toolchain is JDK 25, auto-provisioned via the foojay-resolver-convention plugin.

2. Drop the virtual-thread executor default

AbstractWorkQueue / AbstractMessageStream previously defaulted their handler pool to Executors.newVirtualThreadPerTaskExecutor() — a JDK 21 API emitted into Java-17 bytecode, i.e. a guaranteed NoSuchMethodError on a Java 17 runtime. The default is removed; a handler executor must now be supplied via withHandlerExecutor() before processing (startProcessing() fails fast otherwise). Micronaut consumers already inject the @Named(BLOCKING) executor; test fixtures inject a shared daemon pool.

⚠️ Breaking API change: withHandlerExecutor is now mandatory and non-null; there is no built-in default executor. In-tree the only consumer (CommandServiceImpl) already injects.

3. Fix an API leak

lib-cmd-queue-redis depended on lib-data-workqueue as implementation, but CommandQueue publicly extends AbstractWorkQueue and exposes WorkQueue/MessageConsumer. Changed to api so subclassing consumers get those types on the compile classpath (previously only resolvable via the published POM's runtime scope, which broke Gradle composite builds).

Verification

Plain modules emit bytecode 61 (Java 17); Micronaut modules emit bytecode 69 (Java 25). Full test suites pass, including the Redis testcontainers integration tests for the stream/queue/command modules.

🤖 Generated with Claude Code

pditommaso and others added 4 commits July 21, 2026 16:45
Remove the shared virtual-thread executor default (Executors.newVirtualThread-
PerTaskExecutor, a JDK 21 API) from AbstractWorkQueue and AbstractMessageStream.
Handlers now run on an executor supplied via withHandlerExecutor(), which is
mandatory - startProcessing() fails fast if none was set. This drops the only
Java 21 dependency in these modules, so they compile and run on Java 17.

Micronaut consumers already inject the @nAmed(BLOCKING) executor before adding a
consumer; test fixtures inject a shared daemon pool (TestWorkerPool).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
…as api

Convention plugins now target Java 17: javac --release 17 (which also caps the
API surface to the Java 17 stdlib) and source/target 17 for Groovy. The target is
set once in java-library-conventions - applied by every module - to avoid
duplicate, order-dependent configureEach across the sibling conventions.

Also change lib-cmd-queue-redis's dependency on lib-data-workqueue from
implementation to api: CommandQueue publicly extends AbstractWorkQueue and exposes
WorkQueue / MessageConsumer, so consumers subclassing it need those types on the
compile classpath. It previously resolved only via the published POM's runtime
scope and broke Gradle composite builds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
Restore the two-convention split (superseding the uniform --release 17 from the
earlier commit). libseqera's toolchain moves to Java 25 and the compile target is
chosen per module type:

- io.seqera.java-library-conventions: plain libraries -> javac --release 17 (+
  Groovy source/target 17). These include everything the Nextflow Java 17 runtime
  consumes (lib-httpx, lib-retry, lib-trace, wave-api, wave-utils, lib-cloudinfo,
  lib-platform-oidc).
- io.seqera.micronaut-library-conventions (new): libraries that depend on
  Micronaut -> target Java 25. Micronaut runs on the Java 25 service runtime (and
  Micronaut 5 requires Java 25), so these are never loaded on the Nextflow Java 17
  runtime. Applied to the 21 Micronaut modules.

Bumps Groovy 4.0.24 -> 4.0.31: the older Groovy cannot run on a JDK 25 toolchain
("Unsupported class file major version 69").

Verified: Micronaut libs compile to bytecode 69 (Java 25), plain libs to 61 (Java
17); full compile and the affected module test suites (incl. Redis testcontainers)
pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
Comment thread buildSrc/src/main/groovy/io.seqera.java-library-conventions.gradle
- settings.gradle: add foojay-resolver-convention so the JDK 25 toolchain
  is auto-provisioned on machines without a local JDK 25
- AbstractWorkQueue/AbstractMessageStream javadoc: usage example now shows
  the mandatory withHandlerExecutor() call before addConsumer()
- workqueue/stream READMEs: drop the stale 'virtual-thread executor by
  default' wording — the handler executor is injected, no default

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pditommaso pditommaso changed the title build(java): target Java 17 via --release; drop virtual-thread default; fix api leak build(java): Java 25 for Micronaut libs, Java 17 elsewhere; drop virtual-thread default; fix api leak Jul 24, 2026
@pditommaso
pditommaso requested a review from jordeu July 24, 2026 15:56
@pditommaso
pditommaso merged commit d38afb0 into master Jul 24, 2026
3 checks passed
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.

2 participants