Can Maven automatically build a dependency that is not found? - maven

I have three separate projects I am working on (A, B, and C).
Project B and C rely on a jar that project A generates.
Does Maven have the ability to automatically build project A if the dependency is not found?
The answers I've found so far are indicative of making the other 2 projects modules (which I believe to mean repository layout and incorporate them into project A) and create a parent / child pom.
A just plain "no" was also one of my conclusions as well.
It seems as though if I make a module of project A in B and C, maven doesn't really like that. Can Maven see projects during build time that are outside of the scope of the current project? Sorry if that's a little wordy.

The scenario works fine if A, B and C are modules of a common container project.
From root pom.xml:
<modules>
<module>project-a</module>
<module>project-b</module>
<module>project-c</module>
</modules>
where "project-a" etc. are names of maven project folders inside the parent folder.
The parent project must have <packaging>pom</packaging> for this to work.
Then you can build the parent project and it will build all children in order, or you can use one of the advanced Maven reactor flags.
e.g. mvn clean install -pl project-b will only build project B.
For more info, execute mvn --help and read the multi modules chapter from the Maven By Example book.
But to this question:
Does Maven have the ability to automatically build project A if the
dependency is not found?
... the answer is always no. Maven fails if the dependency is not found, but it never decides which projects to build. You are in charge of which projects need building.

Related

How to run maven plugin for only root of multimodule project [duplicate]

I have maven multi-modules project. At the parent level, i have some java files. And in the parent pom.xml, at the package phase i do some stuff.
Usually, when i run mvn package at parent level, the package phase of parent pom will be run and all the modules will be packaged as well.
I am looking for a way that allow me to do these (when i run mvn package):
allow me to run only paren pom.xml (the script at the package phase), not the modules. This is the 1st priority.
allow me to run paren pom.xml and some particular modules (like module 1, module 2 BUT not module 3 , module 4).
Can i use profile for those issue?
Thanks.
While I agree with the fact that you may not have optimal project structure, the answer is that Maven 2.2.1 has an option "--non-recursive" which satisfies your first requirement:
-N,--non-recursive Do not recurse into sub-projects
So something like this:
mvn --non-recursive clean compile
Why do you want to have java code on the top level? In my opinion this is not a very good idea. Have your code in the subprojects and let the top-level project be responsible for holding the general information and configuration of the entire project.
If you have some base-library code in the top-level project now, you can put it in a sub-project and set up dependencies between the projects.
Take a look at Maven parent pom vs modules pom
The nature of your question indicates that your project structure may not be optimal.

Independently building Maven submodules

After being introduced to Maven in my most recent project, I've been experimenting with it for the past couple of weeks.
I currently have a multi-module project in my development environment. Project "A" and Project "B" are child modules of Project "root", with B having a dependency on A.
I am aware that I can build B independently by using mvn reactor:make... as outlined here. However, I'm curious as to why am I not allowed to build B from inside B's root folder.
To illustrate this, I first built A independently by running a clean install from within A's root directory. However, when I tried doing the same action from B's root directory, Maven reported an error as below -
Could not find artifact org.divesh.mavenrnd:root:pom:1.0 in central
It looks like Maven is not able to resolve the parent's POM file. Any thoughts on why this is happening? From my initial understanding of Maven multi-module projects, the main reason to split a project into sub modules is to share dependencies. This should not, however, prevent me from building a particular module independently from within its folder.
Thanks.
EDIT
Ran an mvn -N clean install to install only the root project's POM in the rep. After this, I was able to successfully build B after building and installing A. There is still one thing I'm not quite clear about -
Assuming I've installed the root project's POM in the repository, if I try to build A, does it refer to the parent root POM directly above it or the POM that is installed in the repository?
That's right. The error you mentioned tells you that maven cannot find parent's pom.
You have 2 options here:
First call mvn -N install in your root project directory to install parent pom to your local repository. Then you can go to B's directory and build the submodule.
Specify <relativePath> in your submodule pom. By default maven will look for parent pom only one level up the file system. If you have other directory structure in your project, you have to specify this option in order for maven to locate your parent pom.
Here's a sample:
<parent>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<relativePath>../../pom.xml</relativePath>
</parent>
You should use mvn -pl ProjectToBuild lifecycle like from the root of your tree:
mvn -pl module-b package
You shouldn't use mvn reactor:make anymore. Except you are using maven 2.0
If you wan't to be sure that everything is depending on module-b is build as well you should use:
mvn -amd -pl module -b package
The best is having a folder layout which represents the appropriate structure of your project and not using relativePath is necessary.

How can a maven project depend on another local maven project?

