Make good use of these techniques to resolve Maven Jar package conflicts easily

Author: Platinum Poseidon

Original link: https://www.cnblogs.com/bryan31/p/13408479.html

Preface

Everyone must have encountered Maven's Jar package conflict problem in the project. The common scenarios are:

NoSuchMethodError and ClassNotFoundException are reported when running locally. Obviously there is this Jar package in the dependency. Why can't it run! ?

The project clearly defines a certain jar package version as 2.0.2, how can it become 2.5.0 after packaging! ?

The A project imported the xxx.jar package and ran well, and the B project also imported xxx.jar, and an error was reported. . Is there a problem with the B project or the xxx.jar package! ?

The local environment and the test environment are running well. When it comes to production, a bunch of NoSuchMethodErrors are reported. Is there a problem with my character or the production environment? ?

If such a problem is investigated by students who are not familiar with the maven dependency mechanism, it will be a headache.

Moreover, maven relies on poorly structured projects, and the risk of introducing new Jar packages is also huge. Smaller ones affect performance, while larger ones cause production release and runtime exceptions.

In fact, the root causes of the above problems all come from Maven's Jar package conflict and improper use of dependency delivery. In this article, I will analyze the following 3 contents:

  • Analysis of the principle of relying on delivery and the principle of causing Jar package conflict
  • Several simple techniques to locate conflicts and resolve Jar package conflicts
  • How to write a POM file with clean dependencies

Dependency transfer principle

Almost all Jar package conflicts are related to the dependency transfer principle, so let's first talk about the dependency transfer principle in Maven:

The shortest path first principle

If two Jar packages A and B are introduced, both of which transitively depend on the Jar package Z:

A -> X -> Y -> Z(2.5)

B -> X -> Z(2.0)

In fact, the version that finally took effect was Z (2.0). Because his path is shorter. If I reference the Z(3.0) package locally, the 3.0 version is effective. The same reason.

First declare the principle of priority

If the path length is the same, the one declared first is preferred.

A -> Z(3.0)

B -> Z(2.5)

Here, A is the first to declare, so the passed Z chooses to use version 3.0.

The principle of Jar package conflict

Suppose our project relies on two Jar packages, A and B. And A and B each have the following transitive dependencies

A -> X -> Z(2.0)

B -> X -> Y -> Z(2.5)

Then the Z package conflicts in the final system, and the two versions of 2.0 and 2.5 conflict. But only one version of the Z package is dependent on the classpath. According to the shortest path first principle of transitive dependency , the final dependency should be version 2.0.

If the new method in the 2.5 version of the Z package is used in the Y package, when this logic is run. Will report NoSuchMethodError. Because it originally relied on version 2.5, but because of the Jar package conflict, Maven chose version 2.0, and there was no new method in version 2.0, which caused an error.

But it should be noted that not all conflicts will cause abnormal operation. On the contrary, most of the company's projects will have some Jar package conflicts, but it does not cause runtime problems.

This is because many Jar packages that are transitively dependent, whether it is version 2.0 or version 2.5, can run.

Only the higher version of the Jar package is not backward compatible, or some new APIs that are not available in the lower version may cause this problem

Positioning conflict

IDEA provides a maven dependency analysis artifact: Maven Helper

Make good use of these techniques to resolve Maven Jar package conflicts easily

 

Use this plugin to display all the dependency trees and conflicts in the project.

Make good use of these techniques to resolve Maven Jar package conflicts easily

 

The part highlighted in red here indicates that the Jar package has a conflict. Select this jar package, you can see the source of the conflict between the two versions.

The example in the above figure shows that the Jar package of cruiser-client has two transitive dependencies, which are version 2.5.0 and version 4.0.1. The description of the conflict is:

omitted for conflict with 2.5.0. Omitted for conflict with 2.5.0

The specific level is also clear on the right, so maven finally chose version 2.5.0 based on the shortest path first principle , and version 4.0.1 was ignored.

At this time, some students will ask: I can use Maven Helper to locate the local environment, what about the pre-production or production environment. Without IDEA, how to locate the details of the conflict?

You can use the mvn command to solve:

mvn dependency:tree -Dverbose

Do not omit the -Dverbose parameter here, otherwise the ignored packages will not be displayed

Make good use of these techniques to resolve Maven Jar package conflicts easily

 

In fact, the mvn command line is just as easy to use. Very clear.

Several practical techniques for solving Jar package conflicts

Exclusion

Still the above example, now 2.5.0 is effective, if you want to take effect 4.0.1. Just click exclude on 2.5.0.

Make good use of these techniques to resolve Maven Jar package conflicts easily

 

Version locking

If many dependencies are passed Jar package A, many versions are involved, but you only want to specify one version. It is too cumbersome to exclude one by one by the method of exclusion, and the exclude will be reflected in the pom file. If too many, it will also affect the cleanliness of the code and the reading experience.

At this time, you need to use the version locking method

What is version locking? A company’s project generally has a parent pom. You only need to specify which version you want to specify in the parent POM of your project (of course, it can also be defined in this project) as follows: (Or take the previous example, specify version 4.0.1)

<dependencyManagement>
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-client</artifactId>
        <version>4.0.1</version>
    </dependency>
</dependencyManagement>

The locked version method can break the two principles of dependency transfer, with the highest priority

After the version is locked, the dependency tree is:

Make good use of these techniques to resolve Maven Jar package conflicts easily

 

They are all unified to 4.0.1. There is an advantage to locking the version: version locking does not exclude the Jar package, and it displays all the inconsistent Jar packages into a unified version, which is more friendly when reading the code. Don't have to endure a lot of exclude tags.

How to write a POM file with clean dependencies

I am a person with mild code cleanliness, so even the dependencies of the pom file want to be clean and tidy. How to write a clean POM, the author believes that there are several tips to pay attention to:

  • Try to define <dependencyManagement> in the parent POM to manage some dependent versions of this project, so that certain conflicts can be resolved to a large extent
  • If it is a Jar package provided to others to rely on, try not to pass on unnecessary Jar packages as much as possible
  • Use the mvn dependency:analyze-only command to detect the dependencies that are declared but not used. If some of them are declared by yourself, then try to remove them
  • Use the mvn dependency:analyze-duplicate command to analyze the repeatedly defined dependencies and clean up those repeatedly defined dependencies

At last

In fact, there must be a lot of dependencies on huge projects. But no matter how complicated the dependency is, don't be afraid to see it. With just a few principles and careful analysis, all dependencies are traceable.

If these transitive dependencies are well managed, your maintenance costs can be greatly reduced. If you don't manage well, each of these wild children may be the fuse for the next NoSuchMethodError.

Guess you like

Origin blog.csdn.net/GYHYCX/article/details/108783867