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

Most experienced developers have already had their share of Maven headaches. Usually in the hard way, banging 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 idiosyncrasies?

If you are reading this, I’m also going to assume that you grasp the basics of Maven. 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 the 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 doesn’t require all those extra jars. It feels like a gamble here, but you can get 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 go by trial and error here, excluding what I think I don’t need and running 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 for 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 as simple as changing the version of the dependency that you are using, or conversely, 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 am 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 toProject A. You build everything locally and proceed to integrate the changes inProject 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 theProject 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 andmvn dependency:tree can also help you here.

The artifact was not found!

Ah, 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. Usemvn 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 tricks of the trade, it will help you and save time debugging build problems. There are of course other ways to fix a few of these problems, but I don’t have enough knowledge  to voice my opinion about them.

Anyway, a big chunk 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 will be useful for you.

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

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

Common Maven Problems and Pitfalls

| Java Language| 2,195 views | 4 Comments
About The Author
- Freelancer. Passionate Java Developer.

4 Comments

  • Neil Bartlett
    Reply

    Why not just turn off transitive dependencies? What value do they add?

    If your own library directly depends on something in the transitive chain then it should just add it as a first-level dependency — by doing this you get control over the version that you build against.

    Otherwise, if you don’t depend on something, there is no need to put it on the classpath.

    • Arturo Tena
      Reply

      I guess the author was talking about some common library is needed for two of your direct dependencies. i.e. commons-*.jar is used by many projects. May be you don’t need commons directly, but you use two dependencies that do.

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=""> <s> <strike> <strong>