Maven build second level+ child projects using reactor option -pl - maven

My maven project structure is as below
Project A
pom.xml
- ProjectB
pom.xml
- ProjectC
pom.xml
- ProjectD
pom.xml
- ProjectY
pom.xml
By using maven reactor options i can
clean install -pl projectB or clean install -pl projectY
But while trying to build the second level child modules using clean install -pl projectC, maven throws
org.apache.maven.MavenExecutionException: Could not find the selected project in the reactor: projectC
how to build the second level+ child modules using maven reactor options

From the documentation for the -pl option it states the following:
-pl,--projects <arg> Comma-delimited list of specified
reactor projects to build instead
of all projects. A project can be
specified by [groupId]:artifactId
or by its relative path.
The important part for you is: "or by its relative path".
So to build projectC, you simply need to refer to it by its relative path (projectB/projectC). So the command you need is:
mvn clean install -pl projectB/projectC

This is an answer from a similar question that is also relevant here.
By using artifactIds you don't have to know the structure of your project.
If you only use the artifactIds of the given project you have to define that correctly on command line:
help output of Maven (mvn --help)
Comma-delimited list of specified reactor projects to build of all
projects. A project can be specified by [groupId]:artifactId or by its
relative path
This means in your case you have to define:
mvn clean install --projects :projectC,:ProjectY
Notice the : that is prepended to the artifactIds to indicate you omit the groupId

Just in case someone else has this one too:
I also encountered this error message. The reason was that by accident I had been in one of my (sub-)modules in the path in terminal.
Of course the command has to be executed in the project's root hierarchy. According to the example above you have to assure that you execute a command like:
clean install -pl projectB
at Poject A
not e.g. at ProjectY or somewhere else deeper in the project structure.
Correct:
user:~/workspace/IdeaProjects/pojecta{master}$ clean install -pl projectB
Wrong:
user:~/workspace/IdeaProjects/pojecta/projecty{master}$ clean install -pl projectB

Related

How to package jar from one project to another in maven multimodule project

I need a best-practice solution for the following problem. I have a maven multi-module project with 3 subprojects:
client-module (simple java app which packaged as .jar)
module-1-that-uses-client
module-2-that-uses-client
module-*-that-uses-client is a bunch of static xml config files with a client-module.jar which is packaged as a .zip file. So, the packaged structure of a module-*-that-uses-client would look like:
client-module.jar
config1.xml
config2.xml
config3.xml
I wonder how I can implement following build strategies.
If I build client-module, then:
build client-module
copy client-module.jar to all module-*-that-uses-client
build all module-*-that-uses-client modules.
If I build any of module-*-that-uses-client, then:
build client-module
copy client-module.jar to exact module-*-that-uses-client
build exact module-*-that-uses-client modules.
Appreciate any help on this problem.
One solution would be the usage of --also-make and --also-make-dependents.
--also-make builds all dependencies of the specified module. Example: mvn --projects module-1-that-uses-client --also-make clean install builds client-module and module-1-that-uses-client in this order.
--also-make-dependents builds the specified module and all other modules with a dependency to the specified module. Example: mvn --projects client-module --also-make-dependents clean install builds first client-module and then both module-*-that-uses-client.
See also the Guide to Working with Multiple Modules.

Define modules list which shall be built in Maven multiproject build

I would like to use Maven -pl option to define which specific modules shall be included into reactor. The option works if list of module's paths is provided. Unfortunately, providing module's artifactIds is not working at all.
Sonatype: Maven: The Complete Reference docs are using multiproject example where directories names are matching artifactIds:
Using Advanced Reactor Options
Is it possible to use -pl option with artifactId?
Yes, it's possible to do this. Take a look at mvn --help:
-pl,--projects <arg> Comma-delimited list of specified
reactor projects to build instead
of all projects. A project can be
specified by [groupId]:artifactId
or by its relative path.
Note in particular that an artifactId without a leading groupId still has a leading colon.
So, for example in a case where the artifactId is the same as the directory name, these three lines would all refer to the same module in Maven:
mvn -pl maven-core
mvn -pl :maven-core
mvn -pl org.apache.maven:maven-core
mvn seems to take the list you provide with -pl to the heart and not build any dependencies automatically.
So in addition to Joe's answer: If the project/module you're trying to build depends on other modules then you can ask mvn to build them as well with -am.
-am,--also-make
If project list is specified, also build projects required by the list
If project list is specified = if -pl option is used
So examples become:
mvn -pl maven-core -am
mvn -pl :maven-core -am
mvn -pl org.apache.maven:maven-core -am

Can the maven reactor resolve module dependencies locally when resuming a build?

In a multi-module project, where module_b has a dependency on module_a, I want to run the test goal only in module_b. Using the advanced reactor option:
mvn -pl module_b test
builds only module_b as expected, but it pulls the dependency for module_a from the repository rather than the module's target directory. If the install target has not been run for module_a, the dependency might be out of date. The same thing happens if I try to do the equivalent with the resume option, i.e.
mvn -am -pl module_b -rf module_b test
(Note that this means the resume option may not produce the same output as a full build, depending on the specified goals)
Is there a way to force the maven reactor to retrieve the module_a dependency from its target directory without rebuilding it?
No, it's not currently possible with the built-in reactor, according to this comment on the Maven JIRA

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 do I exclude certain modules from a Maven build using the commandline

Is there a way to exclude some modules from a big reactor build, similar to -pl ?
Here are a number of ways to do it persistently:
How to exclude a module from a Maven reactor build?
I want to do it from shell, or at least without modifying the poms, which I am not allowed to change.
Maven 3.2.1 has added this feature, you can use to specify the exact projects you want (or to exclude the projects you don't want) -pl or --projects Here's how to exclude two:
-pl "!<modulename>,!<modulename2>"
for exclude certain modules. This can be comma separated list of values that you want to include/exclude.
Update
For windows user following
> mvn clean [package|install] --projects \!groupId:artifactId
Another comment on the accepted answer, don't forget to escape the exclamation sign when running the command in bash:
> mvn clean install -pl \!module,\!module/submodule,\!groupId:artifactId
As Yogesh_D wrote it can be done with the -pl argument with maven 3.2.1+
Here's an example:
> mvn clean install -amd -pl !module,!module/submodule
You need to list every sub-module (and sub-sub-module etc) manually, it does not exclude them recursively. Use the slash for package separation. It's the folder path, not the group or artifact id.
I don't believe this is currently possible from the command line. There is an open feature request in maven3 for this very thing (https://issues.apache.org/jira/browse/MNG-5230).
Looks like your only option at this point is to modify the pom and create a new build profile that includes only the modules you want to build.
Instead of using exclamation ! sign you can use minus - sign.
mvn clean -pl -module1
You can also exclude multiple modules.
mvn clean -pl -module1,-module2
or
mvn clean -pl -module1 -pl -module2
Tested with:
Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-17T20:33:14+02:00)
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Excluded modules must be in reactor of current project, so we can't exclude no existing module.
mvn clean -pl -no-existing-module
currently will fail - https://issues.apache.org/jira/browse/MNG-7033
in 2019 it's
mvn install -pl !:module1
(Windows 10 cmd)
comma separated module name enclosed with double quotes.
eg::
mvn install -pl "!Module1, !Module2"

Resources