Maven Project Aggregation and Variables - maven

Agregate Project 1:
<groupId>com.mycompany</groupId>
<artifactId>builder</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<modules>
<module>../module-1</module>
<module>../module-2</module>
</modules>
<properties>
<project.parent.pom>../builder-v1/pom.xml</project.parent.pom>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<lib.version>2.5.1</lib.version>
</properties>
Agregate Project 2:
<groupId>com.mycompany</groupId>
<artifactId>builder</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<modules>
<module>../module-1</module>
<module>../module-4</module>
<module>../module-6</module>
</modules>
<properties>
<project.parent.pom>../builder-v2/pom.xml</project.parent.pom>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<lib.version>2.6.0</lib.version>
</properties>
Module 1:
<parent>
<groupId>com.mycompany</groupId>
<artifactId>builder</artifactId>
<version>1.0.0</version>
<relativePath>../builder-v1/pom.xml</relativePath>
<!--<relativePath>${project.parent.pom}</relativePath> not work-->
</parent>
<groupId>com.mycompany</groupId>
<artifactId>module-1</artifactId>
Section relativePath with variable from aggregate pom not work
<relativePath>../builder-v1/pom.xml</relativePath>
<!--<relativePath>${project.parent.pom}</relativePath> not work-->
But I need diffrent ${lib.version} in aggregate projects. If I delete inheritance part from
Module 1:
<!--<parent>
<groupId>com.mycompany</groupId>
<artifactId>builder</artifactId>
<version>1.0.0</version>
<relativePath>../builder-v1/pom.xml</relativePath>
</parent>-->
<groupId>com.mycompany</groupId>
<artifactId>module-1</artifactId>
Variables are not passed to the child modules and i got error:
'dependencies.dependency.version' for com.somelib:some-lib:jar must be a valid version but is '${lib.version}'.
How can I configure aggregate project and transfer variables into modules?
UPDATE with #Gab comments
Parent pom:
<groupId>com.mycompany</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<profiles>
<profile>
<id>v1</id>
<activation>
<property>
<name>project.type</name>
<value>v1</value>
</property>
</activation>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<lib.version>2.5.1</lib.version>
</properties>
</profile>
...
</profiles>
Module 1:
<parent>
<groupId>com.mycompany</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
</parent>
<groupId>com.mycompany</groupId>
<artifactId>module-1</artifactId>
Agregate Project 1:
<groupId>com.mycompany</groupId>
<artifactId>builder-v1</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<modules>
<module>../module-1</module>
<module>../module-2</module>
</modules>
When execute builder-v1 goals activate profile project.type=v1:
mvn clean package --file=pom_v1.xml -Dproject.type=v1 -Dproject.main.module=module-1

maybe define a common parent with 2 profile defining different values for ${lib.version} and automatically activate one profile in your "aggregates" poms. All your module will inherit from the parent one
parent-pom (defining 2 different profiles)
|
+ aggregate 1 (inherit from parent-pom - activate profile 1)
| |
| + module 1 (inherit from parent-pom)
|
| + module 2 (inherit from parent-pom)
+ aggregate 2 (inherit from parent-pom - activate profile 2)
|
+ module 1 (inherit from parent-pom)
|
+ module 3 (inherit from parent-pom)
[edit]
Seems the only trick to automatically activate one profile in your "aggregates" poms to avoid to specify a property in the maven command is
<activation>
<file>
<exists>relative_path_of_file_specific_to_project</exists>
</file>
</activation>
because the property based activation works only with system properties (not the one defined in pom) and you can't override inherited profile configuration (active by default).

If I understand your question right, you want your module to have multiple parents. This is not possible. See this discussion.
You could try suggestion of #Gab. Essentially define two profiles - one for builder-v1 and another for builder-v2. You can do pretty much anything inside a profile, including specifying different set of modules and different properties/versions.

Related

Maven pom version inheritance

I have 3 projects Parent,Child,SubChild.
Project Parent pom is as follows:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
</parent>
<groupId>mu.parent</groupId>
<artifactId>parent-system</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
....
Project Child pom is defined below and its Parent is defined follows:
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>mu.parent</groupId>
<artifactId>parent-system</artifactId>
<version>1.0</version>
</parent>
<groupId>mu.dummy.child</groupId>
<artifactId>child-backend</artifactId>
<name>child-backend</name>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>subChild-app</module>
</modules>
...
Now subChild pom is as follows and the child is defined as parent for subChild :
<parent>
<groupId>mu.dummy.child</groupId>
<artifactId>child-backend</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>mu.dummy.subchild</groupId>
<artifactId>subchild-backend</artifactId>
<name>subchild-backend</name>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>org.project.test</groupId>
<artifactId>project</artifactId>
<version></version> --version of parent-system???
</dependency>
</dependencies>
Is it possible to get version of parent-system(1.0) in subchild-backend please without hardcoding it?
You can use CI-friendly versions and write ${revision} for the versions, setting this property in the main pom (from which you build everything).
You need to use the flatten Maven plugin, though, to get proper POMs in the repository.
I asked a similar question a while back and determined that tthe groovy-maven-plugin works for this. See this answer.

