fix(#733): report when a factory descriptor is provided by several bundles - #741
Open
oscerd wants to merge 1 commit into
Open
fix(#733): report when a factory descriptor is provided by several bundles#741oscerd wants to merge 1 commit into
oscerd wants to merge 1 commit into
Conversation
…ral bundles getResource walks bundleContext.getBundles() in install order and takes the first bundle with a matching descriptor, loading the class from that bundle's classloader. findClass caches the result per key, so whichever bundle happened to be scanned first stays selected for the life of the finder. With two versions of a bundle installed side by side, which is a normal state during a rolling upgrade, install order silently decides which one supplies the factory, and an operator who installed a patched bundle has no way to tell it is being ignored. Keep the selection exactly as it is and report the ambiguity: finish the scan, and if more than one bundle provided the descriptor log at WARN which bundle was picked, that it was picked only for being installed first, and which others also provide it. Deliberately not changing the resolution semantics. Scoping selection to the requesting context's bundle wiring is the fix the issue floats, but it alters a core resolution path that has behaved this way for a long time, and factory finder keys are internal Camel SPI names that never come from message content, so there is no urgency to justify that risk. The diagnostics make the situation visible first. BundleEntry becomes package private. It was private while getResource, which returns it, is public, so the modifier was not restricting anything; this makes it reachable from the tests in the package.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #733
What
getResourcewalksbundleContext.getBundles()in install order and takes thefirst bundle with a matching descriptor, loading the class from that bundle's
classloader with no scoping to the requesting context's wiring.
findClasscaches the result per key (
addToClassMap), so whichever bundle happened to bescanned first stays selected for the life of the finder.
With two versions of a bundle installed side by side — a normal state during a
rolling upgrade — install order silently decides which one supplies the factory.
An operator who has installed a patched bundle has no way to tell it is being
ignored.
How
The selection is unchanged. First bundle in install order still wins. What
is new is that the scan no longer breaks early, so when more than one bundle
provides the descriptor it logs at WARN which bundle was picked, that it was
picked only for being installed first, and which others also provide it:
The list is only allocated when there actually is a clash, and
findClasscaches per key, so this costs an already-O(bundles) scan not breaking early on
first resolution of each key.
Why not the wiring-scoped fix
#733 floats scoping selection to the requesting context's
BundleWiring. I havedeliberately not done that here:
for a long time, with a wide blast radius and no cheap way to prove no
regression short of the full Pax Exam suite
message content — so there is no urgency that would justify that risk
Making the situation visible is the cheap half, and it is what tells us whether
the ambiguity happens in practice at all. Happy to follow up with the
wiring-scoped selection as a separate change if you want it.
Tests
OsgiFactoryFinderTestcovers no-provider (returns null), single provider, andseveral providers — the last asserting that install order still decides, so
the selection behaviour the rest of the resolution path depends on is pinned
against future edits to this method.
Note
BundleEntrygoes fromprivate static classto package-private.getResourceis
publicand returns it, soprivatewas never actually restrictinganything; this just makes the type nameable from tests in the same package.
Claude Code on behalf of Andrea Cosentino