This question already has answers here:
Build order of Maven multimodule project?
(4 answers)
Closed 6 years ago.
I have a Maven parent project which has multiple child/modules...I have the following pom.xml for the main/parent;
<modules>
<module>Main-Ear</module>
<module>Sub-Web</module>
<module>Sub-Ui</module>
<module>Sub-Services</module>
<module>Sub-SSO-Login</module>
</modules>
However, I find the actual build order to be different...
After build, the actual order looks like;
Main
Sub-Services
Sub-SSO-Login
Sub-UI
Sub-Web
Main-Ear
Where exactly does Maven take the build order from in this case?
You can't manually control the build order:
From Maven project documentation (Guide to Working with Multiple Modules):
Reactor Sorting
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
Maven not taken the module building order from what we define in the main pom.xml. Maven decide the order by considering module dependencies with each other modules.
In your case definitely Main-Ear should build last.
Let's consider following example.
I have module A, B and C. Module A has dependency from module C and B while module C has dependency from module B. Then maven building order will be
B
C
A
Related
Let's say I have a maven project which has some maven modules inside.
My main module depends on the other modules, so when I compile the main module they should be compiled together.
The question is, how to add these modules as dependencies to the main module?
I know if I have a custom lib that I want to use with maven, let's say a utilities project, I have to compile the jar of the project, do a mvn install:install-file on it to install it on the local repository and then add it to the pom.xml.
Do I have to do this with all my modules and add the dependency to the pom.xml on my main module? Because if it should be done like this, there will be a lot of work to do when changing code on the other modules.
What is the best practice to use avoid the trouble of compiling/installing the modules to local repository?
The question is, how to add these modules as dependencies to the main module?
The same way you add any other dependency to your maven project. By adding group id, artifact id and version to <dependency> element
Do I have to do this with all my modules and add the dependency to the pom.xml on my main module?
If your main module depends on some module A then only the pom of the main module should contain dependency declaration towards module A. You do that for all the dependencies of your module.
I don't know what you mean by "a lot of work when changing the code on other modules". Maven has nothing to do with code changes, it just builds the projects whatever they look like at the given moment...
What is the best practice to use avoid the trouble of compiling/installing the modules to local repository?
Any project that you invoke mvn install on gets built and it's jar copied to local repository. That's all you need to do to get the jar into the repo. This will also put all the dependent jars, if available, into the local repo.
As for best practices for multi module projects:
If your parent project (the one that has modules inside) has <modules> section that lists the modules of your application, and modules are in subdirectories of your parent project, then you simply mvn install (or whatever you want to do) the parent project and that will cause all the modules to be built in order defined by declared dependencies between them. That means that if your main module has dependency on module A, then module A will be built before the main module. This way you can build and install all your modules with one command. On the other hand this approach makes more tight coupling between modules which is not desired in some cases, so it depends on your use case whether it is a good approach or not.
This question already has answers here:
Build order of Maven multimodule project?
(4 answers)
Closed last year.
I have a maven modular project with the following build order.
common
core
third-party
services
web-app
Each module has its own pom.xml and the build order is included in the parent pom. So when I make any changes to common, should I only build common module or all the modules again to get the latest changes from common module?
It is generated a jar file to each module, then you should build all modules again.
suppose I have a project say A which is dependent on B. so when I build project A. does maven generates the artifact of A by bundling with project B artifact?
and suppose if project B is dependent on C. then when I build project A, will it by default takes the transitive dependency c to generate the artifact? and even if it takes, what will happen if I add C as a dependency in project A pom.xml? will maven takes the C artifact for two times to build A and generates a bigger artifact file?
what will happen if I add C as a dependency in project A pom.xml?
If C's dependency has already been resolved, maven will simply ignore it if it is declared elsewhere.
will maven takes the C artifact for two times to build A and generates a
bigger artifact file?
No.
Please check https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Transitive_Dependencies for more details.
Transitivity brings a very serious problem when different versions of the same artefacts are included by different dependencies. It may cause version mismatch issue in runtime. In this case, dependency:tree command is very useful in dealing with conflicts of JARs.
$ mvn dependency:tree
Check https://howtodoinjava.com/maven/maven-dependency-management/#dependency-tree for more details.
this question is a little bit broad, things can change a little with you start to talk about Maven multi-module projects (so there is a parent-child relationship between modules). I will assume that multi-module setups are off-topic for this question.
Also: IDEs have tight integration with Maven and might add additional automatic processes on top of it. I assume this is plain Maven as it would work from a shell.
finally: there is a big difference from working with dependencies you pull in from the internet and projects you are building yourself with Maven. I am going to limit this answer to only building your own projects when it comes to dependency management. Otherwise I'd be writing the Maven manual here.
suppose I have a project say A which is dependent on B. so when I
build project A. does maven generates the artifact of A by bundling
with project B artifact?
Maven will include whatever you put in the dependencies listing; if it cannot it will fail the build. If project B is your own project, it will not automatically build B for you when you are building project A, it will only try to include whatever jar is already in your local maven repository. If there is no jar in your local repository, it will try to download it from all the Maven repositories that are known within the project. This will fail if Project B is just a project living on your harddrive, the only way then to make the jar of Project B available for usage in Project A is to actually build and install Project B first so a copy of the jar is put in your local maven repository.
Similarly if project B changes but you do not change its Maven version number, it is your own responsibility to rebuild and install it so the existing jar in your local maven repository gets overwritten.
It is possible that the dependency jar of B is pushed to a remote repository; it could be that your company is hosting or licensing a Nexus or an Artifactory for example and development builds are pushed to a snapshot repository so it can be used by several developers on different machines without them having to checkout the project and build it on their own machine. Then it depends on how Maven is configured if it will eagerly download updated versions of the jar when building project A. If you are working with a remote repository and you suspect that during the build an older version of a dependent jar is being used, this existing question's answers detail a few ways to force dependency jars to be updated when they were already downloaded before. But you should hardly ever need to use that.
and suppose if project B is dependent on C. then when I build project
A, will it by default takes the transitive dependency c to generate
the artifact?
Yes it will walk the entire dependency tree and include all transitive dependencies.
and even if it takes, what will happen if I add C as a
dependency in project A pom.xml? will maven takes the C artifact for two times to build A and generates a bigger artifact file?
Well first of all: dependencies are not included in the jar of project A by default so the size of the jar does not depend on the number of dependencies the project has. You would have to specifically use a plugin that has this functionality, often called "one jarring", "creating a fat jar" or creating an "uber jar". The Maven Shade plugin is a common way to do this.
Regardless, Maven does not allow multiple copies of the same dependency groupId+artifactId pair to exist on the classpath and will filter out duplicate copies when it finds them. This also happens when you add the same artifact multiple times within the same pom, Maven will call you out on it and include only one copy.
So no, in the end there will be only one copy of C.jar. Even if the pom of A refers to C version 1.0 and the pom of B refers to C version 1.1.
I have 3 projects, A->B->C in that dependency order. Currently everytime I make a change to B or C I have to go to the directory and do a mvn clean install in order to install it into the local repository. It is troublesome if I have to do this every time the projects updates.
How can I do it such that every time I do a mvn clean package on A, it will automatically build and install my dependent projects B and C into the local repository?
Create a parent project for all your projects A,B,C and then add all your child project on the parent pom.xml file something like this
<modules>
<module>A</module>
<module>B</module>
<module>C</module>
</modules>
Its called maven multi module project mentioned by #khmarbaise
Here are some example for this
How do I create a multi-module project in Eclipse?
Maven Multi module tutorial
Guide to Working with Multiple Modules
By use of multi module project you will get plenty of benefits like
Anytime you can add any new project with all of the current project
Separation of project is good for code cleanup
You can build Single project or You can build all project in one go.
Duplicacy of jar can be easily ignore .
Maven take care of the build order for you.
One single Jenkins job to build everything.
Plenty of other benefits.But remember if there will some pros then cons also there,its totally now what you want to use .
You can follow the solution I provided to the question Maven 2 Projects, since it is the pattern I usually use when building project with a certain complexity.
Summarizing you would have to create a main Maven project which has three submodules, say master, platform and parent.
The main project has simply the order in which the other projects will be evaluated by Maven
The master pom contains the list of project to be built and their order (aka Reactor order)
The platform pom contains all information about your platform, like JDK version, maven plugin versions, encoding and so on.
The parent pom has the platform pom as a parent and contains all global GAV information about the dependencies you are going to use in your project (Spring, CXF, junit, log4j etc.)
The situation is, I have two Maven multimodule projects with the same structure:
Parent
- Module 1
- Module 2
When I build project 1, I see that parent is built first (order is parent->module1->module2). However for project 2, parent is built at last (order is module1->module2->parent). Why are the two projects have different build orders? Furthermore, how can I manually control the build order?
Update 1:
Both parent projects are simple POM projects without source code, so I can't explain the build order as per the dependency graph.
Update 2:
The parent POMs are the same except the GAV and child module names:
<?xml version="1.0" encoding="UTF-8"?>
<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>parent-group-id</groupId>
<artifactId>parent-artifact-id</artifactId>
<version>parent-version</version>
<packaging>pom</packaging>
<name>parent-name</name>
<modules>
<module>module-1</module>
<module>module-2</module>
</modules>
</project>
The build order is determined by the Maven reactor which is a mechanism that automatically ensures correct build order for multimodule builds by sorting the projects.
See the official documentation for how it works.
It says:
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)
You can't manually control the build order. If you want to change the order you have to make changes to your project that influence the reactor sort order.
At a high level, the build order is based on a topological sort of the module dependency graph.
EDIT: Question for you. I understand that project 1 contains two modules and so does project 2. But do the modules in project 2 explicitly declare the "parent" pom as a parent? I'm thinking that perhaps your project 1 modules explicitly declare the parent pom, and the project 2 modules don't. Which would mean that the project 2 "parent" isn't really a parent at all and therefore doesn't have to be built before the modules. That's my guess anyway.
I've been having this issue lately with CentOS 7. I updated Maven to 3.5.3 from 3.0.5 and the problem has been solved. If anyone have this issue as well you can try doing that first.
Summary
Why?
Maven is using <module> declarations to determine the list of modules to include in the current run. Maven is using <parent> declaration to generate effective POM for each included module, which is then used to execute the build for that module.
In Project 1, each of module1 and module2 specify parent module in <parent> section.
In Project 2, neither module1 nor module2 specify parent module in <parent> section.
How can I manually control the build order?
By changing dependencies between modules, including <parent>, <dependencies>, plugin dependencies, etc. as described in the official documentation.
Please check also Introduction to the POM for the discussion on aggregation and inheritance.
Details
There are 4 possible scenarios of module relationships in Maven in terms of aggregation (<module> declaration) and inheritance (<parent> declaration).
Let's assume a module A with packaging pom and a module B (packaging does not matter). The module A could either be a parent or an aggregator. The module B could either reference A as parent or not.
Case 1:
Neither A nor B reference each other - the modules are independent.
The Maven can not control build order, each module gets built independently, with manual build order control.
Case 2:
The module A includes the module B in <modules>. The module B does not declare A as parent. The module A is an aggregator for the module B in this case.
Maven invocation mvn -f A/pom.xml will first build B, and then A.
Maven invocation mvn -f B/pom.xml will build B only.
Case 3:
The module A includes the module B in <modules>. The module B declares A as parent. The module A is both the parent and the aggregator (reactor) for the module B in this case.
Maven invocation mvn -f A/pom.xml will first build A, and then B.
Maven invocation mvn -f B/pom.xml will build B only, but will use the POM of A to generate effective POM of B by resolving it either from the local repository or by following /project/parent/relativePath.
Case 4:
The module A does not include the module B in <modules>. The module B declares A as parent. The module A is the parent for the module B in this case.
Maven invocation mvn -f A/pom.xml will build A only.
Maven invocation mvn -f B/pom.xml will build B only, but will use the POM of A to generate effective POM of B by resolving it either from the local repository or by following /project/parent/relativePath.