Exclude parent and its children or modules in maven command executing lifecycle

Executing mvn clean install -pl !Parent2 does NOT apply life-cycles on Parent2 children's nor modules. While all sub-projects are in same level I try to combine Project2 & Project2 into one parent Parent2 to exclude it only from many life-cycles. How could this be done ?
Similarly mvn clean install -pl Parent2 only applied on Parent2 without its children/modules !!
Here are the latest POMs I reached to structure. Noting that my only restriction is keeping folders of all in same level (under Parent1)
Parent1
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>any</groupId>
<artifactId>Parent1</artifactId>
<version>whatever</version>
<packaging>pom</packaging>
<modules>
<module>Parent2</module>
<module>Project1</module>
</modules>
</project>
Parent2
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>any</groupId>
<artifactId>Parent1</artifactId>
<version>whatever</version>
</parent>
<packaging>pom</packaging>
<artifactId>Parent2</artifactId>
<modules>
<module>../Project2</module>
<module>../Project3</module>
</modules>
</project>
Project1
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>any</groupId>
<artifactId>Parent1</artifactId>
<version>whatever</version>
</parent>
<packaging>jar</packaging>
<artifactId>Project1</artifactId>
</project>
Project2 (Project3 is exactly the same)
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>any</groupId>
<artifactId>Parent2</artifactId>
<version>whatever</version>
<relativePath>../Parent2</relativePath>
</parent>
<packaging>jar</packaging>
<artifactId>Project2</artifactId>
</project>
I'm interested in applying the exclusion on sub-modules as well. However mvn clean install -pl Parent2 -amd works as wanted & expected applying clean & install into Parent2, Project2 & Project3. However, as pointed by Pawl's comment and according to MNG-5230 issue
Nested modules are not excluded by parent module. The exclusion method mimics the inclusion method and its matcher does not support wildcards etc. So to cascade exclusion would necessitate an extra flag like -amd.
The dependency graph is filtered in the following order when using
-pl:
1. included projects + possibly upstream and downstream
2. excluded projects
3. skipping for resume projects
So it should be possible to directly exclude nested modules as they should be present in the intial dependency graph before filtering starts.
So excluding nested modules using their parent/holder pom is not possible. Here is how I worked around it to solve this. Simply using profiles and completely removing sub-modules outside profiles definition solved it.
In short is using profiles to identify modules with noting that modules identified outside profiles are shared no matter what profile is activated
Example as of OP projects naming followed
Parent1 (Added Project4 as same as Project1 just for clarifying)
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>Parent1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<profiles>
<profile>
<id>multi-modules-profile</id>
<modules>
<module>Parent2</module>
<module>Project2</module>
<module>Project3</module>
</modules>
</profile>
<profile>
<id>simple-module-profile</id>
<modules>
<module>Project1</module>
</modules>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
<modules>
<module>Project4</module>
</modules>
Project1 (& Project4 is similar)
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>Parent1</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>Project1</artifactId>
Parent2
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>Parent1</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>Parent2</artifactId>
<packaging>pom</packaging>
Project2 (& Project3 is similar)
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>Parent2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../Parent2</relativePath>
</parent>
<artifactId>Project2</artifactId>
Now running mvn clean would apply on Parent1, Project1 & Project4 because Project1 is in profile that is activated by default (without specifying profile during the execution). This has same effect running mvn clean -P simple-module-profile because Project4 is shared outside profiles definitions.
Finally, running mvn clean -P multi-modules-profile will be applied to Parent1, Project4, Parent2, Project2 & Project3 leaving Project1 out which is desired. Notice Project4 is always in because it's outside profiles definitions.
EDIT: the answer applies only to:
Similarly mvn clean install -pl Parent2 only applied on Parent2 without its children/modules !!
Use mvn -pl Parent2 -amd clean install to build Parent2 and all of it's modules.
See the reference: https://books.sonatype.com/mvnref-book/reference/_using_advanced_reactor_options.html#_making_project_dependents

