OK, I thought I understood how to use Maven...
I have a master project M
which has sub-projects A
, B
, and C
. C
contains some common functionality (interfaces mainly) which is needed by A
and B
. I can run mvn compile jar:jar
from the project root directory (the M
directory) and get JAR files A.jar
, B.jar
, and C.jar
. (The versions for all these artifacts are currently 2.0-SNAPSHOT
.)
The master pom.xml
file in the M
directory lists C
under its <dependencyManagement>
tag, so that A
and B
can reference C
by just including a reference, like so:
<dependency>
<groupId>my.project</groupId>
<artifactId>C</artifactId>
</dependency>
So far, so good. I can run mvn compile
from the command line and everything works fine. But when I open the project in NetBeans, it complains with the problem: "Some dependency artifacts are not in the local repository", and it says the missing artifact is C
. Likewise from the command line, if I change into the A
or B
directories and try to run mvn compile
I get "Build Error: Failed to resolve artifact."
I expect I could manually go to where my C.jar
was built and run mvn install:install-file
, but I'd rather find a solution that enables me to just work directly in NetBeans (and/or in Eclipse using m2eclipse).
What am I doing wrong?
Because modules within a multi-module build can depend on each other, it is important that the reactor sorts all the projects in a way that guarantees any project is built before it is required. The following relationships are honoured when sorting projects: a project dependency on another module in the build.
Right-click the utility project, and select Maven>Add Dependency. Type a dependency name in the Enter groupID… field (e.g., commons-logging) to search for a dependency. Select the dependency, and click OK.
Maven relies on the concept of binary dependencies and resolves them through the local repository. In other words, you need to "install" packages in your local repository if you have dependencies between them, compiling and packaging code is not enough. And to do so, you need to run install
(that will install the package into the local repository, for use as a dependency in other projects locally).
Side note: you shouldn't invoke mvn compile jar:jar
but prefer mvn package
. First, running the package
phase will trigger all the phases before package
(including compile
) and package
itself. Second, running package
will invoke jar:jar
, or war:war
, etc depending on the <packaging>
value of the project (check the introduction to the lifecycle for more details on this). That's one of the big strength of Maven: you don't need to know if the project is a JAR, a WAR, an EJB, etc and to run the appropriate goal to package it. Just run the standardized package
phase and Maven will do the job (using the default goals bindings).
That was for the Maven theoretical part. Inside IDEs, things might be slightly different to make working with Maven more convenient. IDEs may use project dependencies (i.e. dependencies on code inside the IDE) instead of binary dependencies so that changes made in one project are made visible in other modules without having to run mvn install
. This is the case of Eclipse + M2Eclipse. And this applies also to NetBeans under the following condition (see Dependency Management):
Hint: If you open a project that other projects depend on, the icon in other projects changes to a "maven project" icon to denote that the IDE knows about link between the projects. However such a link is only established when the groupId, artifactId and version all match in the dependency and project declaration. Frequently occurring problem is that you change an API signature in your library project, but the application is not picking up. Often it's caused by the fact that the application is using an older version of the library artifact. The artifact icon can help you track down these problems.
You need to run mvn install
instead of mvn compile
. The install
goal will copy the built jar into the local repository after compiling and packaging it. If you only run compile, it will only compile the class files into the target
directory and not make them available to other projects.
In Eclipse, if you import a pom from the top level, it will import the subprojects into separate Eclipse projects and set up the dependencies of related projects then set up each project's classpath to depend on others. I'm not familiar with Netbeans but I am pretty sure there is some way to do the same thing.
netbeans links projects together by the local repository content, so mvn install is necessary in most scenarios.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With