Skip to content

Feat: Ability to filter JSR330 beans based on some predicate - #266

Merged
cstamas merged 8 commits into
mainfrom
jsr330-filtering
Jul 27, 2026
Merged

cstamas merged 8 commits into
mainfrom
jsr330-filtering

Conversation

@cstamas

@cstamas cstamas commented Jul 24, 2026 •

Copy link
Copy Markdown
Member

Add feature that allows JSR330 filtering.

Inject:

  • DefaultBeanLocator has new field, that may hold (initially is null) a bean entry predicate supplier.
  • Introduced new class FilteredBeans (based on RealmFilteredBeans in Plexus).

Plexus:

  • RealmManager got new method, that may create predicate for filtering (or just returns null when no filtering needed).
  • RealmFilteredBeans modified to reuse this predicate (prevent logic duplication).
  • DefaultPlexusContainer (and config) modified, and by default, if "realm" visibility (which is default), the JSR330 components will have same filtering applied (by default). Use config new method to control this.

This is very maven specific, hence the config. Also, filtering in Inject module is ONLY applied by default if it is created as part of DefaultPlexusContainer, as it happens in Maven.

Fixes #107

Sisu Inject is extended with a generic ability to filter by predicate.

Plexus Shim makes use of this, and applies filtering, making both,
JSR330 and Plexus beans behave the same.

This is very maven specific, so we might want to add a config in
container configuration, but the current code state is what
Maven needs.
@cstamas cstamas self-assigned this Jul 24, 2026
@cstamas
cstamas requested review from kwin and mcculls July 24, 2026 15:09
@cstamas cstamas added the enhancement New feature or request label Jul 24, 2026
@cstamas

cstamas commented Jul 24, 2026

Copy link
Copy Markdown
Member Author

Maven 3.10.x ITs apache/maven#12539

@cstamas
cstamas marked this pull request as ready for review July 24, 2026 19:34
@cstamas
cstamas requested a review from adreghiciu July 25, 2026 13:09
@sonarqubecloud

Copy link
Copy Markdown

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #266 Review: Feat — Ability to filter JSR330 beans based on some predicate

What works well

  • Clean generalization of FilteredBeans. Extracting realm-specific filtering from the Plexus module into a generic Supplier<Predicate>-based FilteredBeans in sisu.inject is the right abstraction. It keeps the inject module free of ClassRealm dependencies while enabling the same visibility rules to apply to pure JSR330 beans.
  • visibilityPredicate() on RealmManager eliminates logic duplication — the String.valueOf(source).startsWith("ClassRealm") check is now in exactly one place.
  • The Supplier<Predicate> design is correct for this use case — the predicate must capture the context realm at iteration time (via TCCL), so a supplier that produces a fresh predicate per iterator() call is necessary.
  • Thorough test coverage on FilteredBeans — null supplier, supplier-returns-null, always-true, always-false, and selective filtering.

Suggestion: Integration test for DefaultBeanLocator filtering path

The tests cover FilteredBeans in isolation, but there's no test that exercises the DefaultBeanLocator.locate() → FilteredBeans wiring. A test calling setBeanEntryPredicateSupplier() and then locate() would guard against regressions if the wiring in DefaultBeanLocator.locate() were accidentally removed.

Confirmed non-issues

  • (DefaultBeanLocator) qualifiedBeanLocator downcast is safe — field is final MutableBeanLocator qualifiedBeanLocator = new DefaultBeanLocator() (line 119), initialized inline.
  • AtomicReference thread safety is correct — set once during construction; get() in locate() provides happens-before.
  • ContainerConfiguration interface methods without default — consistent with the established pattern (setStrictClassPathScanning added identically in edfceea6).
  • Raw types in DefaultBeanLocator — consistent with the class-level @SuppressWarnings({"rawtypes", "unchecked"}).

Note: This review does not replace specialized AI review tools (CodeRabbit, Sourcery) or static analyzers (SonarCloud).

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

Iterable<BeanEntry<Named, T>> beans = (Iterable<BeanEntry<Named, T>>) beanLocator.<Named, T>locate(key);
if (PlexusConstants.REALM_VISIBILITY.equalsIgnoreCase(visibility)) {
beans = new RealmFilteredBeans<>(realmManager, beans);
beans = new FilteredBeans<>(realmManager::visibilityPredicate, beans);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double filtering for Plexus beans in the default configuration

Under the default configuration (jsr330ComponentVisibilityFollowsPlexusVisibility = true + componentVisibility = "realm"), the beans iterable arriving here is already a FilteredBeans — because DefaultBeanLocator.locate() wraps in FilteredBeans(realmManager::visibilityPredicate, result) when the predicate supplier is set.

This line then wraps it in a second FilteredBeans with the same predicate. Every Plexus bean entry gets evaluated twice by the same realm-visibility logic — not a correctness bug (the filter is idempotent), but redundant work on every Plexus component lookup.

Two possible approaches:

(a) Skip wrapping when the underlying locator already filters:

Suggested change
beans = new FilteredBeans<>(realmManager::visibilityPredicate, beans);
beans = beans instanceof FilteredBeans ? beans : new FilteredBeans<>(realmManager::visibilityPredicate, beans);

(b) Accept as a known tradeoff and add a comment documenting that double filtering is harmless. The per-entry cost is small (two string comparisons), so this may be acceptable depending on the project's preference.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would go with b), as this is true ONLY if using PlexusDefaultContainer in Maven-like scenario.
OTOH, if Sisu Inject is used with some custom filtering, combined with something else, this does not stand (the whole premise of "double filtering" is Maven specific and true there only).

@mcculls ?

@cstamas cstamas Jul 26, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, and also, this is true for plexus beans only. The goal is to move off from plexus beans (Maven core already did), so this double-filtering in Maven case stands only for legacy stuff... as Maven core in 3.10+ is not Plexus anymore, is migrated to JSR330.

@cstamas cstamas added this to the 1.1.0 milestone Jul 27, 2026
@cstamas
cstamas merged commit 41467dd into main Jul 27, 2026
14 checks passed
@cstamas
cstamas deleted the jsr330-filtering branch July 27, 2026 15:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement bean filtering

3 participants