Build multi maven modules then copy JARs inside a docker image - maven

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.

Related

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.

Setting subproject pom.xml to be ignored by parent install

My parent pom modules list looks something like this:
<modules>
<module>jarProject1</module>
<module>jarProject2</module>
<module>jarProject2</module>
<module>warProject1</module>
<module>warProject2</module>
</modules>
I would like warProject1 and warProject2 to be ignored when I run mvn clean install on the parent pom. I want install to only build jars and put them in the maven repo but not the war producing projects. Currently I do it using profiles but I have some problems related to that. I would like the parent pom to keep a comprehensive list of modules in its default modules tag and not under profiles. Is there a way to do it and how?

How to Run SonarQube Findbugs Analysis for a project with multiple source directories

I have one multimodule maven project where there are source directories apart from 'src' where java file resides.
This is the folder structure
folder1
-pom.xml
pom.xml Contains modules defined like this:
<modules>
<module>module1</module>
<module>module2</module>
<module>module3</module>
<module>module4</module>
<module>module5</module>
<module>module6</module>
<module>module7</module>
<module>module8</module>
<module>module9</module>
<module>module10</module>
</modules>
Different modules are organized like this:
module1
-src
-gen
module2
-src
module3
-gen
module4
module5
-src
-gen
So, as you see, there are modules/projects which have either src or gen or both or doesn't have any of it.
When I run findbugs analysis, it picked only java classes from 'src' and skipped 'gen' (Natural as Maven model forces the analyzer to pick from only src)
So, in the Jenkins job configuration, I defined sources explicitly like this:
-Dsonar.sources=src,gen
-Dsonar.exclusions=src/test/java/**
When I run with this configuration, analysis fails for modules which doesn't have both src and gen. (module2, module3, module4)
So, how do I run the analysis to pick either src or gen or skip that module if either of them is not found ?
Thanks,
Ron
When using the SonarQube scanner for Maven, you can't specific properties that only apply to some of the modules using the command line.
In the modules where you want to modify the sources, add in the pom.xml a property. For example, in module5/pom.xml add:
<properties>
<sonar.sources>src,gen</sonar.sources>
</properties>

build multiple modules multiple times in parent pom

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)

Jenkins and maven multi module Projects missing artifacts

This is a simplified example of an ear project, the parent pom aggregates the EAR, the EJBs, and the jars.
I have this structure in a Maven project, stored in SVN:
parent/
|- pom.xml
|- modulA/
| |- pom.xml
|- modulB/
| |- pom.xml
modulB has a Dependency of modulA
The pom.xml have the modules section
<modules>
<module>modulA</module>
<module>modulB</module>
</modules>
And a Dependency Management section
<dependencyManagement>
<dependencies>
<dependency>
<groupId>group</groupId>
<artifactId>modulA</artifactId>
<version>0.0.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>group</groupId>
<artifactId>modulB</artifactId>
<version>0.0.2-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
The sub-modules reference the parent
<parent>
<groupId>group</groupId>
<artifactId>parent</artifactId>
<version>0.0.2-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
in my PC when I compile for the first time with maven 2.2.1 (windows)
mvn clean compile
I don't have any problems
but.... when Jenkins try to compile for first time (Maven 2.2.1 Linux RedHat)
Missing:
----------
1) modulA:jar:0.0.2-SNAPSHOT
Try downloading the file manually from the project website.
Then, install it using the command:
mvn install:install-file -DgroupId=group -DartifactId=modulA -Dversion=0.0.2- SNAPSHOT -Dpackaging=jar -Dfile=/path/to/file
Alternatively, if you host your own repository you can deploy the file there:
mvn deploy:deploy-file -DgroupId=group -DartifactId=modulA -Dversion=0.0.2-SNAPSHOT -Dpackaging=jar -Dfile=/path/to/file -Durl=[url] -DrepositoryId=[id]
Path to dependency:
1) modulB:ejb:0.0.2-SNAPSHOT
2) modulA:jar:0.0.2-SNAPSHOT
----------
1 required artifacts are missing.
Why????????
After that if I deploy the project from my pc to Artifactory, Jenkins doesn't have problems, because Jenkins downloads the artifact from the repository... but why does Jenkins depend on the artifacts in the repository?
:(
Thanks in Advance
EDIT:
I thought the dependencyManagement section only "defines" the dependencies, but if a submodule doesn't use the dependency, the dependency isn't added to the submodule.
I drop the dependencyManagement section and the problem in Jenkins still occurs.
It works on my PC without problems.
I hope above dependency management section is inside the parent pom. According to your requirement modulB has a Dependency of modulA. So I suggest you to include dependency in moduleB instead of having it in the parent pom. I think when it runs in first time maven is looking for both dependencies since you have mentioned in in the parent pom.Look at your project build order. First it builds module A and then B. In your case I hope you have include all other dependencies in moduleA's pom file and once it built it will deploy a jar file in to m2 repository. And then moduleB start to build and since your dependency is already in the m2 repository it wont shout and project will build successfully.
The first time you build parent project, your Jenkins user's maven repository won't have modulA installed. clean compile is then run successfully in modulA, but nothing is installed. When it is run in modulB, the dependency on modulA can't be resolved.
If your Jenkins job's goal was clean install instead of clean compile, then modulA's artifacts would be installed to the Jenkins user's repository before the modulB build begins, and all would work.
Presumably this worked on your own machine because either you had run mvn install at least once in modulA, or because your IDE's classpath resolved the problem for you.

Resources