I have multiple spring boot projects, every project is independent and has its own CICD pipeline.
These projects need some common classes, I have created a separate project with common classes.
Parent
pom.xml (with packaging)
lib-project
pom.xml
project-1
pom.xml
project-2
pom.xml
I can build project easily from the parent directory, it builds all the projects
parent$ mvn clean package
it generates all the jar files and put them in their respective target folder of projects
My problem is I can't initiate this at the parent level, this has to be initiated from within each project from its own pipeline.
and
I cannot use any local or remote repository, to put the dependent jar in m2 using mvn clean install and then refer to it as dependency
I want to build it from the relavent project directory
parent/project-1$ mvn clean package
it shows following error:
Could not resolve dependencies for project com.test.multiple:project-1:jar:0.0.1-SNAPSHOT: Could not find artifact com.test.multiple:lib-project:jar:0.0.1-SNAPSHOT
My expectation stepwise on compilation of project-1
Check if there is a dependency for project-1
Go to ../lib-project
Compile and build it in target folder (or anywhere relative to our project)
Add this generated jar to "project-1" dependency
Compile and build the "project-1" jar file.
Parent Pom Configurations
<project ...>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.test.multiple</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>lib-project</module>
<module>project-1</module>
</modules>
</project>
** Lib project pom **
<project ...>
<parent>
<groupId>com.test.multiple</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.test.multiple</groupId>
<artifactId>lib-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>lib-project</name>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Project-1 pom
<project ...>
<parent>
<groupId>com.test.multiple</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.test.multiple</groupId>
<artifactId>project-1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>project-1</name>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.test.multiple</groupId>
<artifactId>lib-project</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I have multiple spring boot projects, every project is independent and has its own CICD pipeline.
These projects need some common classes, I have created a separate project with common classes.
Congratulations, your projects are not independent any more!
Given the definitions above, here are the dependencies:
lib-project depends on parent;
project-1 depends on parent;
project-1 depends on lib-project.
Please check Introduction to the POM and Guide to Working with Multiple Modules for the discussion on the dependencies in Maven projects.
I cannot use any local or remote repository, to put the dependent jar in m2 using mvn clean install and then refer to it as dependency
Given this limitation, and dependencies listed above, the POMs and source files of all the projects have to be present on the disk for build purposes. The build process has to start from the parent folder. The build process has to build all modules at once.
Also, please consider using mvn clean verify instead of mvn clean install to avoid populating the local repository with the artifacts you are building.
A maven project isn't designed to build its dependencies on demand. However, jenkins can be configured to build downstream projects when changes are pushed to an upstream dependency.
I have also worked around this by using the -pl option on a parent pom in the relevant jenkinsfile to build a subset of the child projects
Jenkinsfile
clone parent project
mvn clean package -pl core,deployable
Related
I have one interesting question about resolving dependencies versions by gradle. Here is my situation. I deployed my libraries to nexus. In this process I used the flatten-maven-plugin and resolveCiFriendliesOnly flattenMode. As result I have parent pom file and child pom files in nexus.
parent pom file from source:
<groupId>ru.example</groupId>
<artifactId>example-parent</artifactId>
<version>${revision}${changelist}</version>
<packaging>pom</packaging>
<properties>
<revision>0.0.1</revision>
<changelist>-SNAPSHOT</changelist>
<version.base>${revision}${changelist}</version.base>
<example-child.version>${version.base}</example-child.version>
<example-child-dependency.version>${version.base}</example-child-dependency.version>
</properties>
child pom file from source
<parent>
<groupId>ru.example</groupId>
<artifactId>example-parent</artifactId>
<version>${revision}${changelist}</version>
<relativePath>..</relativePath>
</parent>
<artifactId>example-child</artifactId>
<version>${example-child.version}</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>ru.example</groupId>
<artifactId>example-child-dependency</artifactId>
<version>${example-child-dependency.version}</version>
</dependency>
</dependencies>
parent pom file from nexus
<groupId>ru.example</groupId>
<artifactId>example-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<version.base>0.0.1-SNAPSHOT</version.base>
<revision>0.0.1</revision>
<changelist>-SNAPSHOT</changelist>
<example-child.version>${version.base}</example-child.version>
<example-child-dependency.version>${version.base}</example-child-dependency.version>
<properties>
child pom file from nexus
<parent>
<groupId>ru.example</groupId>
<artifactId>example-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>ru.example</groupId>
<artifactId>example-child</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>ru.example</groupId>
<artifactId>example-child-dependency</artifactId>
<version>${example-child-dependency.version}</version>
</dependency>
</dependencies>
After that I try to build java application with gradle. In build.gradle file of this application I have such line:
dependencies {
implementation("ru.example:example-child:0.0.1-SNAPSHOT")
}
And build fails with error:
> Task :java_application:compileJava
Resolving global dependency management for project 'java_application'
Errors occurred while build effective model from /u01/jenkins_slave/.gradle/caches/modules-
2/files-2.1/ru.example/example-child/0.0.1-
SNAPSHOT/809129e53f76bfb7b6a141e9aeb8ffb1a692e76c/example-child-0.0.1-SNAPSHOT.pom:
'dependencies.dependency.version' for ru.example:example-child-dependency:jar must be a
valid version but is '${example-child-dependency.version}'. in ru.example:example-
child:0.0.1-SNAPSHOT
Why gradle doesn't resolve placeholder of child project dependency?
gradle appearently does not evaluate ${example-child-dependency.version} and you might have to build with mvn in order to produce consumable/static *.pom for gradle. I mean, most likely mvn would evaluate *.pom, while gradle doesn't.
And that might rather be:
<artifactId>example-child-dependency</artifactId>
<version>${version.base}</version>
The whole project dependencies are looking like this:
- parent
- child-a
- pom.xml
- child-b
- src.main.java.resources
- mybatis-generator.xml
- pom.xml
- pom.xml
parent, pom.xml
<project>
<packaging>pom</packaging>
<modules>
<module>child-a</module>
<module>child-b</module>
</modules>
</project>
child-b, pom.xml
<project>
<packaging>jar</packaging>
<parent>
<artifactId>parent</artifactId>
<relativePath>../</relativePath>
</parent>
<dependencies>
<dependency>
<artifactId>child-a</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<!-- other configs -->
</plugin>
</plugins>
</build>
</project>
When packaging child-b project/module solely,all dependencies were handled properly(child-a was imported as expected).
Problem:
When I'm trying to run mvn mybatis-generator:generate in the directory of child-b:
Error: Failed to execute goal on project service_a: Could not resolve dependencies for project xx.xx.child-b:jar:1.0-SNAPSHOT: Could not find artifact xx.xx.child-a:jar:1.0-SNAPSHOT -> [Help 1]
When you run maven from a nested project, it will only succeed if all the dependencies are available in your local repo. I can reproduce this if I delete a dependency from my local repo and try it on one of my projects.
Snapshot dependencies add another level of complexity in that they expire - meaning maven will look for a newer version if the version in your local repo is not considered current. They may be why a package ran at some point, but later on another maven commend like running the generator failed.
Bottom line...when snapshot dependencies are involved with nested projects, the only reliable way to run maven is to run the entire project (run maven from the parent directory).
I am developing a spring boot project which has few modules. I have on entry point module which has main class, the other module dependencis i have added in entry point module pom.xml. When i give command mvn clean install it throws an error saying `
Failed to execute goal on project api: Could not resolve dependencies
for project com.nikesh:api:jar:1.0.0: The following artifacts could
not be resolved: com.nikesh:lib:jar:1.0.0, com.nikesh:repo:jar:1.0.0,
com.nikesh:entity:jar:1.0.0, com.nikesh:dto:jar:1.0.0,
com.nikesh:service:jar:1.0.0, com.nikesh:common:jar:1.0.0: Failure to
find com.nikesh:lib:jar:1.0.0 in https://repo.maven.apache.org/maven2
was cached in the local repository, resolution will not be reattempted
until the update interval of central has elapsed or updates are forced
-`
This is my pom.xml
<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.nikesh</groupId>
<artifactId>api</artifactId>
<version>1.0.0</version>
<description>api module</description>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
<start-class>com.nikesh.api.MultiModuleApp</start-class>
</properties>
<dependencies>
<dependency>
<groupId>com.nikesh</groupId>
<artifactId>lib</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.nikesh</groupId>
<artifactId>repo</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.nikesh</groupId>
<artifactId>entity</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.nikesh</groupId>
<artifactId>dto</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.nikesh</groupId>
<artifactId>service</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.nikesh</groupId>
<artifactId>common</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Please help me out resolving this issue.
You need to make sure that all sub modules are built in proper order before the main module build.
Guide to Working with Multiple Modules
The Reactor
The mechanism in Maven that handles multi-module projects is referred to as the reactor. This part of the Maven core does the following:
Collects all the available modules to build
Sorts the projects into the correct build order
Builds the selected projects in order
Because modules within a multi-module build can depend on each other, it is important that The reactor sorts all the projects in a way that guarantees any project is built before it is required.
The following relationships are honoured when sorting projects:
a project dependency on another module in the build
a plugin declaration where the plugin is another modules in the build
a plugin dependency on another module in the build
a build extension declaration on another module in the build
the order declared in the element (if no other rule
applies)
Note that only "instantiated" references are used - dependencyManagement and pluginManagement elements will not cause a change to the reactor sort order
for more info. You can refer this link for a sample multi module maven project.
I'm using m2e Maven Plugin for Eclipse. I'm having 5 eclipse projects. A web application project and then 4 projects as jars dependencies for my web application.
I would like to know how can I package jars before including them in the WAR using "mvn clean install" on war project.
Here's my pom.xml:
<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>dispatcher</groupId>
<artifactId>dispatcher</artifactId>
<version>4.0</version>
<packaging>war</packaging>
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>referentiel</groupId>
<artifactId>referentiel</artifactId>
<version>4.7</version>
</dependency>
<dependency>
<groupId>mailTemplates</groupId>
<artifactId>mailTemplates</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>qualityTool</groupId>
<artifactId>qualityTool</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>tools</groupId>
<artifactId>tools</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
...
..
.
</dependencies>
</project>
Thank you in advance.
The answer of #Jigar Joshi is good but i thing you need a view of structure which can help you to understand quickly what we mean.
I. Create a top level maven module (parent of war and jars)
You habe already the 5 moduls that you need. Now create a new Maven project as parent which must contain only a pom.xml file.
parent project pom
<project...>
<groupId>groupId</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Define parent pom </name>
<!-- modul -->
<project>
II. Put your jar projects first as modul and at the end the war project. If you have another dependencies in the jar projects you may also try to order them consequently.
parent project pom
<modules>
<module>referentiel</module> <!-- jar -->
<module>mailTemplates</module> <!-- jar -->
<module>qualityTool</module> <!-- jar -->
<module>tools</module> <!-- jar -->
<module>dispatcher</module> <!-- war-->
</modules>
III. in all other project put the parent reference into the poms
<parent>
<groupId>groupId</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
IV. Now you can go to inside the new created parent project and run from there
mvn clean install
Either create a top level maven module (parent of war and jars) and execute mvn clean install
---pom.xml
|
|dispatcher---pom.xml (war)
|qualityTool----pom.xml (jar)
|mailTemplates----pom.xml (jar)
|referentiel----pom.xml (jar)
|tools----pom.xml (jar)
or use --also-make command line option to make dependencies as well
I'm using Maven 3.
I have multiple maven projects, namely: the 'data model', the 'service', and the 'presentation', split into 3 different projects. They are configured separately (ie. not using maven parent pom).
I have maven release plugin setup on my project correctly, such that when I run mvn release:clean release:prepare release:perform on each individual project, it updates the project version (ie: from 3.4.5-SNAPSHOT to 3.4.5) as well as all the other things.
The problem here is, 'presentation' is dependent on 'service' is dependent on 'data model', and I refer to the projects in the pom files with the version number.
While I develop, say for example I would refer to 'service' in 'presentation' as 3.4.5-SNAPSHOT. But during deploy, I have to release 'service' to change the version to 3.4.5, then I have to update my version reference of 'service' in 'presentation', before I can run a release on 'presentation'.
Is there an automated way of doing this such that I don't need to update the reference of dependent projects during release?
What I have so from thanks to below comments: Updated: 25/03/2013
Run maven with:
versions:use-releases -Dmessage="update from snapshot to release" scm:checkin release:clean release:prepare release:perform
Outcome: version updated, but release build failed.
The Versions Maven Plugin may help you to achieve requirement, especially the goal versions:use-releases. You may be interested in the goal versions:use-next-releases and versions:use-latest-releases as well.
Side Note:
Normally, the good practice is define them as a Maven Multiple Module( here and here). This allow us to manage the version easier as the following example.
The parent
<groupId>my-group</groupId>
<artifactId>my-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
.....
<modules>
<module>my-model</module>
<module>my-service</module>
<module>my-ui</module>
</modules>
The my-model
<parent>
<groupId>my-group</groupId>
<artifactId>my-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>my-model</artifactId>
The my-service
<parent>
<groupId>my-group</groupId>
<artifactId>my-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>my-service</artifactId>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>my-model</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
The my-ui
<parent>
<groupId>my-group</groupId>
<artifactId>my-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>my-ui</artifactId>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>my-service</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
Regarding to the above example when we release, the related version will be updated based on the parent version automatically.