Skip to content

FELIX-6875 - Build and test the modules CI never covered on JDK 21 and 25 - #589

Merged
paulrutter merged 11 commits into
masterfrom
FELIX-6875-build-unbuilt-modules
Nov 2, 2026
Merged

paulrutter merged 11 commits into
masterfrom
FELIX-6875-build-unbuilt-modules

Conversation

@paulrutter

@paulrutter paulrutter commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Impact

Build and test configuration only; no production code changes. Already released artifacts are unaffected.

Java level of the next release (effective release of the compiler, before → after):

Module Before After
coordinator, metatype, healthcheck/annotation, healthcheck/api 7 8
scr-ext-anno 5 8
bundlerepository.osgi-ct 5 8
fileinstall, inventory, features, configadmin-plugins/interpolation, healthcheck/{core,generalchecks,webconsoleplugin}, webconsole-plugins/{ds,event,memoryusage,obr,packageadmin} unchanged (8 or 11) unchanged
  • Java 7 (--release 7) is rejected by JDK 21+, so these modules could not be built there at all. The next release of the affected bundles will carry a higher osgi.ee requirement (JavaSE-1.8); for healthcheck/api and healthcheck/annotation that is visible to consumers.
  • All 18 modules move to felix-parent 9.
  • bundlerepository.osgi-ct now builds against the released bundlerepository 2.0.10 instead of ${project.version}.
  • Test-only: Mockito 1.x → 5.18.0 (healthcheck/api, healthcheck/core, healthcheck/generalchecks, healthcheck/webconsoleplugin, configadmin-plugins/interpolation), healthcheck/core ITs run on framework 8.0.0, bnd-maven-plugin 4.1.0 → 7.1.0 and the baseline maven-bundle-plugin 4.1.0 → 5.1.8 in healthcheck/api (both throw a ConcurrentModificationException on JDK 17+).
  • CI: the 18 modules are added to maven-ci.yml, each behind its own path filter, built on the existing 17/21/25/27 matrix. This adds build time to PRs touching them, and nothing for PRs that do not.

Why

CI never built these modules, so they stayed on old parents and test tooling that fail on JDK 17+ (ianal plugin, Java 7 target, cglib-based Mockito, bnd 4.1.0). An audit on JDK 21 and 25 showed nearly every failure was tooling, not a removed JDK construct.

Left out on purpose: eventadmin, systemready, rootcause (not recently maintained).

Test fix

fileinstall DirectoryWatcherTest.testInvalidTempDir relied on changing java.io.tmpdir at runtime, which JDK 12+ ignores because it caches the value at startup. It now uses fileinstall's own temp-dir setting.

Verification

Run locally (WSL, clean mvn verify) on the final code, JDK 21 and JDK 25: healthcheck/api (11 tests), healthcheck/core (33), healthcheck/generalchecks (66), healthcheck/webconsoleplugin (2), fileinstall (32) all pass. healthcheck/core and fileinstall ran on the previous commit, which differs only in the healthcheck/api pom. The other modules passed on JDK 21 in earlier runs on intermediate trees. The CI run is the first full run of the new module steps on 17/21/25/27.

Jira: https://issues.apache.org/jira/browse/FELIX-6875

🤖 Generated with Claude Code

paulrutter and others added 8 commits November 2, 2026 20:20
These 18 modules were on felix-parent 2.1 to 7 and failed on JDK 21 and 25 for
reasons that have nothing to do with their source:

  - felix-parent 5 and 6 compile with --release 6/7, which JDK 20 and 21 removed
    (metatype, coordinator, healthcheck/api, healthcheck/annotation)
  - felix-parent 3 runs a JavaScript Ant task, and Nashorn was removed in JDK 15
    (scr-ext-anno)
  - felix-parent 7 runs ianal-maven-plugin 1.0-alpha-1, which cannot open
    java.io.File on JDK 17 and later (inventory, features,
    webconsole-plugins, healthcheck/webconsoleplugin)

Move them to felix-parent 9, as the other modules were, and use <relativePath />
because the in-repo parent is a different version.

