You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@maven.apache.org by Hari Krishna Dara <ha...@gmail.com> on 2021/12/29 18:34:53 UTC

Building managed dependencies incrementally

Hi everyone,

I recently started looking at available options to refactor dependencies
across multiple projects such that they are not only consistent but it
would also be easier to change them from one central location, though the
most interesting outcome is to normalize the dependency versions. This
would help reduce the time to respond when a vulnerability is detected as
you would have clarity on the version used and changing it in one place is
going to be quicker. While many of our projects already use
dependencyManagement at project level, we don't manage them across
projects. I see two popular approaches to sharing dependencyManagement at a
higher level:

1) via parent POM
2) using a BOM

In both approaches, one would have to lift the dependencyManagement
sections out of the projects and merge them into the POM of parent or BOM
project. While the BOM approach has some advantages, such as being usable
in an unrelated project (not sharing the same parent POM), both have one
major drawback. The dependency declarations across different projects can
differ in some attributes such as the scope and exclusion rules, which
means the individual projects would need to override the declaration.
However, each such override needs to be a complete declaration by itself,
which means, a child dependencyManagement can't just override the
attributes that are different. E.g., even if it is only the scope that
needs to be changed, we still need to repeat the version which defeats the
purpose of normalizing all the dependency versions at one place. I recently
created MNG-7368 <https://issues.apache.org/jira/browse/MNG-7368> to
provide this flexibility as an  improvement.

I looked at the Maven code to get a better sense of why this happens. I see
that in ModelMerger.mergeDependencyManagement_Dependencies()
<https://github.com/apache/maven/blob/0a8bd727ac6d184512ce513737bb56bb840d10de/maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger.java#L1247>,
we basically use a default merge logic that simply replaces the entire
dependency structure. Something similar can be observed for import scope in
DefaultDependencyManagementImporter.importManagement()
<https://github.com/apache/maven/blob/0a8bd727ac6d184512ce513737bb56bb840d10de/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java#L75>.
What we need for both these places is to do a deeper level merge by merging
the dependency fields. I did a quick POC of implementing a custom merger
and was able to avoid repeating the version while overriding parent POM. By
calling into the same merge from importManagement(), I was also able to
achieve this for the BOM approach.

I updated MNG-7368 <https://issues.apache.org/jira/browse/MNG-7368> with
some of these findings. I started this thread to quickly come to know of
its viability as well as to discuss the nitty gritty details more
interactively. Does anyone else think that having this improvement in place
would facilitate a better management for dependencies? If not, what other
approach can be used to achieve the same goals?

Thank you,
Hari