Skip to content

Deps: Bump to Eclipse Sisu 1.1.0 - #12551

Closed
cstamas wants to merge 1 commit into
apache:masterfrom
cstamas:sisu-110
Closed

Deps: Bump to Eclipse Sisu 1.1.0#12551
cstamas wants to merge 1 commit into
apache:masterfrom
cstamas:sisu-110

Conversation

@cstamas

@cstamas cstamas commented Jul 27, 2026

Copy link
Copy Markdown
Member

@cstamas cstamas self-assigned this Jul 27, 2026
@cstamas cstamas added the dependencies Pull requests that update a dependency file label Jul 27, 2026
@gnodet

gnodet commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

CI Failure Analysis

All 18 downstream checks (full-build + integration-tests) fail with:

[INFO] Resolving Mimir daemon version 0.12.0
[WARNING] Failed to resolve daemon: Unknown NameMapper name: 'file-gaecv', known ones: []
[ERROR] Error enabling Mimir: java.io.IOException: Mimir daemon JAR not found

initial-build passes because it runs Maven 4.0.0-rc-5 (wrapper, Sisu 1.0.1). The downstream jobs use the newly-built Maven (now with Sisu 1.1.0), where the new JSR330 bean filtering (sisu-project#266) hides all NameMapper implementations from the Mimir extension realm (known ones: []).

Confirmed this is Sisu-specific — PR #12538 (no Sisu change) passes on the same CI infra.

Looks like the version bump needs companion changes — e.g. configuring setJSR330ComponentVisibilityFollowsPlexusVisibility in PlexusContainerCapsuleFactory, and/or a Mimir update for the new visibility model.

@gnodet

gnodet commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Update: TCCL + Realm Visibility Root Cause

Dug deeper — the issue is the interaction between DefaultMaven.callListeners() and Sisu 1.1.0's new realm-based JSR330 filtering.

The chain:

  1. DefaultMaven.callListeners() (line 376) sets Thread.currentThread().setContextClassLoader(listener.getClass().getClassLoader()) — i.e., TCCL = Mimir's extension realm (coreExtension>eu.maveniverse.maven.mimir:extension3:0.12.0)

  2. Mimir's afterSessionStart triggers lazy component resolution (needs NameMapper map via artifact resolution)

  3. In Sisu 1.1.0, DefaultBeanLocator.locate() now wraps results in FilteredBeans (new in 1.1.0 — previously only DefaultPlexusBeanLocator did realm filtering):

    // DefaultPlexusContainer constructor (1.1.0):
    ((DefaultBeanLocator) qualifiedBeanLocator)
        .setBeanEntryPredicateSupplier(realmManager::visibilityPredicate);
  4. FilteredBeans calls RealmManager.contextRealm() which walks the TCCL looking for a ClassRealm:

    for (ClassLoader tccl = Thread.currentThread().getContextClassLoader(); 
         tccl != null; tccl = tccl.getParent()) {
        if (tccl instanceof ClassRealm) return (ClassRealm) tccl;
    }
  5. Returns Mimir's realmvisibleRealmNames() computes what's visible from that realm → NameMapper beans (bound in plexus.core) are filtered outknown ones: []

Why Maven 3 / Sisu 1.0.1 works: In 1.0.1, DefaultBeanLocator.locate() returned LocatedBeans directly with no realm filter. Realm filtering only applied to DefaultPlexusBeanLocator.locate() (Plexus container.lookup()). Since the Maven DI bridge and JSR330 injection bypassed Plexus lookups, they saw all beans regardless of realm.

Extension realm setup: Mimir uses the default self-first strategy (realm.setParentRealm(parentRealm)), but the Sisu 1.1.0 visibility predicate apparently doesn't traverse parent realms to include their beans.

Possible fix directions:

  • Configure cc.setJSR330ComponentVisibilityFollowsPlexusVisibility(false) in PlexusContainerCapsuleFactory (line ~107) — but this would undo the Extensions are picked up from non-extension marked plugins #12522 fix
  • Ensure callListeners() sets TCCL to the container realm instead of the listener's classloader before calling lifecycle participants
  • Update the extension realm setup to ensure core realm beans are visible under the new filtering

@gnodet

gnodet commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Correction on the fix directions — options 2 and 3 from my previous comment collapse into one: ensure core beans are visible when a lifecycle participant triggers lazy resolution. Whether that's done by adjusting the TCCL or the realm imports is the same fix from different ends — the extension realm already has setParentRealm(containerRealm) via the self-first default, so the real question is whether Sisu 1.1.0's visibleRealmNames() traverses the parent realm chain or only explicit importFrom() entries.

@gnodet

gnodet commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Reproduced Locally

Setup: Built Maven from master with Sisu 1.1.0, extracted the distribution, tested with/without Mimir extension.

Without Mimir → ✅ BUILD SUCCESS. NameMapper discovery works fine.

With Mimir, daemon JAR cached → ✅ BUILD SUCCESS, but the warning appears:

[WARNING] Failed to resolve daemon: Unknown NameMapper name: 'file-gaecv', known ones: []

(Build passes only because Mimir skips resolution when the daemon JAR already exists on disk.)

With Mimir, daemon JAR removed (= CI's fresh runner state) → ❌ Exact CI error reproduced:

[ERROR] Error enabling Mimir: java.io.IOException: Mimir daemon JAR not found

Same test with Sisu 1.0.1 → ✅ Resolves daemon JAR, starts daemon, BUILD SUCCESS.

Why Maven 3.10.x passes

Sisu 1.1.0 was merged to maven-3.10.x (#12547) and CI is green — but the 3.10.x CI doesn't use Mimir. So the extension realm filtering path is never exercised.

Debug output reveals the mechanism

With -X, the debug log shows NameMapper discovery works during initial container setup but fails during Mimir's lifecycle:

Phase 1 (initial container, TCCL = container realm):

available name mappers [discriminating, file-gaecv, file-gav, file-hgaecv, file-hgav, file-static, gaecv, gav, static]

Phase 2 (Mimir lifecycle, TCCL = extension realm via callListeners() line 376):

Unknown NameMapper name: 'file-gaecv', known ones: []
at NamedLockFactoryAdapterFactoryImpl.selectNameMapper(line 158)
at NamedLockFactoryAdapterFactoryImpl.createAdapter(line 129)
at NamedLockFactoryAdapterFactoryImpl.lambda$getAdapter$0(line 122)
at DefaultSessionData.lambda$computeIfAbsent$0(line 71)

The Map<String, NameMapper> in NamedLockFactoryAdapterFactoryImpl is a lazy supplier (via SisuDiBridgeModule.getMapSupplier()). It's first evaluated inside DefaultSessionData.computeIfAbsent during Mimir's afterSessionStart. At that point, TCCL = Mimir's ClassRealm, and Sisu 1.1.0's FilteredBeans hides all core NameMapper beans.

@gnodet

gnodet commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Correction: Maven 3.10.x + Sisu 1.1.0 + Mimir WORKS

I was wrong — the code IS different between Maven 3 and Maven 4. Retested properly with Mimir enabled on both:

Scenario Result
Maven 3.10.x + Sisu 1.1.0 + Mimir (fresh state) passes — daemon resolved, started, build succeeds
Maven 4.1.0-SNAPSHOT + Sisu 1.1.0 + Mimir (fresh state) Unknown NameMapper name: 'file-gaecv', known ones: []

Same machine, same Mimir 0.12.0, same clean state (daemon JAR + socket removed).

The difference: eager vs lazy Map resolution

Maven 3: Guice/Sisu resolves Map<String, NameMapper> eagerly at injection time (container startup). At that point TCCL = container realm → Sisu 1.1.0's FilteredBeans sees all beans → NameMapper map populated with all 9 implementations.

Maven 4: SisuDiBridgeModule.getMapSupplier() wraps the map resolution in a lazy lambda:

return () -> {
    // ...
    for (var bean : locator.get().locate(toGuiceKey(valueType))) {  // <-- deferred!
        // ...
    }
};

This lambda is first invoked during DefaultSessionData.computeIfAbsent() inside Mimir's afterSessionStart callback, where callListeners() has set TCCL = extension realm → Sisu 1.1.0 FilteredBeans sees zero beans → known ones: [].

Root cause

The Maven 4 DI bridge defers Sisu bean iteration to first access. When that first access happens inside an extension's lifecycle callback (with TCCL scoped to the extension's ClassRealm), Sisu 1.1.0's new realm filtering hides all core beans.

@gnodet

gnodet commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Closing in favor of #12554 (master) and #12556 (4.0.x), which fix the root cause properly.

The original approach of just bumping Sisu to 1.1.0 exposed a realm visibility issue: extension realms (parent=plexus.core) couldn't see beans sourced from the maven.ext container realm through Sisu 1.1.0's new jsr330ComponentVisibilityFollowsPlexusVisibility filtering. The fix adds a reverse realm import (realm.importFrom(extRealm, extRealm.getId())) so that maven.ext is reachable in Sisu's visibility BFS traversal from extension realms — working with the filtering feature, not against it.

@gnodet gnodet closed this Jul 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Extensions are picked up from non-extension marked plugins

2 participants