Maven Multi Module Project looking for modules in repository instead of Building them

I have a multi-module MVN project, which has 1 aggregator pom, another parent pom, and 3 other modules, as follows:
project-all
-project-parent
-project-common
-project-maintainance
-project-webApp
project-WebApp has a dependency on project-common and project-maintenance.
When I run a clean install on project-all, it tries to download the modules from repositories instead of building them.
My understanding of a multi-module project is that it runs an install on all the modules as well, but that is not what is happening.
If I run a clean install on all the modules separately, the project-all clean install works fine. It also works when I run the mvn build in Eclipse with the Resolve Workspace Artifacts option selected.
However, both of these options are not viable options, since the idea of using a multi-module project is to run multiple poms from a single location.
Am I missing something, what would be the process of asking mvn to build those modules instead of looking for them in the repository.
Pom for project-all:
<?xml version="1.0" encoding="UTF-8"?>
<groupId>com.midtier.api</groupId>
<artifactId>project-all</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<name>project-all</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<modules>
<module>project-parent</module>
<module>project-data</module>
<module>project-maintenance</module>
<module>project-WebApp</module>
</modules>
POM for project-parent:
<?xml version="1.0" encoding="UTF-8"?>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<groupId>com.midtier.api</groupId>
<artifactId>project-parent</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<name>${project.artifactId}</name>
<description>${project.artifactId}</description>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<elasticsearch.version>6.2.4</elasticsearch.version>
<jsonsimple.version>1.1.1</jsonsimple.version>
<slf4j-version>1.7.25</slf4j-version>
</properties>
<dependencyManagement>
<!--Dependencies Here-->
</dependencyManagement>
Pom for project-Webapp:
<?xml version="1.0" encoding="UTF-8"?>
<project>
<parent>
<groupId>com.midtier.api</groupId>
<artifactId>project-parent</artifactId>
<version>1.0</version>
</parent>
<groupId>com.rbc.midtier.api</groupId>
<artifactId>project-webapp</artifactId>
<packaging>jar</packaging>
<version>${project.parent.version}</version>
<name>${project.artifactId}</name>
<description>${project.artifactId}</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.midtier.api</groupId>
<artifactId>project-data</artifactId>
</dependency>
<dependency>
<groupId>com.midtier.api</groupId>
<artifactId>project-maintenance</artifactId>
</dependency>
</dependencies>
</project>
project-data and project-maintenance are similar to project-web app but they don't have any internal dependencies.
Again, what I want to do is, just run the clean install command on all, and not have to worry about building any of the modules individually.
I think the problem is that you define the parent as a module. When you run „clean“ the parent used by the other modules is still not available so Maven tries to find it within the repository. Better define the parent information within the project-all pom because during the build phase the parent has to be available.

Maven run only the parent pom with a profile

In my project, I have a custom profile custom-profile-name.
A simplified structure of my POM looks like this:
<artifactId>parent</artifactId>
<modules>
<module>child</module>
</modules>
When I run
mvn help:active-profiles -P custom-profile-name
I get:
Active Profiles for Project 'org.sample:parent:pom':
The following profiles are active:
custom-profile-name
Active Profiles for Project 'org.sample:child':
The following profiles are active:
custom-profile-name
I've been reading about profile inheritance and If I understand correctly, profiles should not be inherited. Can anyone explain why the custom-profile-name is active in the child module.
My ultimate goal is to execute the parent with one configuration of a custom plugin and all child modules with another configuration of the same plugin.
Not sure why both parent and child modules are getting activated for custom-profile-name. But to get whats needed for you can be done by defining properties inside the profile.
Example:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>parent</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<name>parent-app</name>
<url>http://maven.apache.org</url>
<modules>
<module>child</module>
</modules>
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>child</module>
</modules>
<properties>
<parentProp>foo</parentProp>
<childProp>foo</childProp>
</properties>
</profile>
<profile>
<id>custom-profile-name</id>
<modules>
<module>child</module>
</modules>
<properties>
<parentProp>xyz</parentProp>
<childProp>abc</childProp>
</properties>
</profile>
</profiles>
The 'parentProp' is a configuration used by the parent pom and 'childProp' is the configuration used by the child pom. From the configuration it can be seen that the default profile and the 'custom-profile-name' profile behaves differently as the values for the properties is different.

Dependency hierarchy not using property from parent pom?

