Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resolve dependencies between modules within multi-module project?

Tags:

After working with Maven for a while, I am thrilled by the many features that Maven brings into the build architecture, particularly the dependency management. However, I have run into one issue again and again - how Maven resolves dependencies between multi-module projects. I am wondering if this is the big flaw of the current Maven implementation and/or if there is any satisfactory workaround.

Let's say I have a multi-module Maven project. The Parent pom contains three modules -- moduleA (jar), moduleB (jar), and moduleC(war). B depends on A and C depends on B. Simple enough? Now that I want to run the mvn dependency:go-offline at the parent project, which is supposed to resolve all the dependencies and bring them into the local .m2 directory. It fails because Maven complains that it cannot solve dependency for moduleA when it is acting on moduleB. Because all these modules belong to one groupId, I even try to use -DexcludeGroupIds=x.y.z to exclude these module dependencies, but it still fails at the same point.

I understand why Maven is complaining - moduleA is not built yet and thus there is no moduleA:jar artifact in my local or internal repository when go-offline goal is executed. But IMHO the plugin should treat these inter-module dependencies differently. In this case, it should simply ignore it. One might argues that I can simply do mvn clean install, which will install moduleA:jar into the local repository. After that, running mvn dependency:go-offline will work for sure. But that workaround defeats the purpose of this go-offline goal. This plugin allows us to resolve and pull dependencies into our local repository without building the whole project. I used dependency:copy-dependencies goal in another case and it has the same issue.

I also ran into similar issue in other scenarios: "mvn clean generate-source" could not resolve dependencies. When I ran mvn clean compile, everything works fine, but when I ran mvn clean generate-source, it fails because Maven cannot resolve inter-module dependency. In that case, the was caused by @requiresDependencyResolution in the antrun plugin.

Since both antrun plugin and dependency plugin are very popular in the Maven world, I am sure I am not the only one who have run into this issue. Anyone finds any solution/workaround?

like image 857
Lan Avatar asked Feb 04 '13 19:02

Lan


People also ask

Can two modules depend on each other?

In software engineering, a circular dependency is a relation between two or more modules which either directly or indirectly depend on each other to function properly. Such modules are also known as mutually recursive.

CAN modules have dependencies?

Dependency on libraries. If a module or mediation module needs to use resources from a library or if a library needs to use resources from another library, you have to open the module or library with the dependency editor and add a dependency on the required library.

What is the use of multi-module project in Maven?

A multi-module project is built from an aggregator POM that manages a group of submodules. In most cases, the aggregator is located in the project's root directory and must have packaging of type pom. The submodules are regular Maven projects, and they can be built separately or through the aggregator POM.

How can I add an existing Maven project to another Maven project as a module?

Just do a regular "Import existing maven project into workspace" to get this done. Show activity on this post. If you use M2e with Eclipse you do not need to do that, because Eclipse resolves dependencies across the workspace. You just need to have the two projects open and your dependencies declared correctly.


1 Answers

Maven has the concept of a "reactor" where artifacts that have been built in a single run (e.g. maven package) are available for dependency resolution during the build. For example, if your dependency graph yields the build order moduleA moduleB moduleC, and you do mvn package, Maven will build moduleA, package its artifact and add it to the reactor, then build moduleB, package it and add it to the reactor, then the same for moduleC. This means moduleB has access to moduleA's artifact for dependency resolution, and moduleC has access to moduleA and moduleB. This only works if artifacts are actually built, i.e. when you run the package goal.

The problem is that when you don't run the package goal because you're not interested in the artifacts (as for your dependency:go-offline example), artifacts for modules that have been processed don't get built and thus not added to the reactor. I find this annoying as well; I think Maven should look at the POM files in its list of modules to build and look there as well; but it doesn't.

In short, the solution to your problem is to do mvn package dependency:go-offline . This will not install artifacts in your local repository (which I believe is very bad practice) but it will put them in the reactor for the duration of the build, meaning that Maven will be able to resolve dependencies from your moduleB to the moduleA that has already been built. The downside is every module will be tested and packaged, which is a lot of work when all you wanted is to do dependency:go-offline.

Either way, hope this helps.

like image 148
Frans Avatar answered Sep 29 '22 23:09

Frans