[MNG-5527] Honor BOM relocation during dependency management import - #13081
goutamadwant wants to merge 3 commits into
Conversation
Follow partial and chained BOM relocations in both model builders while preserving import precedence, exclusions, resolver-selected versions, and ordinary imported-model validation behavior. Detect relocation and mixed import cycles, retain coordination for ordinary cold imports, and avoid cyclic waits introduced by relocation traversal. Add focused compatibility and concurrency tests and a Core IT for the reported missing managed-version failure. Signed-off-by: goutamadwant <workwithgoutam@gmail.com>
| + dependency.getManagementKey() + " is missing.") | ||
| .setLocation(dependency.getLocation(""))); | ||
| continue; | ||
| DependencyManagement importMgmt = loadDependencyManagement(dependency, model, request, problems, importIds); |
There was a problem hiding this comment.
renamed the variables to use full names.
| } | ||
|
|
||
| continue; | ||
| @SuppressWarnings("checkstyle:methodlength") |
There was a problem hiding this comment.
maybe you should break this method up
| importRequest.setUserProperties(request.getUserProperties()); | ||
| importRequest.setLocationTracking(request.isLocationTracking()); | ||
| } | ||
| final ModelBuildingResult importResult; |
There was a problem hiding this comment.
move into the try block, don't split declaration and initialization
There was a problem hiding this comment.
Sure. Moved the declaration and initialization of importResult inside the try block, together with the result handling. Let me know if this is good now
gnodet
left a comment
There was a problem hiding this comment.
I reviewed the three comments from @elharo. Here's my assessment:
Comment 1 — "no abbreviations please" (line 1185, importMgmt)
importMgmt is not new to this PR — it already exists on master (along with depMgmt) in the same method. The PR merely moved this code into an extracted loadDependencyManagement method. While renaming abbreviations is a fine cleanup, it shouldn't be a blocker for this PR since it's pre-existing code. If there's a desire to rename these, it could be done as a separate cleanup across the file.
Comment 2 — "maybe you should break this method up" (line 1199, @SuppressWarnings("checkstyle:methodlength"))
The @SuppressWarnings("checkstyle:methodlength") was on master's importDependencyManagement before this PR. This PR already did break the method up: it extracted loadDependencyManagement out of importDependencyManagement, which went from ~160 lines down to ~15. The new method inherited the suppress annotation because the relocation-chain logic added more code. Further decomposition is possible (e.g., extracting the relocation handling) but this is already a significant improvement over master.
Comment 3 — "move into the try block, don't split declaration and initialization" (line 1303)
The final ModelBuildingResult importResult; pattern is carried verbatim from master (previously at the same indentation inside the loop). It's a pre-existing pattern, not introduced by this PR. That said, it's a trivial fix — the variable can be moved inside the try block:
try {
final ModelBuildingResult importResult = build(importRequest, importIds);
problems.addAll(importResult.getProblems());
importModel = importResult.getEffectiveModel();
} catch (ModelBuildingException e) {
problems.addAll(e.getProblems());
return null;
}This is a reasonable cleanup the contributor could apply.
Summary: All three comments point at pre-existing patterns that this PR carried over unchanged. Comment 3 is the only one with a concrete, actionable fix that's trivial to apply. The other two are either already addressed by the PR (method extraction) or out of scope (renaming existing abbreviations).
|
Maven 4 already has a relocation SPI: Also a relocation-only loop reports "dependencies of type=pom and with scope=import form a cycle" though one import is declared; |
|
Good observations @renechoi. Two distinct points here: 1. Relationship with These operate at different layers:
Before this PR, if a BOM declared Regarding 2. Error message wording for relocation-only cycles Valid point. When a cycle involves only relocation hops (no actual This review was generated by an AI agent, Hermès on behalf of @gnodet. |
Use a cycle diagnostic that covers imports and relocations in both model builders. Assert the complete message for ordinary, relocation-only, and mixed cycles. Extract imported-model resolution from compatibility dependency-management loading, expand the local variable names, and initialize the model-building result inside its try block. Signed-off-by: goutamadwant <workwithgoutam@gmail.com>
Yes, this fix is limited to distributionManagement relocations in imported BOMs. Imports use ModelResolver rather than the artifact-descriptor relocation SPI; extending maven.relocations.entries to BOM imports would be a separate change. Changed the diagnostic to “The import POMs form a cycle”, covering ordinary imports, relocations, and mixed cycles. Both model builders now assert the message and cycle path. @gnodet, could you approve the new CI run? |
gnodet
left a comment
There was a problem hiding this comment.
Second commit (a7b8f49) addresses all outstanding review feedback:
-
Variable renames —
depMgmt→dependencyManagement,importMgmt→importedManagement,importMgmts→importedManagements. Pre-existing abbreviations cleaned up per @elharo's request. -
Method extraction —
resolveImportModel()extracted fromloadDependencyManagement(), removing the@SuppressWarnings("checkstyle:methodlength"). The extraction is a pure refactoring: workspace-first resolution with early return, then fallback toModelResolver, same semantics as before with cleaner flow. -
Declaration inside try —
importResultis now declared and initialized inside the try block as requested. -
Cycle diagnostic — Message changed to
"The import POMs form a cycle: ..."in both model builders (compat and impl), covering relocations, imports, and mixed cycles. Concise and accurate regardless of whether the cycle involves relocation hops. -
New tests —
detectsImportCycle()in the compat builder test anddetectsDirectImportCycle()in the impl builder test, both asserting the updated cycle message.
CI status: all completed checks are green. The one failure (integration-tests (macos-latest, 17)) is an infrastructure issue — the "Set up JDK 17" step failed, not related to this PR. Remaining checks still in progress.
Changes look solid. @gnodet — this is ready for your review when CI completes.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
|
CI has been approved and is running. Status so far:
The second commit addresses all review feedback cleanly:
Looks good. I'll re-check once the remaining integration tests complete. This comment was generated by an AI agent, Hermès on behalf of @gnodet. |
gnodet-bot
left a comment
There was a problem hiding this comment.
Re-review: [MNG-5527] Honor BOM relocation during dependency management import
Verdict: 💬 COMMENT — All prior review feedback (elharo + gnodet) addressed. One gap in the compat builder worth fixing before merge.
Prior findings — all addressed
- ✅
depMgmt→dependencyManagement,importMgmts→importedManagements— renamed. - ✅ Method broken up —
importDependencyManagementnow delegates toloadDependencyManagementandresolveImportModel. - ✅ Variable declarations moved inside try blocks.
Finding: potential NPE in compat resolveImportModel when workspace returns null and modelResolver is absent
In compat/maven-model-builder, the guard at the top of resolveImportModel only catches the case where both resolvers are null:
if (workspaceResolver == null && modelResolver == null) { throw new NullPointerException(...); }If workspaceResolver is non-null but returns null (model not in workspace — a legitimate outcome), execution falls through to:
importSource = modelResolver.resolveModel(groupId, artifactId, version);modelResolver could be null here — for example, IDE embedders that supply a WorkspaceModelResolver but no legacy ModelResolver. This produces an NPE with no actionable diagnostic.
Fix: add a null guard before the fallthrough:
if (modelResolver == null) {
problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
.setMessage("Cannot resolve import POM "
+ ModelProblemUtils.toId(groupId, artifactId, version)
+ ": not found in workspace and no ModelResolver provided")
.setLocation(dependency.getLocation("")));
return null;
}Impl builder: concurrency analysis
The ImportModelCacheEntry + ReentrantLock + volatile ImportedModel pattern is correct:
- Normal import paths block (via
lock.lock()) until the in-flight build completes, then re-readcached.model— avoids duplicate work. - Relocation paths skip waiting via
tryLockto prevent deadlock when a relocation chain leads back to a currently-building import — produces at most duplicate work, not a correctness problem. volatileoncached.modelguarantees cross-thread visibility without needing a fullsynchronizedblock.BomRelocationConcurrencyTestcovers concurrent cycles, concurrent aliases, and the shared-build path (concurrentOrdinaryImportsBuildSharedBomOnce).
No concurrency bugs in the impl builder.
Test coverage
BomRelocationTest (compat) covers simple relocation, partial chains, cycles (relocation→import, import→relocation, import→import), workspace path, invalid coordinates, and deduplication (resolutions.get("test:new:1") == 1).
BomRelocationTest + BomRelocationConcurrencyTest (impl) mirror the compat coverage and add multi-thread correctness.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
Report a model-building error when an imported BOM is absent from the workspace and no fallback ModelResolver is configured. Include the attempted coordinates and original import location in the diagnostic. Cover original and relocated workspace misses, configured fallback resolution, and workspace error precedence without changing successful imports or the existing invalid-request contract.
|
@gnodet-bot @gnodet Fixed. A workspace miss without a fallback ModelResolver now reports a normal model-building error with the missing BOM coordinates and import location. thanks! |
gnodet-bot
left a comment
There was a problem hiding this comment.
Re-review: [MNG-5527] Honor BOM relocation during dependency management import
Verdict: ✅ APPROVE
Prior finding — addressed
✅ The modelResolver == null guard in compat resolveImportModel is now in place. When a workspace resolver is configured but returns null (model absent from workspace) and no fallback ModelResolver is provided, an ERROR-severity problem with coordinates and source location is reported instead of throwing an NPE.
The severity choice is correct: FATAL is reserved for workspace resolver exceptions (the catch (UnresolvableModelException e) path above). A misconfigured embedder that provides only a workspace resolver without a fallback is a build-configuration error, not a fatal runtime failure — ERROR is appropriate and consistent with the UnresolvableModelException path.
New tests
Five new test methods in BomRelocationTest (compat) cover the full matrix:
reportsWorkspaceMissWithoutModelResolver— plain miss, empty workspace, no fallbackreportsWorkspaceRelocationTargetMissWithoutModelResolver— relocation chain where the target is missingfallsBackToModelResolverAfterWorkspaceMiss— workspace returns null, fallback resolver succeedsfallsBackToModelResolverForWorkspaceRelocationTarget— relocation chain where only the target needs fallbackpreservesWorkspaceResolutionFailure— workspace exception (FATAL) takes precedence over fallback
assertMissingWorkspaceModel asserts ERROR severity, message contains the missing coordinates, modelId == "test:consumer:1", and both lineNumber > 0 / columnNumber > 0 (location tracking enabled). Thorough.
No new issues.
This review was generated by an AI agent, Hermès on behalf of @gnodet.
Fixes #6804.
Follow BOM relocation chains in both model builders, including partial relocations. Preserve dependency-management precedence, import exclusions, and the modern resolver's selected version when resolving a range.
Report invalid relocation coordinates, missing relocation targets, and relocation/import cycles without changing ordinary imported-model validation behavior. Preserve sharing of ordinary in-flight imports while avoiding cyclic waits introduced by relocation traversal.
Validation:
The reported failure reproduces on untouched master and passes with the fix through both the CLI and the new Core IT.
All 39 focused relocation, compatibility, and concurrency tests pass.
mvn verifypasses: 3,152 unit tests, zero failures/errors, 16 skips, plus one reactor integration test.Full forked Core IT: 1,074 tests, three failing tests, 43 skips. MNG3955 and MNG4411 fail identically on untouched master. MavenITMvnupToolchainPluginStrategyTest passes after refreshing its previously modified generated fixture. MNG4590 and the new MNG5527 test pass in the full run.
This pull request addresses one issue without unrelated changes.
The description explains what changes, how, and why.
Commits have meaningful subjects and bodies.
Regression tests cover the behavioral changes; the reported case fails without the fix.
mvn verifypasses.The Core IT suite passes.
I hereby declare this contribution to be licenced under the Apache License Version 2.0, January 2004.
In any other case, please file an Apache Individual Contributor License Agreement.