build multiple modules multiple times in parent pom - maven

There are several applications that need to be built and packaged from a number of modules.
In parent pom, i'm using the profile to invoke builds for different apps.
root
parent/
pom.xml
moduleA/
pom.xml
moduleB/
pom.xml
moduleC/
pom.xml
For example, app "profile-1" would need a subset of existing modules to be built and put together as a tar ball.
The tar would contain several jars and different config files pulled from the target/ of the sub modules.
I'm using a shell script invoked using exec-maven-plugin to put together the tar.
The problem I'm facing is that, in one application, i need to build the same module multiple times but with different maven parameters.
What is the best way to do this?
<profiles>
<profile>
<id>profile-1</id>
<modules>
<module>../moduleA</module>
<module>../moduleB</module>
<!-- <module>../moduleC</module> -->
</modules>
<properties>
<global.version>0.0.1-SNAPSHOT</global.version>
</properties>
<build>
<!-- use maven exec plugin to run a shell script which generates the tar ball picking jars and config files from different modules target dirs -->
<plugins>
</plugins>
</build>
<profile>
</profiles>
A sample sub module pom
<groupId>com.test</groupId>
<artifactId>moduleC</artifactId>
<packaging>bundle</packaging>
<version>${global.version}</version>
<name>test :: ${project.artifactId} :: ${name} </name>
<parent>
<groupId>com.test</groupId>
<artifactId>parent</artifactId>
<version>${global.version}</version>
<relativePath>../parent</relativePath>
</parent>
Things i tried:
1) Can i separate into multiple profiles and invoke them as -Pprofile-1,profile-2?
It did not work for me but i would be doing something wrong.
2) Have another shell script that has mvn command line to build the moduleC in different ways.
- Even though i pass in the "-Dglobal_version", the moduleC run from mvn command line does not seem to find the parent in the repository.
I tried doing a "-N" build to put the parent pom in the repository before building the application but did not help.

Best way is:
mvn clean install --projects moduleA, moduleB
mvn clean install --projects moduleB, moduleC
You can't run multiple builds with maven (see this stackoverflow question)

Related

Build child module without building parent module if there is some changes in parent pom

I have a multi module project with more than 70 modules and it takes 3 Hrs to build the project with tests.
Parent pom.xml
...
<version>${revision}</version>
<properties>
<app.version>1.0</app.version
<properties>
.....
<modules>
<module>a<module>
<module>b<module>
<module>c<module>
.....
...
Child pom.xml
<parent>
<groupId>com.test</groupId>
<artifactId>parent</artifactId>
<version>${revision}</version>
</parent>
<artifactId>b</artifactId>
How to build only module b only if we change the version number in parent pom.xml
After upgrading the parent POM to a new version (and the reference to it in b's pom.xml), you could run :
mvn --projects b <maven_phase_you_want> # or mvn -pl b [...]
From Maven's 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
However, this only works if the old version of your parent POM is already in your local repository, or at least is available (it have been deployed on a repository manager). Otherwise, you'll get an error because, even if specifying --projects b, Maven will try to resolve parent POM (that he won't find) for other modules a and c.

Can a maven build tell if it is multi-module

I have a multi-module maven build, with a structure like
a/
pom.xml
b/
pom.xml
c/
pom.mxl
d/pom.xml
e/
pom.xml
Some of the analysis plugins are slow, so I would like to skip them when running building multiple modules (cd a; mvn install) but not a single module (cd a/b/c; mvn install). In the single module build, I might look at the generated warnings and fix them, but with the multi-module build, they I won't look at them, since the full build literally builds dozens of modules.
Is there a way to determine if I am building multiple modules from within the build?
I am hoping for something like reactor.build is defined in all modules when I run from /a but not defined when I run from /a/b/c.
All I was able to find when I googled was how to set up a multi-module build or only build some of the projects, which is not what I am looking for.
Goals
I understand the maven build cycle. I want to be able to add something like this to my pom root pom:
<properties>
<skipSlowPlugin>${multi.project.build}</skipSlowPlugin>
<properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.slow</groupId>
<artifactId>analysis-tool</artifactId>
<version>1.0.0</version>
<configuration>
<skip>${skipSlowPlugin}</skip>
</configuration>
</plugin>
</plugin>
</pluginManagement>
</build>
If I run the build from /a/b/c, multi.project.build will be false and the plugin will run. If I run from /a or /a/b, then multi.project.build will be true and the plugin will not run.
In every case, I want to build everything under the current directory, so --pm and --am are irrelevant.

Build multi maven modules then copy JARs inside a docker image

