2
votes

I referred to this thread differences between dependencymanagement and dependencies in maven but this question is specific.

Parent POM:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.company.rtdp.rtds</groupId>
      <artifactId>rtds-client</artifactId>
      <version>${rtdp.rtds-client.version}</version>
      <!-- SCENARIO 1 : Either give scope here in parent POM -->
      <!-- <scope>provided</scope> -->
    </dependency>
  </dependencies>
</dependencyManagement>

<rtdp.rtds-client.version>1.4.6</rtdp.rtds-client.version>

Child POM:

 <dependencies>
    <!-- SCENARIO 2
    <dependency> 
        <groupId>com.company.rtdp.rtds</groupId> 
        <artifactId>realtimedataserv-client</artifactId> 
        <version>1.4.6</version>
        <scope>provided</scope> 
    </dependency> 
    -->

    <dependency> 
        <groupId>com.company.idi</groupId> 
        <artifactId>idi-persistence</artifactId>
        <version>3.3</version>
        <!--  has a dependency of com.company.rtdp.rtds:rtds-client:jar:1.4.6:compile -->
    </dependency>
 </dependencies>

<!-- SCENARIO 1: OR give scope here in child POM 
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.company.rtdp.rtds</groupId>
      <artifactId>rtds-client</artifactId>
      <version>1.4.6</version>
      <scope>provided</scope> 
    </dependency>
  </dependencies>
</dependencyManagement>
-->

rtds-client is a transitive dependency of many artifacts out of which idi-persistence is one of them. I want to exclude 1.4.6 in all of the transitive dependencies since I am going to include a different artifact rtds-framework-client (different artifact name) explicitly which is backward compatible to 1.4.6 with <dependency> in child POM.

If have to use <exclusion> I have to explicitly give this in all the dependencies. So, I have decided to go <scope>provided</scope> way.

Known info of Maven based on which my question follows:

If I include the following in child POM (with a version higher than 1.4.6, then rtds-client in all transitive dependencies gets shifted to 1.8. I could see this from 'Dependency Hierarchy' of Eclipse which says 'omitted for conflict with 1.8' [compile]) which means it considers/overrides the version specified in child POM (idi-persistence now gets 1.8).

<dependency>
    <groupId>com.company.rtdp.rtds</groupId>
    <artifactId>rtds-client</artifactId>
    <version>1.8</version>
</dependency>

Question:

If I include the following in child POM without <dependencyManagement> around:

<dependency>
    <groupId>com.company.rtdp.rtds</groupId>
    <artifactId>rtds-client</artifactId>
    <version>1.4.6</version>
    <scope>provided<scope>
</dependency>

None of the rtds-client which comes as transitive dependency considers provided scope whereas I mention the same in a <dependencyManagement> tag either in parent or child POM, provided scope gets applied.

Why version gets affected but not scope given inside <dependency> tag and for scope (for this kind of use case) I have to go for <dependencyManagement> ?

Say if this is allowed, what problem it would lead us into ?

EDIT:

i) <scope>provided with <dependencyManagement>/<dependencies>/<dependency> either in child or parent POM:

enter image description here

Though the longer path is omitted, it says [provided],here.

[INFO] +- com.company.idi:idi-persistence:jar:3.3:compile
[INFO] |  +- com.company.rtdp.rtds:realtimedataserv-client:jar:1.4.6:provided

ii) <scope>provided with direct <dependencies>/<dependency> in child POM without <dependencyManagement> around :

enter image description here

Though the longer path is omitted, it does not say provided and just compile alone.

[INFO] --- maven-dependency-plugin:2.3:tree (default-cli) @ read-rest-service ---
[INFO] +- com.company.rtdp.rtds:realtimedataserv-client:jar:1.4.6:provided (scope not updated to compile)
1
1) It's called <exclusion> rather than <exclude>. 2) Perhaps this is due to Dependency mediation: "You can always guarantee a version by declaring it explicitly in your project's POM. Note that if two dependency versions are at the same depth in the dependency tree, [...] since Maven 2.0.9 it's the order in the declaration that counts: the first declaration wins." - Gerold Broser
Question is not about resolution of version conflict. It is about scope conflict. Why does it not resolve the scope the same way it does version with <dependency>? Say in the last snippet having version 1.4.6 <scope>provided</scope>, I replace the version to 1.8 retaining the same scope, rtds-client which comes as transitive dependencies for other dependencies in child pom, gets switched to version 1.8 (version conflict is taken care of), but it does not get switched to provided (it is still at compile)! It accepted a explicitly declared version but why not the scope? - user104309
Potentially unnecessary info which might cause confusion but may be useful: I do not use rtds-client's classes directly in my project. So I don't have to explicitly declare that inside <dependency> just to make it provided (if at all it worked) (looks like the purpose of explicit mention of dependency inside <dependency> targets only version and its meant for dependencies whose classes must be directly used in our project) although even this sounds like a good solution to me. - user104309
[continued] So it is better to mention provided inside <dependencyManagement> either in child or parent pom to propagate everything inside of this tag if at all they are used down the hierarchy. But say I am using rtds-client classes inside my project, this approach sounds like a very valid solution. - user104309
Dependency mediation is not just about versions. That's just an example. It concerns whole dependencies and their declaration(s). The "omitted for conflict with 1.8" is because of this mediation since the doc also says in the previous sentence: "Currently, Maven 2.0 only supports using the "nearest definition" which means that it will use the version of the closest dependency to your project in the tree of dependencies.". Without the complete POMs it's hard to say whether this behaviour (provided in <depMgmt> vs. <dep>) is intended, hence, logical or whether it's possibly a bug. - Gerold Broser

1 Answers

2
votes

I can't comprehend your <scope>provided in <dependencyManagement> vs. <dependency.

If I declare a child POM, with no dependency[Management] in the parent whatsoever, like:

<project ...>
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>igb.so</groupId>
        <artifactId>SO-44987444-parent</artifactId>
        <relativePath>../SO-44987444-parent</relativePath>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>SO-44987444-child</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-text</artifactId>
            <version>1.1</version>
            <!--  has a dependency of org.apache.commons:commons-lang3:jar:3.5:compile -->
        </dependency>
    </dependencies>

</project>

the dependency:tree looks like:

[INFO] ------------------------------------------------------------------------
[INFO] Building SO-44987444-child 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ SO-44987444-child ---
[INFO] igb.so:SO-44987444-child:jar:0.0.1-SNAPSHOT
[INFO] \- org.apache.commons:commons-text:jar:1.1:compile
[INFO]    \- org.apache.commons:commons-lang3:jar:3.5:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

If I add commons-lang3 as direct dependency with <scope>provided:

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.5</version>
            <scope>provided</scope>
        </dependency>

the dependency:tree looks like:

[INFO] ------------------------------------------------------------------------
[INFO] Building SO-44987444-child 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ SO-44987444-child ---
[INFO] igb.so:SO-44987444-child:jar:0.0.1-SNAPSHOT
[INFO] +- org.apache.commons:commons-text:jar:1.1:compile
[INFO] \- org.apache.commons:commons-lang3:jar:3.5:provided
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

Even if I add to the parent POM:

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

the dependency:tree results aren't any different.