ChatGPT解决这个技术问题 Extra ChatGPT

Differences between dependencyManagement and dependencies in Maven

What is the difference between dependencyManagement and dependencies? I have seen the docs at Apache Maven web site. It seems that a dependency defined under the dependencyManagement can be used in its child modules without specifying the version.

For example:

A parent project (Pro-par) defines a dependency under the dependencyManagement:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8</version>
    </dependency>
 </dependencies>
</dependencyManagement>

Then in the child of Pro-par, I can use the junit:

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
    </dependency>
 </dependencies>

However, I wonder if it is necessary to define junit in the parent pom? Why not define it directly in the needed module?


L
Lii

I'm fashionably late to this question, but I think it's worth a clearer response than the accepted one (which is correct, but doesn't emphasize the actual important part, which you need to deduce yourself).

In the parent POM, the main difference between the <dependencies> and <dependencyManagement> is this:

Artifacts specified in the section will ALWAYS be included as a dependency of the child module(s).

Artifacts specified in the section, will only be included in the child module if they were also specified in the section of the child module itself. Why is it good you ask? Because you specify the version and/or scope in the parent, and you can leave them out when specifying the dependencies in the child POM. This can help you use unified versions for dependencies for child modules, without specifying the version in each child module.


I'm also late for the party, but here is one question. For dependancyManagement section, why not have properties (versions) set in parent and then, in child, just use that version in dependencies section? Why have it set in both parent and child pom?
I would add to Artifacts specified in the <dependencies> section will ALWAYS be included as a dependency of the child module(s) that they are included in the parent as well. Seems its not possible to set a dependency for children, but not for the parent.
@DimitarVukman because the answer is incomplete: it is simply more than version. You may have defined version, scope and even exclusion for a dependency. And, even just for version, it is much clearer and more maintenanble to just declare GA (group, artifact) in child pom, instead of GAV (and the value of V is something you defined customly in parent)
the value of the dependencyManagement in a parent pom becomes clear when you have 10, 15, or scores of projects and you need to ensure that they are all using the same versions of various shared libraries without necessarily declaring that all of those projects use all of those dependencies
Why not to put the dependencies too, into the parent pom.xml? Is it not a good idea just in case these dependencies are not needed by all the child projects?
P
Pascal Thivent

Dependency Management allows to consolidate and centralize the management of dependency versions without adding dependencies which are inherited by all children. This is especially useful when you have a set of projects (i.e. more than one) that inherits a common parent.

Another extremely important use case of dependencyManagement is the control of versions of artifacts used in transitive dependencies. This is hard to explain without an example. Luckily, this is illustrated in the documentation.


So, its need to declare dependencies in child project pom's anyway even if they declared in parent project's pom at section? Is it possible to make some kind of inheritance of dependencies?
Yes, you still need to define them in the child POM to show that you are using them. They are not actually included in the child projects just because they are in <dependencyManagement> in the parent POM. Enclosing dependencies in <dependencyManagement> centralizes management of the version, scope, and exclusions for each dependency, if and when you decide to use it. Maven's guide to dependency management gets into all the details.
The second paragraph (dependencyManagement also controls transitive dependencies) is only true when the dependencies are explicitly set: stackoverflow.com/questions/28312975/…
@johnny-b-goode What you can still do is creating a new dependencies section in your parent pom. We did that so that all child project have some apache-commons by default and not to declare them all the time.
It is useful to note that dependencyManagement also controls the scope, not just the version of transitive dependencies.
J
Janez Kuhar

The documentation on the Maven site is horrible. What dependencyManagement does is simply move your dependency definitions (version, exclusions, etc) up to the parent pom, then in the child poms you just have to put the groupId and artifactId. That's it (except for parent pom chaining and the like, but that's not really complicated either - dependencyManagement wins out over dependencies at the parent level - but if have a question about that or imports, the Maven documentation is a little better).

After reading all of the 'a', 'b', 'c' garbage on the Maven site and getting confused, I re-wrote their example. So if you had 2 projects (proj1 and proj2) which share a common dependency (betaShared) you could move that dependency up to the parent pom. While you are at it, you can also move up any other dependencies (alpha and charlie) but only if it makes sense for your project. So for the situation outlined in the prior sentences, here is the solution with dependencyManagement in the parent pom:

<!-- ParentProj pom -->
<project>
  <dependencyManagement>
    <dependencies>
      <dependency> <!-- not much benefit defining alpha here, as we only use in 1 child, so optional -->
        <groupId>alpha</groupId>
        <artifactId>alpha</artifactId>
        <version>1.0</version>
        <exclusions>
          <exclusion>
            <groupId>zebra</groupId>
            <artifactId>zebra</artifactId>
          </exclusion>
        </exclusions>
      </dependency>
      <dependency>
        <groupId>charlie</groupId> <!-- not much benefit defining charlie here, so optional -->
        <artifactId>charlie</artifactId>
        <version>1.0</version>
        <type>war</type>
        <scope>runtime</scope>
      </dependency>
      <dependency> <!-- defining betaShared here makes a lot of sense -->
        <groupId>betaShared</groupId>
        <artifactId>betaShared</artifactId>
        <version>1.0</version>
        <type>bar</type>
        <scope>runtime</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
</project>

<!-- Child Proj1 pom -->
<project>
  <dependencies>
    <dependency>
      <groupId>alpha</groupId>
      <artifactId>alpha</artifactId>  <!-- jar type IS DEFAULT, so no need to specify in child projects -->
    </dependency>
    <dependency>
      <groupId>betaShared</groupId>
      <artifactId>betaShared</artifactId>
      <type>bar</type> <!-- This is not a jar dependency, so we must specify type. -->
    </dependency>
  </dependencies>
</project>

<!-- Child Proj2 -->
<project>
  <dependencies>
    <dependency>
      <groupId>charlie</groupId>
      <artifactId>charlie</artifactId>
      <type>war</type> <!-- This is not a jar dependency, so we must specify type. -->
    </dependency>
    <dependency>
      <groupId>betaShared</groupId> 
      <artifactId>betaShared</artifactId> 
      <type>bar</type> <!-- This is not a jar dependency, so we must specify type. -->
    </dependency>
  </dependencies>
</project>

Somewhat off-topic question: what does dependency type "bar" mean? I saw in an example pom on the Maven documentation but couldn't find a definition. I assumed it was a typo of "war" or "jar", but I see it in other examples such as yours.
NobodyMan - So it is just a placeholder for another archive type. Like using 'foo'. Or it could be used if someone made a custom type with the extension 'bar'. And there are plenty of obscure archive types out there. Like sar, which is jboss service archive.
Your example is quite clear, and reaffirms what I had grokked on my own from the documentation. Have you submitted it to the Maven project? Having studied your example, I am preparing to simplify a POM that has both, and needs only Dependency declarations, since the project with which it is associated has no children.
Well, I was about to drop the DependencyManagement node, until it occurred to me that leaving it allows me to establish a minimum version for any child POMs that find their way into the dependency tree indirectly. As an example, in chasing down javax.cache.cache-apI, I discovered a significantly newer version 1.0.0 (versus 0.3.0) that may as well be used throughout.
This explanation is pefect.
A
Andrejs

There's still one thing that is not highlighted enough, in my opinion, and that is unwanted inheritance.

Here's an incremental example:

I declare in my parent pom:

<dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>19.0</version>
        </dependency>
</dependencies>

boom! I have it in my Child A, Child B and Child C modules:

Implicilty inherited by child poms

A single place to manage

No need to redeclare anything in child poms

I can still redelcare and override to version 18.0 in a Child B if I want to.

But what if I end up not needing guava in Child C, and neither in the future Child D and Child E modules?

They will still inherit it and this is undesired! This is just like Java God Object code smell, where you inherit some useful bits from a class, and a tonn of unwanted stuff as well.

This is where <dependencyManagement> comes into play. When you add this to your parent pom, all of your child modules STOP seeing it. And thus you are forced to go into each individual module that DOES need it and declare it again (Child A and Child B, without the version though).

And, obviously, you don't do it for Child C, and thus your module remains lean.