Also remove a Java level no current JDK accepts: bundlerepository.osgi-ct
compiled to 1.5 and pinned maven-bundle-plugin 2.3.4. osgi-ct also depended on bundlerepository at
${project.version}, its own 2.0.3-SNAPSHOT, which no longer exists anywhere; use
the latest release, 2.0.10.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
mockito-all 1.x and mockito-core 1.9.5 define classes through cglib, which needs
ClassLoader.defineClass and is refused on JDK 17 and later (InaccessibleObject
Exception). Mockito 5.17.0 and earlier 5.x do not work on JVM 25 either, the same
reason gogo-parent already uses 5.18.0.

Move to mockito-core 5.18.0, and rename the org.mockito.Matchers imports, removed
in Mockito 4, to ArgumentMatchers.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…k 8.0.0 release

healthcheck/core pinned framework 7.0.5 for its pax-exam tests, and its
HealthCheckServletIT errored on JDK 21. Use 8.0.0, the latest release, as
the other modules do.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…urrent JDKs in healthcheck/api

healthcheck/api failed on JDK 17 and later in two places: bnd-maven-plugin 4.1.0
and the baseline goal of maven-bundle-plugin 4.1.0 both throw a
ConcurrentModificationException. Use bnd-maven-plugin 7.1.0 and
maven-bundle-plugin 5.1.8, the version cm.json already runs its baseline with.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The test stubs performRequest with any(HttpRequestsCheckTrustedCerts.class), and
check() is called with a null trustedCerts. In Mockito 1.x any(Class) matched
null; since Mockito 2 it only matches instances. After the upgrade the stub no
longer applied, so the real HTTP request ran and testSimpleRequestSpec and
testSimpleRequestSpecWithContentCheck got WARN instead of OK.

nullable(Class) matches both, which is what the test meant.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…s own setting

DirectoryWatcherTest.testInvalidTempDir set the java.io.tmpdir system property
at runtime and expected DirectoryWatcher to fail creating its temp directory.
Since JDK 12 that property is read once when the JVM starts, so changing it in
the test has no effect: the temp directory was created in the real location and
the test failed with "Expected an IllegalStateException", on its own as well as
with the rest of the class.

Point File Install at the invalid directory through felix.fileinstall.tmpdir
instead, which is how a user configures it. That goes through prepareDir, which
throws a RuntimeException ("Cannot create folder"), so the test now expects that
and checks the message. It also makes the directory writable again afterwards so
that it can be cleaned.

Failing to create the folder is logged, and the logger asks the BundleContext for a
LogService, which the mock did not expect, so the test stubs that call too.

Like before, this relies on the directory not being writable, which does not
hold when the tests run as root.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
healthcheck/api declared mockito-core 1.9.5, which defines classes through cglib
and is refused on JDK 17 and later. It was not in the previous Mockito change
because the module did not get far enough to run its tests: its bnd plugin
failed first. HealthCheckMetadataTest then failed inside org.mockito.cglib.

Use 5.18.0 as in the other modules, and replace MockitoAnnotations.initMocks,
deprecated since Mockito 3.4, with openMocks.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Add the modules moved off their old parents and fixed in this change to the
CI workflow, each behind its own paths-filter group, so a change to one of
them is built and tested on the full JDK matrix. They are not in a reactor and
pin released Felix bundles, so they are built one by one with clean verify.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@paulrutter
paulrutter force-pushed the FELIX-6875-build-unbuilt-modules branch from 154fce6 to ec0455a Compare November 2, 2026 19:49
paulrutter and others added 3 commits November 2, 2026 20:56
checkScheduledPeriodsOverlap slept a fixed 3000ms and expected the job's second
execution, due at the third full second after the first fire, to have started.
Depending on the sub-second time the test starts, that fire lands within a few
milliseconds of the assertion, as it did on JDK 25 in CI (1 execution instead
of 2).

Wait for the second execution, then wait 1000ms for the fire that has to be
skipped while it is still running, and assert exactly two.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The monitor publishes Healthy, Unhealthy and SystemReady from a run that repeats
every second, so after a health check is registered they appear up to a second
later. The test registered the monitor, slept, registered the health check and
asserted right away, which failed on a slower runner (testSystemReady: expected
one Healthy service, found none).

Wait up to ten seconds for the service before asserting on it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…osgi-ct

Removing the 2.3.4 pin left the plugin without a version, which Maven warns
about and resolves to whatever is newest on the day. Pin 6.2.0, the release CI
resolved when the module passed on JDK 17, 21 and 25.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@paulrutter
paulrutter merged commit 0c2a940 into master Nov 2, 2026
4 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.

1 participant