Uploaded image for project: 'Maven'
  1. Maven
  2. MNG-8041

Maven Core bug regarding resolution scopes for Mojos

    XMLWordPrintableJSON

Details

    Description

      This bug affects all released Maven versions.

      Reproducer: https://github.com/cstamas/MNG-8041

      Description of the bug: when a Mojo requires Core to collect/resolve given ResolutionScope, Maven Core does it wrong. Problem is how LifecycleDependencyResolver and DefaultProjectDependenciesResolver colaborate plus, how Resolver works. LDR constructs the Resolver filters properly, then it calls into DPDR, that performs collection. To achieve that, DPDR blindly adds all the POM dependencies to Collect request (which is graph root). But this is wrong, as this should happen with considering requested (to be included or to be excluded) scopes. Next what happens, that when collect request is processed by Resolver, it will contain nodes from unwanted scopes (as Maven Core blindly added all of them from POM). Just as detail: if Resolver would be asked to create root, it would NOT add these in the first place. Due these present, conflict resolver may possibly eliminate other nodes (as POM ones "always wins", are the closest to graph root. Finally, these winners may be eliminated in subsequent step, for example due scope filtering. This results in incomplete resolution scope.

      Example: let's consider example where Mojo asks for "runtime" resolution scope. To serve this, Maven will add ALL dependencies present in POM to collect request (even those in scopes to be omitted, like "test" scoped ones), and will perform "collect" using Resolver. When Resolver returns the graph, it will contain nodes (as 1st level was populated by Maven) that MAY be contained in deeper nodes of non-test scoped ones (the guice+guava example). Next, "conflict resolution" happens, and naturally all the "test" scoped 1st level dependencies will "win", rendering removal of others. Finally, due "runtime" requested resolution scope, the "test" scoped dependencies are (rightfully) filtered out. This obviously leads to incomplete runtime build path.

      Or in other words, Maven is wrong here: it adds 1st level dependencies to CollectRequest that should not be there in the first place (in example above, the "test" scoped ones), that will cause that Resolver "collect" step build a graph that has "unwanted" scoped nodes closer to root than actually needed runtime dependencies (remember: test nodes will be not affected by filter, as they are already present, added by Maven, and test node children are collected also as "runtime", just to have "test" scope inherited later in the process, hence all the children of "test" node will end up in "test" scope, despite "exclude test" is present!), this will cause that in dependency conflict resolution step, they will kick out all the rightful runtime dependencies, and finally, all these winners are removed due scope filter.

      Implication of this bug is following important fact: the project "runtime" resolution scope (as when asked by Mojo) and project "runtime" resolution scope (as when used as a dependency on some downstream project) were not the same!

      Effects of this bug are explained in "Important Consequences" section of this page https://maven.apache.org/resolver-archives/resolver-2.0.0-alpha-7/common-misconceptions.html#important-consequences (that is wrongly written: all that is a consequence of this bug). Also, have to note, that when this bug get addressed, it will NOT render "workarounds" broken (ie. introduction of another module just to package "runtime" classpath using m-assembly-p or alike plugins), just "obsolete", as packaging of runtime dependencies will become possible in-situ (in the same module of the project).

      Exercises: check out reproducer and execute these commands:

      • mvn dependency:tree => OK, it shows "dependencies included from all scopes" (this is equiv to "test" build scope), guava is in test scope
      • mvn dependency:tree -Dscope=runtime => NOT OK, it will show effect of this bug, guava is missing from runtime resolution scope
      • install the reproducer project into local repository, and create another project (or use downstream/pom.xml from reproducer) that uses reproducer project as dependency (only one, no depMgt and so on), ask for mvn dependency:tree => OK (and look! Guava IS there)

      Attachments

        Issue Links

          Activity

            People

              Unassigned Unassigned
              cstamas Tamas Cservenak
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

                Created:
                Updated: