Skip to content

SONARJAVA-6421 Implement S9352: Bean autowiring ambiguity should be resolved using "@Qualifier" or "@Primary" - #6073

Merged
NoemieBenard merged 14 commits into
epic-SONARJAVA-6237from
nb/sonarjava-6421-implement-s9352
Sep 8, 2026
Merged

SONARJAVA-6421 Implement S9352: Bean autowiring ambiguity should be resolved using "@Qualifier" or "@Primary"#6073
NoemieBenard merged 14 commits into
epic-SONARJAVA-6237from
nb/sonarjava-6421-implement-s9352

Conversation

@NoemieBenard

@NoemieBenard NoemieBenard commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Implements the S9352 rule (AmbiguousDependencyCheck) using the SpringContextModel/TypeToDependenciesIndex built by the model-extension branch, plus the @Profile extraction added on top of it.
  • Wires check reporting through SpringContextModelSensor and JavaFrontend.
  • Registers the rule (metadata, Sonar way profile) and adds unit + cross-module integration tests.
  • Includes a fix for a false positive where profile filtering wasn't re-checking uniqueness/primary on the filtered candidate set.

@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

SONARJAVA-6421

Comment thread java-frontend/src/main/java/org/sonar/java/JavaFrontend.java
@NoemieBenard
NoemieBenard force-pushed the nb/sonarjava-6421-implement-s9352 branch from 32778b7 to 001cfdb Compare September 2, 2026 12:40
@datadog-sonarsource

This comment has been minimized.

@NoemieBenard
NoemieBenard force-pushed the nb/sonarjava-6421-implement-s9352 branch from 878ad6a to a7b6ed9 Compare September 3, 2026 12:11
@NoemieBenard
NoemieBenard marked this pull request as ready for review September 3, 2026 12:13
gitar-bot[bot]

This comment was marked as resolved.

Base automatically changed from nb/sonarjava-6421-add-profile-support to epic-SONARJAVA-6237 September 8, 2026 09:51
@NoemieBenard
NoemieBenard force-pushed the nb/sonarjava-6421-implement-s9352 branch from 82217dc to bb7d327 Compare September 8, 2026 09:52
@gitar-bot
gitar-bot Bot dismissed their stale review September 8, 2026 09:53

✅ All blocking issues resolved.

Configure merge blocking

@gitar-bot

gitar-bot Bot commented Sep 8, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 12 resolved / 12 findings

Implements S9352 rule for detecting bean autowiring ambiguity, integrating with SpringContextModel and adding profile-aware resolution. The implementation resolves profile filtering logic, qualifier/field name matching, sensor rule activation checks, and IT concurrency issues.

✅ 12 resolved
Quality: Profile filtering logic, incl. the claimed FP fix, has no test

📄 java-checks/src/main/java/org/sonar/java/checks/spring/AmbiguousDependencyCheck.java:89-99 📄 java-checks/src/test/java/org/sonar/java/checks/spring/AmbiguousDependencyCheckTest.java:49-63
excludeCandidatesWithProfile / hasProfile and the re-application of the uniqueness/primary check on the filtered set are the behaviour the PR description calls out as the false-positive fix, yet grepping the new resources shows no @Profile anywhere in java-checks-test-sources/.../checks/spring/s9352/ nor in its/.../ambiguous-dependencies-should-be-resolved/; none of the 7 unit tests nor the cross-module IT exercises a profiled candidate. Add at least two cases: (a) two candidates where one is @Profile-annotated (expect no issue) and (b) three candidates where one is profiled and the remaining two are ambiguous (expect one issue), so the filtered-set re-check cannot silently regress.

Bug: Qualifier/field name matching profiled bean is a false positive

