5

Given a very simple Maven project with a single pom-file containing a single dependency:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>maven-test</artifactId>
  <version>1.0-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>org.apache.cxf.xjc-utils</groupId>
      <artifactId>cxf-xjc-runtime</artifactId>
      <version>3.3.0</version>
    </dependency>
  </dependencies>

</project>

When running mvn dependency:tree different results are given depending on Java version.

With Java 8:

[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------------< org.example:maven-test >-----------------------
[INFO] Building maven-test 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ maven-test ---
[INFO] org.example:maven-test:jar:1.0-SNAPSHOT
[INFO] \- org.apache.cxf.xjc-utils:cxf-xjc-runtime:jar:3.3.0:compile
[INFO]    \- jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.2:compile
[INFO]       \- jakarta.activation:jakarta.activation-api:jar:1.2.1:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.982 s
[INFO] Finished at: 2020-06-22T15:05:56+02:00
[INFO] ------------------------------------------------------------------------

With Java 11:

[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------------< org.example:maven-test >-----------------------
[INFO] Building maven-test 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ maven-test ---
[INFO] org.example:maven-test:jar:1.0-SNAPSHOT
[INFO] \- org.apache.cxf.xjc-utils:cxf-xjc-runtime:jar:3.3.0:compile
[INFO]    +- jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.2:compile
[INFO]    |  \- jakarta.activation:jakarta.activation-api:jar:1.2.1:compile
[INFO]    +- javax.annotation:javax.annotation-api:jar:1.3.1:compile           <-- This and below only with Java 11
[INFO]    +- javax.xml.ws:jaxws-api:jar:2.3.0:compile
[INFO]    |  +- javax.xml.bind:jaxb-api:jar:2.3.0:compile
[INFO]    |  \- javax.xml.soap:javax.xml.soap-api:jar:1.4.0:compile
[INFO]    \- javax.activation:activation:jar:1.1.1:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.261 s
[INFO] Finished at: 2020-06-22T15:05:51+02:00
[INFO] ------------------------------------------------------------------------

I would have expected the trees to be the same under the two Java versions.

Maven version is 3.6.0.

Why do the resolved dependencies differ between the Java versions?

Magnilex
  • 11,584
  • 9
  • 62
  • 84
  • 4
    Quite possibly because `+- javax.annotation:javax.annotation-api`, `+- javax.xml.ws:jaxws-api` and `\- javax.activation:activation` are no more a part of the JDK in 11! – Naman Jun 22 '20 at 14:05
  • @Naman The classes for the two dependencies you are mentioning are in the _rt.jar_ of Java 8, and sure, they have been removed with Java 11. Is Maven smart enough to "parse" the _rt.jar_ and exclude those dependencies? This would explain the behaviour. – Magnilex Jun 22 '20 at 14:15
  • @Naman I don't think a sample project is needed. The pom file is the one and only file and can easily be copy-pasted. – Magnilex Jun 22 '20 at 14:15
  • @Magnilex yeah, makes sense..trying it out. – Naman Jun 22 '20 at 14:21
  • 1
    Dependency tree mojo trims lower level dependencies if the dependency is already present higher in the tree. – Amit kumar Jun 22 '20 at 14:39
  • @Amitkumar I suggest you make an answer of your comment, so this question can be marked as resolved. – Basil Bourque Jun 22 '20 at 15:29
  • 1
    Sure @BasilBourque. Done! – Amit kumar Jun 22 '20 at 16:17

2 Answers2

3

The reason why the dependency tree differs between the Java versions is found in the dependency:

<dependency>
  <groupId>org.apache.cxf.xjc-utils</groupId>
  <artifactId>cxf-xjc-runtime</artifactId>
  <version>3.3.0</version>
</dependency>

This in turn has xjc-utils as its parent:

<parent>
    <groupId>org.apache.cxf.xjc-utils</groupId>
    <artifactId>xjc-utils</artifactId>
    <version>3.3.0</version>
</parent>

In this POM file, we find the dependencies that are excluded when building with Java 8:

<profile>
    <id>java9-plus</id>
    <activation>
        <jdk>[9,)</jdk>
    </activation>
    <dependencies>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.ws</groupId>
            <artifactId>jaxws-api</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
    </dependencies>
 </profile>

This pretty much speacks for itself, the dependencies will only be included if Java 9 or above is used, as stated in this range: <jdk>[9,)</jdk>. The documentation for the tag states:

Specifies that this profile will be activated when a matching JDK is detected. For example, 1.4 only activates on JDKs versioned 1.4, while !1.4 matches any JDK that is not version 1.4.

This activation profile makes sure these dependencies are included when Java 11 is used:

[INFO]    +- javax.annotation:javax.annotation-api:jar:1.3.1:compile
[INFO]    +- javax.xml.ws:jaxws-api:jar:2.3.0:compile
[INFO]    |  +- javax.xml.bind:jaxb-api:jar:2.3.0:compile
[INFO]    |  \- javax.xml.soap:javax.xml.soap-api:jar:1.4.0:compile
[INFO]    \- javax.activation:activation:jar:1.1.1:compile

More info about activation can be found in the official Maven documentation:

Activations are the key of a profile. The power of a profile comes from its ability to modify the basic POM only under certain circumstances. Those circumstances are specified via an activation element.

Together with another example of activation based on Java version:

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      https://maven.apache.org/xsd/maven-4.0.0.xsd">
  ...
  <profiles>
    <profile>
      <id>test</id>
      <activation>
        <activeByDefault>false</activeByDefault>
        <jdk>1.5</jdk>
        <os>
          <name>Windows XP</name>
          <family>Windows</family>
          <arch>x86</arch>
          <version>5.1.2600</version>
        </os>
        <property>
          <name>sparrow-type</name>
          <value>African</value>
        </property>
        <file>
          <exists>${basedir}/file2.properties</exists>
          <missing>${basedir}/file1.properties</missing>
        </file>
      </activation>
      ...
    </profile>
  </profiles>
</project>
Magnilex
  • 11,584
  • 9
  • 62
  • 84
2

Dependency tree mojo trims lower level dependencies if the dependency is already present higher in the tree.

We can use verbose flag (-Dverbose) to show the excluded dependencies.

To find a specific artifact : mvn dependency:tree -Dverbose -Dincludes=[groupId]:[artifactId]:[type]:[version]

Please visit Maven Dependency Tree to know more.

Amit kumar
  • 2,169
  • 10
  • 25
  • 36
  • 1
    Good, but a few more details would be nice. Maybe a citation to do documentation. – Basil Bourque Jun 22 '20 at 20:04
  • Added details for clarification. Please let me know if something isn't clear/needs to be updated. – Amit kumar Jun 22 '20 at 20:23
  • There are not any other dependencies present in the pom. There is however a difference in that the source for `javax.annotation-api` and `activation` can be found in the Java 8 JDK, but not in the Java 11 JDK. So I guess what must be happening is that Maven detects this and excludes the dependencies. How is this done? Any sources? – Magnilex Jun 23 '20 at 05:42
  • @BasilBourque Although this answer is indeed true, it is not the answer to my question. The pom file has one single dependency and the reason for the tree difference was actually because of activation profiles in the single dependency. See my answer: https://stackoverflow.com/a/62553245/1421925. Just thought I'd ping you as well because you were part of the discussion for this answer. – Magnilex Jun 24 '20 at 10:49