In late March 2020 I ran a quiz on Maven Dependency Resolution which turned out to be an eye opener for some people (including myself!). You can read the whole questionnaire, results, and analysis here. One of the surprising results was found in the very first question, a rather innocuous one but it resulted in a major stumbling block for 2/3 of respondents! Here’s the question
What’s surprising is that only 36% people chose the correct answer and a similar percentage chose the “Build error” option because clearly duplicate dependencies ought to cause a build error, right?
Wrong! Maven does output a warning but continues the build, by selecting the last dependency. You may be thinking “of course! version 28.2-jre is bigger than 27.0-jre, thus it’s the selected version”. Hmm, I wouldn’t bet on it. Let’s invert the definitions so that 28.2-jre is first and 27.0-jre is last, then invoke
That’s right, the last version was selected once again and it happens to be 27.0-jre, what gives?! And that was exactly the reaction of quite a good number of respondents. This got me thinking, if so many thought that either of these two POM files should result on a build error it might be because additional tool support is aware of such bad practice. Let’s ask the IDEs!
In the gauntlet we have:
- Eclipse [Version: 2020-03 (4.15.0) Build id: 20200313-1211]
- VS.Code [Version 1.44.2] with “Maven for Java” 0.21.2 and “Java Dependency Viewer” 0.9.0
- Apache NetBeans IDE 11.3
- IntellliJ IDEA Ultimate 2019.3
Let’s begin with Eclipse. Creating a simple Maven project with Eclipse is a straight forward operation by following the project creation wizzard. Adding the two duplicate dependencies to the POM file results in a view similar to this one
Let’s see what we have here. No indication on the editor that the POM file contains duplicate dependencies. No warnings nor errors to be found in the Problems view. If we switch tabs to “Dependencies” we get a view of the
<dependencies> block as it is, thus we can’t actually see the resolved version. But if we switch to the “Effective POM” tab then we have a different result as you can see in the next picture with manual highlight on the
Of course, if we execute
mvn verify on the console we get the same warning as before, good. Now, there might be a way to have a resolved dependencies view but I must confess I’m not an Eclipse user and I didn’t bother looking too much into it, why? Because every other IDE that follows offers you that view in an intuitive manner. Let’s move on to VS.Code.
Opposed to Eclipse, for VS.Code I had to install 2 additional extensions to get Maven support, after all VS.Code is a general purpose tool (not really Java nor Maven specific) like Eclipse is. Loading up the same POM file on VS.Code results in the following view
Here we can see that the editor also has no indications on duplicate dependencies but the resolved list of dependencies does show the correct answer. Executing
mvn verify from the IDE’s terminal displays the same warning as before, after all, that’s regular Maven thus no change in behavior should be observed. Now on to NetBeans, which many claim it to be the best IDE for Maven. We shall see.
Upon downloading NetBeans you’re greeted with additional download dialogs. OK, I suppose that’s natural on a computer that never had any NetBeans preferences nor previous installations, a bit bothersome but it gets the job done. Opening the same POM file results in this view
Aha! The first indication found on the editor that something is odd with this POM file, hurray! Executing
mvn verify also results in the same warning, hurray! Now looking at the dependencies view we see that the resolved version for Guava is … the wrong one. What?! Ooookaaay, let’s see what the last IDE in the group has to say, onward with IntelliJ IDEA.
Importing the project as a Maven project is as simple as the other IDEs, and we get the following view once the project has been processed
The editor does show some sort of problem with the duplicate dependencies, however I must say that having an icon on the line gutter like NetBeans did might be a better choice (if there is such option it’s not enabled by default). At least IntelliJ marks both definitions as problematic. The resolved dependencies view shows the correct dependency, great! Finally executing
mvn verify results in the same warning as with the other IDEs, as expected.
OK, so none of the IDEs flag this POM as really problematic nor cause some sort of build error; how come 35% people though the POM should cause a build error? The next option would be that a good number of the respondents of that 35% have configured the enforcer-maven-plugin and the <banDuplicatePomDependencyVersions> enforcer rule (either in direct knowledge or via a parent POM) thus they would have seen an error on a problematic build before, however based on this very unscientific Twitter poll, completely unrelated to the quiz, makes me think that might not have been the case
Do you apply the maven-enforcer-plugin on your projects?
— Andres Almiray (@aalmiray) March 27, 2020
What happens then if we configure that rule in the POM file? Let’s see the result
Finally! A broken build! Yay?
Here’s the deal: many (including myself) think that Maven is a simple tool (it’s just XML after all, right?) but at the same time it’s supposed to do a lot of things on its own. Well it so happens that Maven has more moving parts and features, one of those is a rich plugin ecosystem. The enforcer plugin is a must if you really want to get your builds in shape. There are many rules to choose from, the one shown here it’s just the tip of the iceberg.
Keep on coding!