Will the dependencies mentioned in downloded for parent pom project?
Are you sure that if we use <dependencyManagement> in the parent pom then by default dependencies won't be inherited in the child poms? Because in the doc:maven.apache.org/guides/introduction/… while explaining the second use of the <dependencyManagement> it looks like it will be inherited by default. At one line they are saying that:"When maven is run on project B, version 1.0 of artifacts a, b, c, and d will be used regardless of the version specified in their pom" even though "b" is not used in the project B
Try it out yourself
And as someone already asked but remained unanswered, why not to simply use properties from the parent pom without dependencyManagement section in the parent?
@Andrey M. Stepanov - good question. For a single dependency, it's not only the version that you may want to manage centrally, but also the , and other artifact attributes. It's cleaner to use then, instead of 3-4 properties per artifact.
K
Koray Tugay

It's like you said; dependencyManagement is used to pull all the dependency information into a common POM file, simplifying the references in the child POM file.

It becomes useful when you have multiple attributes that you don't want to retype in under multiple children projects.

Finally, dependencyManagement can be used to define a standard version of an artifact to use across multiple projects.


So, dependencies does not inherited? Its need to be declared in child project's pom anyway?
Yes, you need to declare them anyway in children projects, but without specifying a version.
This scenario is useful when you want to have governance of versions in multiple java projects having parent-child relationship.
I
IamVickyAV

Sorry I am very late to the party.

Let me try to explain the difference using mvn dependency:tree command

Consider the below example

Parent POM - My Project

<modules>
    <module>app</module>
    <module>data</module>
</modules>

<dependencies>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>19.0</version>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.9</version>
        </dependency>
    </dependencies>
</dependencyManagement>

Child POM - data module

<dependencies>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
    </dependency>
</dependencies>

Child POM - app module (has no extra dependency, so leaving dependencies empty)

 <dependencies>
</dependencies>

On running mvn dependency:tree command, we get following result

Scanning for projects...
------------------------------------------------------------------------
Reactor Build Order:

MyProject
app
data

------------------------------------------------------------------------
Building MyProject 1.0-SNAPSHOT
------------------------------------------------------------------------

--- maven-dependency-plugin:2.8:tree (default-cli) @ MyProject ---
com.iamvickyav:MyProject:pom:1.0-SNAPSHOT
\- com.google.guava:guava:jar:19.0:compile

------------------------------------------------------------------------
Building app 1.0-SNAPSHOT
------------------------------------------------------------------------

--- maven-dependency-plugin:2.8:tree (default-cli) @ app ---
com.iamvickyav:app:jar:1.0-SNAPSHOT
\- com.google.guava:guava:jar:19.0:compile

------------------------------------------------------------------------
Building data 1.0-SNAPSHOT
------------------------------------------------------------------------

--- maven-dependency-plugin:2.8:tree (default-cli) @ data ---
com.iamvickyav:data:jar:1.0-SNAPSHOT
+- org.apache.commons:commons-lang3:jar:3.9:compile
\- com.google.guava:guava:jar:19.0:compile

Google guava is listed as dependency in every module (including parent), whereas the apache commons is listed as dependency only in data module (not even in parent module)


C
Clijsters

There are a few answers outlining differences between <depedencies> and <dependencyManagement> tags with maven.

However, few points elaborated below in a concise way:

allows to consolidate all dependencies (used at child pom level) used across different modules -- clarity, central dependency version management allows to easily upgrade/downgrade dependencies based on need, in other scenario this needs to be exercised at every child pom level -- consistency dependencies provided in tag is always imported, while dependencies provided at in parent pom will be imported only if child pom has respective entry in its tag.


M
Mustafa Güven

If the dependency was defined in the top-level pom's dependencyManagement element, the child project did not have to explicitly list the version of the dependency. if the child project did define a version, it would override the version listed in the top-level POM’s dependencyManagement section. That is, the dependencyManagement version is only used when the child does not declare a version directly.


I believe this statement may not be correct. In Maven's Dependency Management examples (#2), they say that dependencies defined in a parent pom with a version, will override the version specified in the child pom: "When maven is run on project B version 1.0 of artifacts a, b, c, and d will be used regardless of the version specified in their pom."
@devdanke At least, Eclipse m2e issues a warning: Overriding managed version ... for ....
H
Harry Coder

Just in my own words, your parent-project helps you provide 2 kind of dependencies:

implicit dependencies : all the dependencies defined in the section in your parent-project are inherited by all the child-projects

explicit dependencies : allows you to select, the dependencies to apply in your child-projects. Thus, you use the section, to declare all the dependencies you are going to use in your different child-projects. The most important thing is that, in this section, you define a so that you don't have to declare it again in your child-project.

