Hi everyone! In this post I’m gonna show you why you have to check your dependency versions in your maven project and how you can do it.
Problem
Some time ago I got the bug at work that forced me to spend some hours to understand what's going on. And when I finally realised the cause I was surprised, the bug was because we had dynamic changing version for some dependency in our maven project. This dependency had the LATEST
version.
And I had a thought: Why we don’t have step in our ci pipeline to check such issues? And Why I haven't even heard about such tool?
So In that moment I decided to find or create maven plugin to fail our build if we have dynamic changing versions of dependencies. Such as LATEST
, RELEASE
or something like [1.5,)
When could such a case happen? Just accidentially. Or by copy pasting the code. Of course it should be detected in code review. But it could easilly miss in the fast development step.
I can't imagine the situation when such dynamic changing versions could be helpful. If you have one, share this in the comments.
Why maven?
There are not only maven to build java projects. Gradle is on the way to mass adoption. And some things we can make really easily with Gradle comparing to maven. But maven is still the most popular one. Specially for big and old enterprise companies. And when I got this problem we used maven for our projects. So it is why I'm showing how to solve it using maven.
Research
I started to search existing plugins. And surprising for me I didn’t find them.
The most closest to what I wanted was requireUpperBoundDeps rule.
But the <version>LATEST</version>
not a problem for a verification of this plugin rule. The plugin just verify dependency has the latest version that exists.
If 1.5
version of dependecy available and you run mvn install
with this plugin, project’ll be successfully builded. But If you set 1.4
explicitly, build’ll failed.
So it totally is not what I wanted to achieve.
And also I found exactly what I was looking for but for plugins. It is a requirePluginVersions rule.
Idea
Idea is simple. Let's have regexes about incorrect dependencies versions to match. And we will just check every dependency’s version. And if it matches with any regex we’ll throw the exception to fail build.
Implementation
To implement this idea we can make maven plugin from scratch. Maven has ability to make it from maven-core library. You can find good tutorial how to make it here.
But there much more actions to make simple strings check by regex. Do we have more simple way to do it or not?
The answer is yes. We have a maven enforcer plugin where we can add custom rules.
You can find instructions how to do this here
The following code is just enough:
MavenProject mavenProject = EnforcerRuleUtils.getMavenProject(helper);
List<Dependency> dependencies = mavenProject.getDependencies();
for (Dependency d : dependencies) {
String version = d.getVersion();
boolean isRestrictedVersion = restrictedVersionRegexes.stream().anyMatch(p -> p.matcher(version).find());
if (isRestrictedVersion || restrictedVersionStrings.contains(version)) {
throw new EnforcerRuleException(String.format("Dependency %s has restricted version %s.", d, version));
}
}
Using relates to surface plugin. You can add specific dependency and custom rule to use this functionality.
It looks like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0</version>
<dependencies>
<dependency>
<groupId>io.github.DaniilRoman</groupId>
<artifactId>dependency_restricted_version_checker</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>enforce</id>
<configuration>
<rules>
<myCustomRule implementation="io.github.daniilroman.versionchecker.RestrictDependencyVersionRule">
<enabled>true</enabled>
</myCustomRule>
</rules>
</configuration>
<goals>
<goal>enforce</goal>
</goals>
</execution>
</executions>
</plugin>
And that's all. Now when you run mvn install
it run enforcer plugin that run this custom rule.
As a result if your junior developer add such a dangerous change
For example:
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
and you miss this in code review stage. Such checker’ll help you to protect the codebase.
Summary
In this article we showed why checking dependency versions can helpful. How to implement it for maven using enforcer plugin and how to add it in your projects.
That's all for today, stay tuned and don’t forget to check your code.
P.S. You can find the whole code on GitHub
Top comments (1)
The most and important step in such situations is to check the build output because while using
LATEST
orRELEASE
for a dependency you will get a WARNING by Maven itself...