views:

357

answers:

3

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?

+3  A: 

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.

Ken Liu
+1  A: 

netbeans links projects together by the local repository content, so mvn install is necessary in most scenarios.

mkleint
+2  A: 

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.

Pascal Thivent
Thanks. I sort of knew that about using `mvn package` instead of `mvn compile`, but thanks for the reminder. However, the "Maven Best Practices" link at wiki.netbeans.org was especially useful, so I'm marking this answer as accepted.
Daniel Pryden
@Daniel You're welcome. But the side note was more about `mvn package` vs `mvn jar:jar` :) Glad you found the link useful though.
Pascal Thivent