I have a problem I wonder if someone could help me to resolve.
I have a module structure in my project where I resolve dependencies using Maven. For this structure I have versions with different content I distinguish using classifiers. For each classifier I have defined a profile in a parent pom with the string for the classifier in a property. This way in my modules I use this property and is the profile I defined who decides the classifier constant.
The problem I'm stuck with now is the dependency hierarchy not recognizing the classifier when a dependency is inherit from the one I define in the pom of one of my modules.
For example, if I have projects A, B and C, B depends on A and C depends on B, from C I'm getting B with the classifier but not A with it.
This happens if I use the property from the parent pom. If I use directly a constant string instead, the dependencies get caught correctly.
The only solution I see is using profiles on each pom defining the dependencies inside them. But I have 5 profiles! Isn't there any other way to resolve this?
I'm using STS 3.8 with m2e plugin as my IDE.
Thank you in advance!
I add the poms
parent pom:
<profiles>
<profile>
<id>TRUNK</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<svnBranch />
</properties>
</profile>
<profile>
<id>MON</id>
<properties>
<svnBranch>MON</svnBranch>
</properties>
</profile>
<profile>
<id>LOLA</id>
<properties>
<svnBranch>LOLA</svnBranch>
</properties>
</profile>
<profile>
<id>NBA</id>
<properties>
<svnBranch>NBA</svnBranch>
</properties>
</profile>
<profile>
<id>TEST</id>
<properties>
<svnBranch>TEST</svnBranch>
</properties>
</profile>
<profile>
<id>PROD</id>
<properties>
<svnBranch>PROD</svnBranch>
</properties>
</profile>
</profiles>
Project A:
<parent>
<groupId>com.myproject</groupId>
<artifactId>pom</artifactId>
<version>1.0.10</version>
</parent>
<artifactId>core-services</artifactId>
<version>1.1.0.41-SNAPSHOT</version>
Project B:
<parent>
<groupId>com.mycompany</groupId>
<artifactId>pom</artifactId>
<version>1.0.10</version>
</parent>
<artifactId>olb-services</artifactId>
<version>1.1.0.41-SNAPSHOT</version>
<properties>
<module.core-services.dependency.version>1.1.0.41-SNAPSHOT</module.core-services.dependency.version>
</properties>
<dependencies>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>core-services</artifactId>
<version>${module.core-services.dependency.version}</version>
<classifier>${svnBranch}</classifier>
</dependency>
</dependencies>
Project C:
<parent>
<groupId>com.mycompany</groupId>
<artifactId>pom</artifactId>
<version>1.0.10</version>
</parent>
<artifactId>nba-services</artifactId>
<version>1.1.0.41-SNAPSHOT</version>
<properties>
<module.olb-services.dependency.version>1.1.0.41-SNAPSHOT</module.olb-services.dependency.version>
<module.core-services.dependency.version>1.1.0.41-SNAPSHOT</module.core-services.dependency.version>
</properties>
<dependencies>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>olb-services</artifactId>
<version>${module.olb-services.dependency.version}</version>
<classifier>${svnBranch}</classifier>
</dependency>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>core-services</artifactId>
<version>${module.core-services.dependency.version}</version>
<classifier>${svnBranch}</classifier>
</dependency>
</dependencies>
Using the ${svnBranch} in the classifier tag for each dependency doesn't work. It looks like in project B, when is referenced by project C, the property ${svnBranch} is empty nevertheless it comes from the parent pom.
In maven, you can only use a profile defined at the parent level in your child pom, if you can only activate it at built time by passing -D{activation.property}=value or -P{profile.id/s} .
You cannot define a profile in your parent and try it to activate in your child pom as profile can not be inherited(you are not even trying to activate in the child pom in your case as per your example).
in another word,unless the profile is activate by default maven doesn't know about it (you might be tempted to activate everything by default in your case, but bear in mind only one profile can be activate by default at the time)
your problem is ${svnBranch} from TRUNK is only present in your child pom and has no value, therefore maven only acts on the GAV and not the classifier. and to prove that check your child's effective pom (mvn help:effective-pom). also you can check which of your profile are active and which are not (mvn help:all-profiles).
I don't think using profiles is the best approach for what you are doing. A better/simpler approach maybe be to just declare your branch names in normal properties in your parent for example.
<properties>
<svnBranch.lola>LOLA</svnBranch.lola>
<svnBranch.nba>NBA</svnBranch.nba>
</properties>
then your child uses as needed.
<dependencies>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>olb-services</artifactId>
<version>${module.olb-services.dependency.version}</version>
<classifier>${svnBranch.lola}</classifier>
</dependency>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>core-services</artifactId>
<version>${module.core-services.dependency.version}</version>
<classifier>${svnBranch.nba}</classifier>
</dependency>
</dependencies>

Resources