I'm having two maven project project/foo/pom.xml and project/bar/pom.xml. I have foo depend on bar, and I want that every timefoo/pom.xmlcompiles, it'll automatically compilebar`.
How can I do that with maven?
Update: I can tuck them both into a parent project, but then, what will I do if I want to run mvn jetty:run on a child project?
Option 1
Setup both builds in Jenkins, which can detect dependencies between projects
Automatic build chaining from module dependencies
Jenkins reads dependencies of your project from your POM, and if they are also built on
Jenkins, triggers are set up in such a way that a new build in one of those dependencies
will automatically start a new build of your project.
Option 2
If the two Maven projects are closely related (released together, sharing the same revision number) then perhaps they're really two modules of the same project?
If that is the case read the following document for guidelines on how to create a parent POM:
http://maven.apache.org/guides/introduction/introduction-to-the-pom.html
You can combine them into one project, with two modules.
An example project structure:
parent (pom)
|- foo (jar)
|- bar (jar)
In the parent pom:
<groupId>org.me</groupId>
<artifactId>parent-project</artifactId>
<packaging>pom</packaging>
<modules>
<module>foo</module>
<module>bar</module>
</modules>
In each child pom:
<artifactId>foo</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>org.me</groupId>
<artifactId>parent-project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
To build the project (both modules) with Maven, execute this from the parent directory:
$ mvn install
This is not possible using maven alone. The closest you can get is to make both as modules of an aggregator POM, so you can build both with a single command. Note that a mvn install will already consider if there have been changes since the last build so you're saving a few CPU cycles there.
First, setup a multi-module build as Daniel has shown. Then change to the directory with the parent POM. Then, for example to install foo with automatically installing bar before, too, type:
mvn --also-make --projects foo install
This will check the dependencies within the reactor and then resolve to run the install life cycle on bar before it runs the install life cycle on foo.
This works with any life cycle or goal. Mind you however that if you specify jetty:run, then this goal would be run in both projects, which is probably not quite what you want.
You can find more information about this feature here: http://maven.apache.org/guides/mini/guide-multiple-modules.html

How to rebuild dependencies before running jetty from maven

I have a multi module maven project. One of the modules is a reusable part which is packaged into a jar, and the other is a war web-app which depends on the first module. When I use jetty:run-exploded on the second module, the packaged jar is taken from local maven repository whereas I want the first module to be rebuild and packaged into the resulting war. Is there any way to force such behavior instead of the default one?
From everything I can tell from reading documents about Maven's design and using Maven myself this cannot be done in the projects own directory.
Maven will not follow module paths UP a hierarchy. Using -amd (also make dependencies) will only work at the top level module that ties all the other multi-module pom's together. So what you can do is this:
At the TOP level directory
mvn -amd -pl jetty_module jetty:run-exploded
I think you can use maven Advanced Reactor Options to archive this.
http://www.sonatype.com/people/2009/10/maven-tips-and-tricks-advanced-reactor-options/
The -pl or –projects option allows you to select a list of projects from a multimodule project. This option can be useful if you are working on a specific set of projects, and you’d rather not wait through a full build of a multi-module project during a development cycle.
Maven -amd(also-make-dependents ) also help to build multi module project once. Using that you can build a project and any project that depends on that project.

Why does maven recognize dependencies on only installed POM files?

I've got a project with Maven in which one subproject (A) wants to depend on another subproject (B) which uses "pom" packaging.
If I do this the straightforward way, where A specifies a dependency on B with <type>pom</type>, things work perfectly if I do "mvn install", but if I run any phase earlier than install, such as mvn compile or mvn package, then it fails while trying to build A: it goes looking for B's pom in the repository, and doesn't find it.
I don't really want this pom in the repository, because it's part of our active source code and changes frequently.
For all the jar-packaged projects we build, it seems to work fine to keep them out of the repository, build with mvn package, and Maven knows how to find all the dependencies in the source and build trees it manages without resorting to the repository; however for the pom-packaged project it always wants to go to the repository.
A couple things I learned while trying to understand this:
Maven best practices encourage you to use pom-packaged projects to group dependencies, but with the added step of "mvn install" on the POM project
Maven lifecycle documentation says "a project that is purely metadata (packaging value is pom) only binds goals to the install and deploy phases"; maybe this is why the POM project is invisible as a dependency target unless I invoke the install phase? I tried binding the compiler plugin to the compile phase and this didn't seem to help.
Is there a way that I can specify the POM subproject as a dependency of another subproject in the same parent project, without installing the POM project to the repository?
It isn't purely a question of which goals are bound to which lifecycle phases for POM projects. If it were, then binding the "package" goal would solve the problem.
When building a multi-module project, Maven reads the POMs of all modules to determine dependencies between modules, so that it can build the depended-upon modules before the depending modules. It's able to achieve this even when running the "package" goal (such that the depended-upon modules are not yet in the local repository).
Therefore, the code that constructs the classpath for builds must be managing several cases, notably:
extra-project jar dependency, where it looks for the POM in the local repository, handles its dependencies, and adds the POM's jar to the classpath
extra-project pom dependency, where it looks for the POM in the local repository and handles its dependencies
intra-project jar dependency, where it looks for the POM within the project tree, handles its dependencies, and adds that module's target/classes folder to the classpath
intra-project pom dependency, where for some reason it doesn't look for the POM within the project tree, and therefore doesn't handle it's dependencies.
Notice the asymmetry in the last two cases, as compared to the first two.
I can see two solutions to your problem. One is to file a bug report, or rather a request to change the behaviour (since it's obviously intentional), perhaps only for the case of intra-project dependencies on multi-module projects. Or indeed propose a patch. But since the behaviour is intentional, you might meet a refusal. In the best of cases, you're in for a long wait. (I'd vote for your bug report though - I've been stung by that same behaviour, in a different context.)
The other solution is simply to run an install on your project. I don't really understand why you don't want the POM project in your repository: if needs be, you can use a snapshot repository, where it doesn't matter if things change frequently, to avoid polluting your main repository.
Configuring maven-install-plugin to run during the compile phase, and copy the relevant pom.xml to the repository, seems to accomplish what I wanted as far as Maven itself is concerned, though m2eclipse still is not happy (it throws "failed to read artifact descriptor" errors with no additional description for the pom.xml that has a dependency on the other POM project).

Resources