I have a multi-modules project configured with maven.
/myProject
/module1
/target
pom.xml
/module2
/target
pom.xml
pom.xml
The pom parent is building the submodules.
Using the com.spotify.dockerfile-maven-plugin I want to build all the modules, build a docker image and copy all the JARs inside that image.
The pom parent
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>myTest</artifactId>
<name>test</name>
<version>0.0.1</version>
<packaging>pom</packaging>
<modules>
<module>module1</module>
<module>module2</module>
</modules>
</project>
If I put a Dockerfile at the root of /myProject, the plugin complains there is no Dockerfile for module1
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} /home/xyz/jars
maven plugin:
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<configuration>
<repository>mytest</repository>
<buildArgs>
<JAR_FILE>target/${project.artifactId}-${project.version}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
This works fine with one module if I put the Dockerfile inside that module but how to do with multiple modules and only 1 Dockerfile?
Can I build the submodules and then the docker image with a single mvn clean install on the parent pom?
Maybe by creating a submodule only with a pom and the Dockerfile?
If the jars are dependencies for one executable then yes, you could just build that one executable with its dependencies declared in its pom.xml file. Maven should figure out which order to build the submodules in, so long as you don't create a cycle. As you suggest, you want to make it a submodule and not the root pom as the root pom is parent configuration that is inherited by other modules. Just put the plugin on that one submodule (in its pom.xml) and only give it the Dockerfile.
(If you think of this as a problem about having one executable depending on libraries in the same maven project then it's not really related to docker. You could ask the same question about a spring boot app using libraries in the same multi-module project. In a sense it just is that problem as the jar will get built together with its dependencies and copied into the docker image.)
Or if you mean that each jar for each submodule is an executable in itself (and I don't think you do) then you could create multiple docker images, each from its own Dockerfile, and then you can bundle and start them together if you want to with a docker-compose file.

version property dynamic in pom.xml

I have a Maven pom.xml, I build project and executable jar deploy in Nexus with Jenkins.
But I want changes of version name according to branch name.
For example: I have in pom.xml
<groupId>net.test</groupId>
<artifactId>test-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>iin-parent</name>
<packaging>pom</packaging>
I need set like this : (Branch- Master/Test1/Test2/..)
<groupId>net.test</groupId>
<artifactId>test-parent</artifactId>
<version>BranchName_0.0.1-SNAPSHOT</version>
<name>iin-parent</name>
<packaging>pom</packaging>
How can this be done?
I was using MVN build like -Drevision=BranchName-SNAPSHOT clean compile package deploy. But I want dynamically fetch the branch name.
enter code here
If you use clean compile package deploy you are duplicating several parts..only clean deploy is needed. Please read the documentation about Maven Life cycle.
Furthermore if you like to change the version dynamically you can do that by using the correct properties (Starting with Maven 3.5.0+) which are ${revision}, ${sha1} and ${changelist} so for example:
<groupId>net.test</groupId>
<artifactId>test-parent</artifactId>
<version>${revision}</version>
<properties>
<revision>1.0-SNAPSHOT</revision>
</properties>
This can be done in Maven like this:
mvn -Drevision=2.0-SNAPSHOT clean package
or if you like to do this for a branch:
mvn -Drevision=2.0-BranchName-SNAPSHOT clean package
You have to be aware if you like to do mvn clean deploy please read carefully the docs and follow them.

Jenkins fails to build multi-module Maven project

I have a multi-module Maven project where I have multiple micro services as modules so I have modules listed in my parent pom.xml like below:
<modules>
<module>core</module>
<module>model-base</module>
<module>module1</module>
<module>module2</module>
...
<module>module5</module>
<module>module7</module>
<module>module6</module>
</modules>
Here the module7 is dependent on module5, 6 so I have dependencies listed like below in my module7 pom.xml:
<parent>
<artifactId>pojectA</artifactId>
<groupId>com.domain</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>module7</artifactId>
<dependencies>
<dependency>
<groupId>com.domain</groupId>
<artifactId>core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.domain</groupId>
<artifactId>module5</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.domain</groupId>
<artifactId>module6</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
When I run mvn clean package in my local the module5, 6 called before the module7 as expected but in Jenkins it is trying to build module 5 then module7 making build fail saying:
[ERROR] Failed to execute goal on project module7: Could not resolve dependencies for project module7:jar:1.0-SNAPSHOT: Could not find artifact module6:jar:1.0-SNAPSHOT -> [Help 1]
Do I need to run any other jobs or re-order the modules in my pom.xml, how is it differ from local to Jenkins? Appreciate any help on this.
The order of modules is not relevant. Maven recognizes which project depends on which other project(s) and sets the build order in the reactor accordingly. See POM Reference, Aggregation (or Multi-Module):
You do not need to consider the inter-module dependencies yourself when listing the modules, i.e. the ordering of the modules given by the POM is not important. Maven will topologically sort the modules such that dependencies are always build before dependent modules.
Add Pre-Step as per below attached screenshot. This will compile all your top modules.
Then we can execute which ever module we want.
As is probably quite well understood, the issue is that the dependencies between the child modules fail because they aren't installed in the local repository yet (because they are yet to be built). The goal that causes this (for me anyway) is mvn test, which is invoked by mvn package. Your local build probably works because at some point you've done a mvn install and this has bootstrapped your system.
In Jenkins the only way I've found to make these builds work is to use the Pre-build step invoking a Maven target of install, and then build the main step as usual.

Resources