Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does resolved dependencies differ between Java 8 and Java 11?

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?

like image 695
Magnilex Avatar asked Jun 22 '20 14:06

Magnilex


People also ask

What changed from Java 8 to Java 11?

The list of new features introduced in the Java version 11: The most significant changes made to Java version 11 are as follows: As a preview, ZGC or Z Garbage Collector, a new, experimental garbage collector was added. The new toArray method was added to the Collections interface in Java 11.

Is Java 11 fully backward compatible with Java 8?

Java 11 is backwards compatible with Java 8. So you can swiftly change from Java 8 to 11.

Does Maven work with Java 11?

Chances are that it just runs fine with Java 11. Hint: You can speed up multi-module Maven projects by using parallel builds, e.g. mvn -T 4 compile compiles all modules in parallel on 4 CPU cores.

What is the difference between Java 8 and Java 11?

License: Java 8 and java 11 are released under different licenses. Long Term: Java 8 is a Long Term Support release, while java 11 is not. JDK: The Oracle JDK for Java 8 will be available until at least January 2020, but the Oracle JDK for java 11 will only be available until at least June 2022.

What is-release 8 in Java 8?

The -release 8 is an example that we need to compile at a Java 8 level. It is one of the features which is added in Java 11. Multi-jar provides a way to still the code with the latest features of Java 11 while maintaining support and functionality for Java 8 clients. In Java 10, the var keyword was introduced, which improved in Java 11.

Is JAXB no longer part of the JDK?

As most of us know that Java has been modularized from Java 9 onwards and there are multiple API and modules which are no longer part of JDK and needs to be added explicitly if we want to use them. JAXB, JavaFX and JAX-WS are few of the modules which were deprecated in Java 9 and removed in Java 11.

What are the new features of Java 11?

Java 11 comes with new features to provide more functionality. Below are the features which are added in the four and a half years in between these two versions. The Modularity feature is not available in Java 8. It is one of the biggest changes that have been added in Java 9.


2 Answers

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>
like image 197
Magnilex Avatar answered Oct 13 '22 20:10

Magnilex


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.

like image 36
Amit kumar Avatar answered Oct 13 '22 18:10

Amit kumar