Jenkins fails to build multi-module Maven project - maven

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.

Related

Can modules referring to parent pom by relative path be depended on by 3rd parties?

I have a parent module, which defines its version as follows:
<groupId>org.group</groupId>
<artifactId>parent-id</artifactId>
<packaging>pom</packaging>
<version>${library.version}</version>
<properties>
<library.version>1.0.0</library.version>
</properties>
Then I have a sub module, which points to its parent as follows:
<parent>
<groupId>org.group</groupId>
<artifactId>parent-id</artifactId>
<version>${library.version}</version>
<relativePath>../../</relativePath>
</parent>
<artifactId>child-id</artifactId>
<packaging>jar</packaging>
And I depend on it in my other projects like so:
<dependency>
<groupId>org.group</groupId>
<artifactId>child-id</artifactId>
<version>1.0.0</version>
</dependency>
This results in the following error for me:
Failed to read artifact descriptor for org.group:child-id:1.0.0: Failure to find org.group:parent-id:pom:${library.version}
Can this problem be solved without resorting to mvn versions:set in my multi module project to manage explicit versions in all poms?
/edit: currently solved this problem with a workaround that makes using mvn versions:set a little easier.

Depend on module in multi-module Maven project when module doesn't produce an artifact

I have a multi-module maven project that contains the following modules:
system-x-server
system-x-client
system-x-server-image
system-x-integration-tests
The system-x-server-image produces a docker image that is used to conduct integration tests within the tests-only system-x-integration-tests project. Adding it as a dependency:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>system-x-server-image</artifactId>
<version>${project.version}</version>
</dependency>
Produces an error because the system-x-server-image doesn't produce an artifact (it does, but not one that's resolved using Maven).
Is there some way that I can make the the system-x-integration-tests depend on the system-x-server-image given that system-x-server-image doesn't produce an artifact?
Please set packaging to pom in system-x-server-image module.
<project ...>
...
<packaging>pom</packaging>
...

Generating the .war file from maven dependency project

Here I have two projects those are project(1) and project(2).
I am going to generate a .war file for the project(1) but it depends on project(2).
I built the project(2) as a .jar file and added it to the project(1)'s build path but while runnig mvn install it results in compilation errors like:
package com.disha.db.dao.orm.gen does not exist` the package is in the project(2).
Can any one please help to me.
You have to delegate dependency management to Maven and that's actually where it comes in hand, otherwise you can move on packaging and resolving inter-projects dependencies by hand and let the Maven alternative be dropped.
You should make sure you have provided the correct Project Object Module description for your projects (pom.xm) along with tha packaging type.
Then since you want the project(2) to be availble for project(1) at compilation time, you have to declare, project(2) as a dependency of project(1).
project(2) pom.xml (I will refer to it as project-2 since 'project(2)' does not match a valid id pattern.):
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>project2.group.id</groupId>
<artifactId>project-2</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
</project>
Now the project(1) will refer to the project-2 artifact as a dependency with scope compile:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>project1.group.id</groupId>
<artifactId>project-1</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>project2.group.id</groupId>
<artifactId>project-2</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
Note: Update the group and artifact IDs with ones you are using.

Adding A Group of Files to a Local Maven Repository

I have an existing java project. It is a maven project. I want to add it to my local maven repository for reuse in other projects.
MyUtilityClass.jar
MyUtilityClassSources.jar
MyUtilityClassDocs.jar
Dependent on
slf4j-1.7.2.jar
junit-4.11.jar
This SO Question/Answer gives instructions for adding a single file to a local maven repository using mvn install:install-file
This SO Question/Answer gives instructions for adding a group of jars - sources, javadoc, etc. using mvn deploy-file.
This SO Question/Answer alludes to specifying dependencies via a pom.xml file, but doesn't provide details.
I have two tasks in front of me that I'd like to accomplish:
add the project for MyUtilityClass to my local repository, with sources, docs, and dependencies automatically added when I pull them in.
I'd like to create a maven task for the MyUtilityClass project that adds the latest and greatest bundle to my local repository.
I am using eclipse as an IDE and maven version 3.0.4. The POM for this project looks like this:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.local.mine</groupId>
<artifactId>MyUtilityClass</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>MyUtilityClass</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>com.local.mine</groupId>
<artifactId>slf4j</artifactId><!--from local repo -->
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>com.local.mine</groupId>
<!--from local repo and shouldn't be automatically added -->
<!-- to projects that reuse the resulting bundle -->
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</project>
The easiest way to do this is to think of each project as their own release cycles. They should be independant of each other.
As you have discovered, you can
use install to install the artifact to your local repository
use install-file to install secondary artifacts to your local repository
use deploy to so the same steps as install(-file), but to remote repositories
What also does this is the release plugin. When you perform the pair goals of release:prepare and release:perform, you end up with
version values update in the pom files
version control tags created
the artifact installed & deployed
any source and/or javadoc artifacts deployed
What you want to use is the release plugin.
The simple solution is to use
mvn install
in the project you would like to reuse. This will install the artifacts of your project into your location repository.

How to generate Javadoc for Maven Dependencies

I have a maven project with the following POM snippet:
<modelVersion>4.0.0</modelVersion>
<artifactId>Foo-Deploy</artifactId>
<name>Foo-Deploy</name>
<packaging>pom</packaging>
<description>foobar</description>
<dependencies>
<dependency>
<groupId>de.foo.bar</groupId>
<artifactId>some-api</artifactId>
<version>${project.version}</version>
<classifier>doc</classifier>
<type>zip</type>
</dependency>
</dependencies>
The idea is to have a dependency defined in which some sources are (this is created successfully before).
Now I want to run javadoc on exactly THIS dependency. When I call
mvn javadoc:jar -DincludeDependencySources=true -DdependencySourceIncludes=de.foo.bar:some-api:*:doc:zip
it fails with the message
Not executing Javadoc as the project
is not a Java classpath-capable
package
what is wrong ? and would it work anyhow ?
or how can I generate javadoc from a specific dependency (assuming this project has more dependencies) ?
Thanks
To generate javadoc for dependent sources, a sequence of steps needs to be done. These are outlined in this link.
Essentially you need to ensure that the source files of the dependency is generated/available and <includeDependencySources> parameter is enabled.

Resources