In Maven how can I recursively build -SNAPSHOT dependencies present in the filesystem but outside the reactor? - maven

I have two projects as follows, in neighbouring directories on the filesystem:
project_a (-SNAPSHOT)
project_b (-SNAPSHOT, depends on project_a)
I'd like to build project_b and for Maven to discover that project_a exists on the filesystem and thus build it rather than look in the local repo for its artifact.
I could build these within an aggregator and use the reactor to select project_b i.e.
mvn --projects project_b [goal]
However, this is problematic because
this two-project example is a simplification of my real build, which consists of dozens of projects, and I don't want to have to maintain an aggregator project that lists all of them.
I only want to recursively build -SNAPSHOT dependencies
Is there a neat way I could get Maven to perform a recursive build that looks on the filesystem to find -SNAPSHOT dependency projects and builds them?

I needed this a while back and made a simple recursive wrapper cli in nodejs. https://github.com/kenglxn/mvnr/blob/master/README.md
Install from npm with
sudo npm install -g mvnr
Then just pass any maven command to mvnr, and it will run that command on all mvn projects under the cwd.

You could play with Maven Reactor plugin, e.g. try mvn reactor:make -Dmake.folders=foo,bar

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.

Maven to Gradle -- command line options

I'm making a case for moving our builds from Maven to Gradle. Below are a few of the Maven command-line options my team finds useful. What are the Gradle equivalent choices?
-am,--also-makeIf project list is specified, also build projects required by the list
-amd,--also-make-dependentsIf project list is specified, also build projects that depend on projects on the list
-o,--offline Work offline
-pl,--projects Build specified reactor projects
instead of all projects
-rf,--resume-from Resume reactor from specified project
Maven Examples:
I only want to build the sub-project I'm working on and its dependencies.
mvn install --also-makeIf --projects :my-sub-project
After fixing an build issue, I want to start the build from the point of failure.
mvn install --resume-from :my-sub-project
I don't want to download external dependencies from an central repo.
mvn install --offline
Here are some rough analogues:
-am: buildNeeded (This triggers a full build of all upstream projects; building those parts of upstream projects that are required to fulfill the command at hand is automatic in Gradle.)
-amd: buildDependents
-o: --offline
-pl: :subproject1:build :subproject2:build
-rf: No direct analogue (not reliable, wouldn't work for parallel builds, etc.), but Gradle's incremental build will get you to the "resume point" quickly.
Note that Gradle's core concepts differ significantly from Maven's. To give one example, in Gradle build order is solely determined by task relationships, and there is no such concept as an execution dependency between projects. Due to these differences, some Maven features aren't necessary or useful in Gradle, some you get for free, and some come in a different form.

Maven: how can I skip building artifacts which exist in central repo?

My situation: I have project which contains several Maven modules. I make changes to one of them. Suddenly I find out, that my project is no longer possible to be built because of the errors in other modules. To fix this I need to run SVN UPDATE and rebuilt the project.
My assumption: probably, during the build process of my module some of the artifacts are taken from central repository and have the most newest version, while others are still outdated and taken from my local repo.
A question: I don't want to rebuild my project each time someone updates ANOTHER Maven module. I want to download the already built artefacts from the central repository without rebuilding them by myself. Is it possible?
You can tell Reactor which modules to build. In your case when you only change a single module and want to speed up the build you can pass -pl (Project Location) parameter to maven. For example:
mvn -pl module-with-changes
That will build single module, while taking other dependencies from your local Maven Repository or download from Central (whatever is the latest). That said, if you already ran mvn install for whole project and other artifacts have not been updated in Central repository, then Maven will see your local artifacts as latest and will not re-download them.
Another issue you might get with -pl parameter is when other modules in your project depend on the module that you are building. If there is a problem in dependent module you will not see it by building only the dependency model. To avoid that you can pass -amd (Also Make Dependents). Like this:
mvn -pl module-with-changes -amd
That will trigger the build for module-with-changes + modules that depend on module-with-changes + their dependents.
You can get more info about Reactor parameters from here:
http://www.sonatype.com/people/2009/10/maven-tips-and-tricks-advanced-reactor-options/

Best practice wrt. `mvn install`, multi-module projects, and running one submodule

I tend to avoid using mvn install in my multi-module projects because I feel like I then don't know which exact version of a submodule is then used when building / launching other submodules (particularly when switching between branches very often).
I tend to use mvn package a lot and then mvn verify.
I'm now facing the issue in a FOSS project (a Maven archetype moreover) where I'd like to use Maven's best practices.
It's a multi-module project with a webapp submodule depending on the other modules, and what worries me is the ease of development along with mvn jetty:run (or jetty:start).
Currently, I defined 2 profiles:
prod, the default one, declares dependencies on the other submodules;
dev on the other hand does not depend on the other modules, and configures the jetty-maven-plugin by adding the other modules' output directories as extraClasspath and resourcesAsCSV.
That way, I can mvn package once and then cd webapp && mvn jetty:start -Pdev and quickly iterate, reloading the webapp without the need to even stop the server.
AFAICT, extraClasspath was added for that exact purpose (JETTY-1206).
I've been pointed at the tomcat7-maven-plugin which can resolve modules from the reactor build when using Maven 3 (and I raised an issue to bring the same to Jetty: JETTY-1517), but that hardly solve my
If I hadn't removed the dependency on the other submodules from in dev profile, I'd have had to do an mvn install first so that validating the POM doesn't fail, even if jetty:start doesn't use those dependencies afterwards.
So here's my question: is mvn install really that common? or my approach of putting the intra-reactor dependencies only in the prod profile OK?
(note that I have the exact same problem with the gwt-maven-plugin, so please don't tell me to simply switch to Tomcat; that wouldn't even work actually, details here)
The mvn install is common in particular in relationship with multi-module builds, cause it will give you the chance to run a single module from your multi-module build.
This can be achieved by using:
mvn -pl submodule LifeCycle
I just found a workaround (which seems logical as an afterthought): https://jira.codehaus.org/browse/JETTY-1517?focusedCommentId=306630&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-306630
In brief: skip the plugin by default in the parent module then re-enable it where needed.
This however only works if the plugin can be skipped (i.e. has a skip configuration) and is only used in one specific submodule, and it has to be selectively done for each plugin you need/want to run that way (in my case, jetty:run and gwt:run).
I do most of my development on my laptop. For the projects I'm currently working on, my local repository is really more of a temporary holding area. I run mvn install all the time. Putting artifacts in one's local repo is the only way I know of to share built artifacts between projects, especially if you are working on projects which are related but are not (and should not be) part of the same multi-module build.
When I'm done developing I commit changes to the shared SCM and let Jenkins build & deploy the code to the shared remote repo. Then I either blow away the changed projects in my local repository so the next build brings down the freshly built artifacts, or I run Maven with -U to force updates.
This works well for me, YMMV.

Build single module from multimodule pom

Is it possible to do?
The environment: Multimodule pom consists of 3 modules: mm1, mm2, mm3. Module mm2 has mm1 as dependency. It is possible to build parent pom without any errors.
The question: Is it possible to build single module mm2 (i.e., run maven from mm2 base directory) without installing mm1 into local repository?
Thanks.
I'm not sure what you mean exactly by "without installing mm1 into local repository". Do you mean previously to building mm2 or never?
In doubt, maybe one of the new build options announced in the Maven Tips and Tricks: Advanced Reactor Options blog post can help:
Starting with the Maven 2.1 release,
there are new Maven command line
options which allow you to manipulate
the way that Maven will build
multimodule projects. These new
options are:
-rf, --resume-from
Resume reactor from specified project
-pl, --projects
Build specified reactor projects instead of all projects
-am, --also-make
If project list is specified, also build projects required by the list
-amd, --also-make-dependents
If project list is specified, also build projects that depend on projects on the list
I was specifically thinking to the -pl and -am options. To build a subset of the modules, run the following from the root directory
$ mvn --projects mm2 --also-make install
However, I'm not sure this answers your question (which is not totally clear for me).
Without automatic installing not, but it's possible to build only choosen projects. You need to have multi module build (I'm assuming you do). In reactor mode every command need to be run from the root of reactor.
So in your case:
mvn reactor:make -Dmake.folders=mm2
In this case you build mm2 module and modules on which it depends (mm1).
Useful links:
Maven reactor plugin reference
Maven book reactor chapter
From book examples I build only project persist and his dependency project model. Others projects are untouched with
mvn reactor:make -Dmake.folders=sample-persist
alt text http://www.sonatype.com/books/maven-book/reference/figs/web/running_aro-dependencies.png
Other useful command is reactor:make-dependents which build projects that depend on X.
This goes against the principle of dependencies of Maven2. What is the interest of doing that exactly?
However, we can imagine to define the mm1 dependency of mm2 as a system dependency:
<dependency>
<groupId>...</groupId>
<artifactId>mm1</artifactId>
<version>...</version>
<scope>system</scope>
<systemPath>../mm1/target/</systemPath>
</dependency>

Resources