gnodet opened a new pull request, #13728:
URL: https://github.com/apache/maven/pull/13728

   ## Problem
   
   When building with `-b concurrent` and a high thread count (e.g. `--threads 
max`), the build fails intermittently with:
   
   ```
   Failed to execute goal 
org.apache.maven.plugins:maven-dependency-plugin:3.11.0:properties
   (prepare-for-mockito-agent) on project apache-maven: Cannot invoke
   "java.io.File.getAbsolutePath()" because the return value of
   "org.apache.maven.artifact.Artifact.getFile()" is null
   ```
   
   Reproducer (self-build):
   ```
   mvn -b concurrent --threads max install -DskipTests -o
   ```
   
   ## Root cause
   
   In `LifecycleDependencyResolver.resolveProjectDependencies()`, a snapshot of 
each reactor project's artifact file was taken up-front into a `Map<Artifact, 
File>`:
   
   ```java
   Map<Artifact, File> reactorProjects = new 
HashMap<>(session.getProjects().size());
   for (MavenProject reactorProject : session.getProjects()) {
       reactorProjects.put(
               reactorProject.getArtifact(),
               reactorProject.getArtifact().getFile()); // may be null!
   }
   ```
   
   In the concurrent builder, a sibling project may not yet have written its 
jar when this snapshot is taken. The map then stores `null` for that artifact's 
file. The subsequent guard `if (reactorProjectFile != null)` silently skips the 
`setFile()` call, leaving the artifact with a `null` file even after dependency 
resolution.
   
   Any plugin that then calls `artifact.getFile().getAbsolutePath()` on a 
resolved artifact will NPE. The `maven-dependency-plugin:properties` mojo (used 
here to expose the Mockito agent jar path to Surefire) is one such plugin.
   
   This is the same class that MNG-6300 previously fixed for the 
`target/classes` case; this is the concurrent-builder variant of the same 
problem.
   
   ## Fix
   
   Replace `Map<Artifact, File>` with `Map<Artifact, MavenProject>` and defer 
`getFile()` to lookup time, so the most up-to-date value is always used:
   
   ```java
   Map<Artifact, MavenProject> reactorProjects = new 
HashMap<>(session.getProjects().size());
   for (MavenProject reactorProject : session.getProjects()) {
       reactorProjects.put(reactorProject.getArtifact(), reactorProject);
   }
   // ...
   MavenProject reactorProject = reactorProjects.get(artifact);
   if (reactorProject != null) {
       File reactorProjectFile = reactorProject.getArtifact().getFile();
       if (reactorProjectFile != null) {
           artifact.setFile(reactorProjectFile);
       }
   }
   ```
   
   ## Verification
   
   Before fix: `mvn -b concurrent --threads 16 install -DskipTests 
-Drat.skip=true -o` fails ~1 in 3 runs.
   After fix: 5 consecutive runs all pass (the race is no longer triggerable).


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to