The <dependencyManagement> in my point of view (correct me if I am wrong) is just useful by helping you centralize the version of your dependencies. It is like a kind of helper feature. As a best practice, your <dependencyManagement> has to be in a parent project, that other projects will inherit. A typical example is the way you create your Spring project by declaring the Spring parent project.


r
rps

The difference between the two is best brought in what seems a necessary and sufficient definition of the dependencyManagement element available in Maven website docs:

dependencyManagement

"Default dependency information for projects that inherit from this one. The dependencies in this section are not immediately resolved. Instead, when a POM derived from this one declares a dependency described by a matching groupId and artifactId, the version and other values from this section are used for that dependency if they were not already specified." [ https://maven.apache.org/ref/3.6.1/maven-model/maven.html ]

It should be read along with some more information available on a different page:

“..the minimal set of information for matching a dependency reference against a dependencyManagement section is actually {groupId, artifactId, type, classifier}. In many cases, these dependencies will refer to jar artifacts with no classifier. This allows us to shorthand the identity set to {groupId, artifactId}, since the default for the type field is jar, and the default classifier is null.” [https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html ]

Thus, all the sub-elements (scope, exclusions etc.,) of a dependency element--other than groupId, artifactId, type, classifier, not just version--are available for lockdown/default at the point (and thus inherited from there onward) you specify the dependency within a dependencyElement. If you’d specified a dependency with the type and classifier sub-elements (see the first-cited webpage to check all sub-elements) as not jar and not null respectively, you’d need {groupId, artifactId, classifier, type} to reference (resolve) that dependency at any point in an inheritance originating from the dependencyManagement element. Else, {groupId, artifactId} would suffice if you do not intend to override the defaults for classifier and type (jar and null respectively). So default is a good keyword in that definition; any sub-element(s) (other than groupId, artifactId, classifier and type, of course) explicitly assigned value(s) at the point you reference a dependency override the defaults in the dependencyManagement element.

So, any dependency element outside of dependencyManagement, whether as a reference to some dependencyManagement element or as a standalone is immediately resolved (i.e. installed to the local repository and available for classpaths).


G
Gangnus

In Eclipse, there is one more feature in the dependencyManagement. When dependencies is used without it, the unfound dependencies are noticed in the pom file. If dependencyManagement is used, the unresolved dependencies remain unnoticed in the pom file and errors appear only in the java files. (imports and such...)


@KorayTugay "unresolved", of course, thank you for your notice. Edited.
x
xxy

I do not recommend using dependencyManagement.

The only benefit of using it is that you can define the version in parent pom and do not need to define it again in child pom. But if you have a set of projects (especially micro-service projects). Using dependencyManagement has no benefits.

Different projects may need different dependency. Why inherit it from the same parent pom. Keep it as simple as possible. If one project needs A dependency, then add it to the pom file. Don't confuse developers.


You are missing a point that you can define/override transitive dependencies which give you a single location in a project which dependencyManagement is the right choice...If you have single module setup than your statement is fine but if you have more than one it easier to have a dependencyManagement in your root pom and define everything there...centralized location when you need to change things...also many libraries etc. give you a bom which makes it easier to use those frameworks/libs (junit 5/spring boot/etc.)...
J
JSamir

If you have a parent-pom anyways, then in my opinion using <dependencyManagement> just for controlling the version (and maybe scope) is a waste of space and confuses junior developers.

You will probably have properties for versions anyways, in some kind of parent-pom file. Why not just use this properties in the child pom's? That way you can still update a version in the property (within parent-pom) for all child projects at once. That has the same effect as <dependencyManagement> just without <dependencyManagement>.

In my opinion, <dependencyManagement> should be used for "real" management of dependencies, like exclusions and the like.


M
MagGGG

One use case of <dependencyManagement> is for resolving library versions conflict.

Example:

Project A have library x:1.0.1

Project A have B library

B library have library x:1.0.0

Having this set you will get conflict having project A both x:1.0.1 and x:1.0.0. To resolve this you can put dependency with specific version into <dependencyManagement> tag


P
Phan Xuan Bao

It was explained by here to be easy to understand. The conclusion difference between dependencyManagement & dependencies are declaration and actually addition


As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.