Maven Common Problems and Pitfalls

posted by Roberto Cortez on
tags:

Love it or hate it (and a lot of people seem to hate it), Maven is a widely used tool by 64% of Java developers (source – Java Tools and Technologies Landscape for 2014).

Most experienced developers already got their share of Maven headaches. Usually in the hard way, banging with their head into a brick wall. Unfortunately, I feel that new developers are going through the same hard learning process.

Looking into the main Java conferences around the world, you cannot find any Maven related sessions that guide you through the fundamentals. Maybe the community assumes that you should already know them, like the Java language itself. Still, recycling this knowledge could be a win-win situation for everyone. How much time do you or your teammates waste with not knowing how to deal with Maven particularities?

If you are reading this, I’m also going to assume that you grasp Maven basics. If not, have a look into the following articles:

There a lot of other articles. I see no value in adding my own, repeating the same stuff, but if I feel the need I may write one. Let me know if you support it!

Anyway, I think I can add some value by pointing out the main issues that teams came across when using Maven, explain them and how to fix them.

Why is this jar in my build?

Due to Maven transitive dependencies mechanism, the graph of included libraries can quickly grow quite large.

If you see something in your classpath, and you didn’t put it there, most likely is because of a transitive dependency. You might need it or maybe not. Maybe the part of the code of the library you’re using doest not required all those extra jars. It feels like a gamble here, but you can have a rough idea if you use mvn dependency:analyze. This command will tell you which dependencies are actually in use by your project.

I mostly do trial and error here, exclude what I think that I don’t need and run the code to see if everything is OK. Unfortunately, this command doesn’t go so far to tell you if the transitive dependencies are really needed for the dependencies that you are using. Hey, if someone knows a better way, let me know!

I can’t see my changes!

This can happen because of multiple reasons. Let’s look into the most common:

Dependencies are not built in the local repository

You may have Module A and Module B. Module B has a dependency to Module A. The changes you made to Module B are not visible in Module A.

This happens, because Maven look into it’s own local jar repository to include in the classpath. If you make any changes, you need to place a copy of new jar into the local repository. You do that by running mvn install in the changed project.

Dependency version is not correct

This can be so simply as to change the version of the dependency that you are using, or a real pain to figure it out. When Maven performs the dependency lookup, it uses the rule Nearest Definition First. This means that the version used will be the closest one to your project in the tree of dependencies. Confused? So do I. Let’s try an example.

You want to use dependency Dv1 in your project A, but you’re getting Dv2, and you have the following dependency tree:

A -> B -> C -> Dv1

A -> E -> Dv2

Which dependency of D is included? Dv1 or Dv2? In the case Dv2 because of the Nearest Definition First rule. If two dependency versions are at the same depth in the dependency tree, it’s the order in the declaration that counts.

To fix this problem you could explicitly add a dependency to Dv1 in A to force the use of Dv1 or just exclude Dv2.

If you use the command mvn dependency:tree it will output a tree will all the dependencies and versions for the project. This is very helpful to debug these kind of problems.

Remote repository has overwritten your changes

It’s usual for companies to have an internal Maven repository, to cache artifacts, store releases or serve the latest changes of the project you are working on. This works great most of the time, but when you’re working with SNAPSHOT versions, Maven is always trying to pick up the latest changes to that dependency.

Now, you are happily working on your Project B changes which has a dependency to Project A. You build everything locally and proceed to integrate the changes in Project A. Someone or something, upload a new SNAPSHOT version of Project B. Remember, your changes are not visible yet, since you have everything locally and did not commit to VCS yet. The next build you make of Project A it’s going to pick the Project B from the company repository and not the one in your local repository.

The jar is not included in the distribution!

To add a little more confusion, let’s talk about scopes. Maven has four scopes: compile, provided, runtime and test. Each dependency has a scope and the scope defines a different classpath for your application.

If you are missing something, and assuming that you have the dependency defined correctly, most likely the problem is in the scope. Use the compile scope to be on the safe side (which is the default). The commands mvn dependency:analyze and mvn dependency:tree can also help you here.

The artifact was not found!

Ahh, the dreaded “Could not resolve dependencies … Could not find artifact”. This is like the Java NPE! There are many reasons for why this happens. A few more evident that others, but a pain to debug anyway. I usually follow this checklist to try to fix the problem:

  • Check that the dependency is defined correctly
  • Check if you are pointing to the correct remote repositories that store the dependency
  • Check if the remote repository actually holds the dependency!
  • Check if you have the most recent pom.xml files
  • Check if the jar is corrupted
  • Check if the company repository is caching the internet repositories and didn’t not issue a request to get the new libraries
  • Check if the dependency definition is being overridden by something. Use mvn help:effective-pom for the actual maven setting building the project
  • Don’t use -o

Conclusion

Maven is not a perfect tool, but if you learn a few of tricks it will help you and save time debugging build problems. There are other that fix a few of these problems, but I don’t have enough knowledge to be able to voice my opinion about them.

Anyway, a big chuck of projects use Maven as a build tool and I believe that developers should know about their build tool to be able to perform better in their everyday work. Hopefully this post can be useful to you.

Feel free to post any other problem not covered here. Unfortunately, Maven sometimes seems a box full of surprises.

One last advice: Never trust the IDE! If it works on the command-line then it’s an IDE problem!

Leave a reply

Your email address will not be published.

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>