📄 java-checks/src/main/java/org/sonar/java/checks/spring/AmbiguousDependencyCheck.java:60-71 📄 java-checks/src/main/java/org/sonar/java/checks/spring/AmbiguousDependencyCheck.java:81-83 📄 java-checks/src/main/java/org/sonar/java/checks/spring/AmbiguousDependencyCheck.java:89-91
findInjectionPointsNotMatchingCandidateByName is called with effectiveCandidates, i.e. the candidate set after excludeCandidatesWithProfile removed every bean carrying a @Profile. Trigger: type Mailer has beans smtpMailer, sesMailer (no profile) and devMailer (@Profile("dev")), and an injection point annotated @Qualifier("devMailer") (BeanDefinitionGatherer stores the qualifier value as the injection-point name, see BeanDefinitionGatherer#dependencyKey). devMailer is not in effectiveCandidates, so the explicitly-qualified injection point is reported with message "Multiple beans match this dependency (sesMailer, smtpMailer)" — a false positive on code that is already disambiguated. Name/qualifier resolution should be evaluated against the full candidates set, since name-based resolution does not depend on the profile filtering used for the uniqueness heuristic.

Quality: Sensor runs checks and creates issues without an active-rule check

📄 sonar-java-plugin/src/main/java/org/sonar/plugins/java/SpringContextModelSensor.java:60-67
execute runs every SpringContextCheck and calls context.newIssue().forRule(ruleKey) unconditionally. When S9352 is not in the quality profile the whole-project analysis still runs and issues are built only to be discarded by the scanner engine (issues for inactive rules are dropped). Guard the loop with a lookup in context.activeRules() so a disabled rule costs nothing.

Quality: Dead condition: effectiveCandidates.size() > 1 is always true there

📄 java-checks/src/main/java/org/sonar/java/checks/spring/AmbiguousDependencyCheck.java:62-71 📄 java-checks/src/main/java/org/sonar/java/checks/spring/AmbiguousDependencyCheck.java:76-79
hasUniqueOrPrimaryCandidate returns true whenever candidates.size() <= 1, so reaching the body of if (!hasUniqueOrPrimaryCandidate(effectiveCandidates, registry) && effectiveCandidates.size() > 1) already guarantees effectiveCandidates.size() > 1. The extra clause is unreachable-as-false and suggests the two predicates are checking different things. Drop it to keep the intent ("still ambiguous after filtering") readable.

Quality: SAME_THREAD on the IT base class serializes unrelated IT classes

📄 its/scanner-integration-tests/src/test/java/org/sonar/java/it/ScannerIntegrationAbstractTest.java:56
The @Execution switch from CONCURRENT to SAME_THREAD is on the shared abstract base, so the pre-existing SpringBeansShouldBeAccessibleCrossModuleTest is serialized too, and every future subclass silently inherits it — each analyze() call runs a Maven build plus an in-process scanner run, so this is a real wall-clock cost on the IT suite. If the serialization is needed only because the new test cannot run concurrently (shared Maven local repository or shared plugin-container state), put @Execution(ExecutionMode.SAME_THREAD) on AmbiguousDependencyCrossModuleTest and document the reason; otherwise state in a comment on the base class why concurrent analyses are unsafe.

...and 7 more resolved from earlier reviews

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@NoemieBenard
NoemieBenard force-pushed the nb/sonarjava-6421-implement-s9352 branch from bb7d327 to 70debad Compare September 8, 2026 10:02
@sonarqube-next

sonarqube-next Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Quality Gate failed Quality Gate failed

Failed conditions
Vulnerability dependency risks too severe (required < 'medium' severity)

See analysis details on SonarQube

@asya-vorobeva asya-vorobeva 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.

LGTM! Thanks a lot for your hard work 🌻

@NoemieBenard
NoemieBenard merged commit bc76f52 into epic-SONARJAVA-6237 Sep 8, 2026
14 of 16 checks passed
@NoemieBenard
NoemieBenard deleted the nb/sonarjava-6421-implement-s9352 branch September 8, 2026 12:01
NoemieBenard added a commit that referenced this pull request Sep 8, 2026
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