maven dependency conflict handling

I don't know if you have encountered problems such as "NoSuchMethodError" or "ClassNotFoundException" when using Maven, or even Java classes where these problems occur you haven't heard of. To figure out the reason for this, we have to learn Maven's handling mechanism for dependency conflicts.

 

Maven uses a "nearest wins strategy" to handle dependency conflicts, that is, if a project ends up depending on multiple versions of the same artifact, the version closest to the project in the dependency tree will be used. Let's look at a practical example.

 

Please download the github source code of this article: https://github.com/davenkin/maven-dependency-conflict-demo

 

We have a web application resolve-web, which depends on project-A and project-B, project-A depends on version 1.0 of project-common and calls the sayHello() method in it. project-B depends on project-C, which in turn depends on version 2.0 of project-common and calls the sayGoodBye() method in it. The 1.0 and 2.0 versions of project-common are different. 1.0 contains the sayHello() method, while 2.0 contains the sayHello() and sayGoodBye() methods. The dependencies of the entire project are as follows:

 


 

According to Maven's transitive dependency mechanism, resolve-web will depend on both versions 1.0 and 2.0 of project-common, which creates a dependency conflict. And according to the most recent winning strategy, Maven will choose the 1.0 version of project-common as the final dependency. This is different from Gradle, which by default will choose the latest version as the winning version. And for Maven, version 1.0 wins because version 1.0 of proejct-common is closer to resolve-web in the dependency tree than version 2.0. Execute "mvn dependency:tree -Dverbose" in resolve-web to see the dependencies of resolve-web:

 

copy code
[INFO] resolve-web:resolve-web:war:1.0-SNAPSHOT

[INFO] +- junit:junit:jar:3.8.1:test

[INFO] +- project-B:project-B:jar:1.0:compile

[INFO] |  \- project-C:project-C:jar:1.0:compile

[INFO] |     \- (project-common:project-commmon:jar:2.0:compile - omitted for conflict with 1.0)

[INFO] +- project-A:project-A:jar:1.0:compile

[INFO] |  \- project-common:project-commmon:jar:1.0:compile

[INFO] \- javax.servlet:servlet-api:jar:2.4:provided
copy code

 

 

As can be seen from the above, project-common:project-commmon:jar:2.0 is ignored. At this time, only the 1.0 version of project-common will be included in the war package of resolve-web, so the problem comes. Since version 1.0 of project-common does not include the sayGoodBye() method, which is required by project-C, a "NoSuchMethodError" will appear at runtime. (Please reproduce the error message according to the steps in the README.md in the github project of this article.)

 

For this problem caused by dependency conflicts, we have two solutions.

 

方法1:显式加入对project-common 2.0版本的依赖。先前的2.0版本不是离resolve-web远了点吗,那我们就直接将它作为resolve-web的依赖,这不就比1.0版本离resolve-web还近吗?在resove-web的pom.xml文件中直接加上对project-common 2.0 的依赖:

 

<dependency>       
   <groupId>project-common</groupId>      
   <artifactId>project-commmon</artifactId>  
   <version>2.0</version>   
</dependency>  

 

方法2:resolve-web对project-A的dependency声明中,将project-common排除掉。在resolve-web的pom.xml文件中修改对project-A的dependency声明:

 

copy code
<dependency>  
          <groupId>project-A</groupId>  
          <artifactId>project-A</artifactId>  
          <version>1.0</version>  
          <exclusions>  
              <exclusion>  
                  <groupId>project-common</groupId>  
                  <artifactId>project-commmon</artifactId>  
              </exclusion>  
          </exclusions>  
</dependency>  
copy code

 

此时再在resolve-web中执行"mvn dependency:tree -Dverbose",结果如下:

 

copy code
......

[INFO] resolve-web:resolve-web:war:1.0-SNAPSHOT

[INFO] +- junit:junit:jar:3.8.1:test

[INFO] +- project-B:project-B:jar:1.0:compile

[INFO] |  \- project-C:project-C:jar:1.0:compile

[INFO] |     \- project-common:project-commmon:jar:2.0:compile

[INFO] +- project-A:project-A:jar:1.0:compile

[INFO] \- javax.servlet:servlet-api:jar:2.4:provided

......
copy code

 

The 1.0 version of project-common is no longer included in the dependency tree at this time.

 

In addition, we can also declare the dependency on project-common as optional in project-A, optional means non-transitive. At this time, when project-A is referenced in resolve-web, Maven will not regard project-common as Transitive dependencies are added automatically, unless another project (such as project-B) declares a transitive dependency on project-common or we explicitly declare a dependency on project-common in resolve-web (method 1).

Reprinted from: https://www.cnblogs.com/davenkin/p/advanced-maven-resolve-dependencies-conflicts.html

 

optimization dependencies

can be summarized into three commands

mvn dependency:list

Indicates the list of dependencies, the maven eclipse plug-in has been implemented, there is a graphical display, in the dependencies page of pom.xml

mvn dependency:tree

Indicates the dependency list, the maven eclipse plug-in has been implemented, there is a graphical display, in the dependency hierarchy page of pom.xml

mvn dependency:analyze

Find dependencies that are not used but explicitly declared in compilation and testing

 

Reprinted from: https://blog.csdn.net/lastsweetop/article/details/8493475

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326069769&siteId=291194637