Parent POM vs Super POM - are they same? - java

I want to understand if Parent POM and Super POM are same or are there still differences.
Take below maven poms, I declare a parent pom as below:
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>deps</artifactId>
<packaging>pom</packaging>
<version>0.0.1-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<!-- not relevant for this question -->
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.12</version>
</dependency>
</dependencies>
</project>
Now I declare a child pom as below:
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>deps2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>com.demo</groupId>
<artifactId>deps</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<!-- not relevant for this question -->
</dependencies>
</project>
Now deps is the parent pom for deps2. I am not sure if I can also call deps as super pom for deps2.
Which of the below inheritance hierarchy is correct
dep2 --> deps end (NO Maven provided super pom)
dep2 --> deps --> Maven provided super pom end

Option 2, because all models implicitly inherit from the Super POM.
deps is a parent for deps, but not the Super POM.
This is according to the definitions on the website.
What is more ... if you inspect the effective POM, you will see that it will always inherit from the Super POM on the MVN website.

Related

Maven property substitution for repository url not happening if parent pom is defined

I'm having an issue where maven is not properly substituting properties into my repository URLs if and only if there is a parent pom defined. This is particularly a problem because the parent pom is IN the remote repository, so I need to have the parent pom defined.
minimum reproducible 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.group</groupId>
<artifactId>parent-artifact</artifactId>
<version>1.0.0</version>
<relativePath/>
</parent>
<groupId>com.group</groupId>
<artifactId>project-artifact</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>project</name>
<description>test project</description>
<properties>
<nexus.url>https://nexus.myorganization.net</nexus.url>
</properties>
<repositories>
<repository>
<id>nexus-server</id>
<url>${nexus.url}/repository/maven-releases/</url>
</repository>
</repositories>
</project>
Using this pom, I get the error message Cannot access ${nexus.url}/repository/maven-snapshots/... so clearly it is not replacing the property with the actual value.
If I remove the <parent> section of the POM, then suddenly property substitution begins working just fine:
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.group</groupId>
<artifactId>project-artifact</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>project</name>
<description>test project</description>
<properties>
<nexus.url>https://nexus.myorganization.net</nexus.url>
</properties>
<repositories>
<repository>
<id>nexus-server</id>
<url>${nexus.url}/repository/maven-releases/</url>
</repository>
</repositories>
<!-- adding this dependency so that Maven is forced to download from the repository -->
<dependencies>
<!-- some dependency here -->
</dependencies>
</project>
I know its working properly because I can see in maven's output the line Downloading from nexus-server: https://nexus.myorganization.net/repository/maven-releases/...
Any ideas?
Thanks to the commenters, the reason is because the property resolution does not occur until after the parent pom has been resolved, so that there are no property conflicts between current pom and parent pom.
More details provided at tickets MNG-2569 and MNG-624 (source).
I think you have a wrong tag in the definition of the parent.
Why is there a relativePath tag?
just remove the tag:
and try it again

How to inherit dependencies from other libraries in maven?

I created a custom my-commons library with maven. The commons pom contains eg the following dependency:
<?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">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
<relativePath/>
</parent>
<groupId>de.mydomain</groupId>
<artifactId>my-commons</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<!-- workaround for http://jira.codehaus.org/browse/MASSEMBLY-603-->
<maven.build.timestamp>${maven.build.timestamp}</maven.build.timestamp>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
I installed the custom library into my local repository.
In a different project, I reuse the library. It resolves correctly, so it exists in the repo:
<project ...>
<groupId>de.mydomain</groupId>
<artifactId>my-core</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>my.domain</groupId>
<artifactId>my-commons</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
Now in this project I'd like to use a class org.springframework.web.bind.annotation.ResponseBody.
Problem: the class is not in classpath. So maven complains [ERROR] cannot find symbol.
But why?? I'd expect the dependency being inherited!
Sidenote: I'm using Intellij IDEA if that matters. The same problem applies to all "inherited" libraries. The spring-web lib is just an example.
Please check if .m2 folder contains the jar you want to use or not. You can use mvn install command in commons project to generate the jar. Also you need to add commons project in your project pom that you are running.
You need to create the artifact for your commons project, through its pom.xml.
Like in my below example i created a separate project where i am using the AWS and some other dependency and then final jar, which i am using in other project :-
My AWS-client pom.xml looks like below :-
<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.kaamkaj</groupId>
<artifactId>aws-clients</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>aws-clients</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<aws.sdk.version>1.11.104</aws.sdk.version>
</properties>
<dependencies>
<!--AWS dependency-->
<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-dynamodb -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-dynamodb</artifactId>
<version>${aws.sdk.version}</version>
</dependency>
<dependency>
<groupId>com.mercadopago</groupId>
<artifactId>sdk</artifactId>
<version>0.3.4</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>mercadopago</id>
<url>https://github.com/mercadopago/sdk-java/raw/master/releases</url>
</repository>
</repositories>
</project>
Also, run mvn clean install on the commons pom, in your case.
And then in all other project where i need to include the aws-client , i use the artifact-id of above project, like below :-
<dependency>
<groupId>com.kaamkaj</groupId>
<artifactId>aws-clients</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
Let me know if you have any questions:
Found it: removing the <maven.build.timestamp>... <property> solved the problem. I don't know why it prevented the inheritance to work properly, especially as I didn't get any errors.

How to update the dependency version in the parent pom when building in Jenkins

I have a project with the following pom :
<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>
<parent>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>2.5.1-RELEASE</version>
</parent>
<groupId>com.bb.cc.dd</groupId>
<artifactId>Proj1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>bla bla bla</name>
<description>abcfgd</description>
<!-- Configuration of repositories for dependency resolution -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>aa.bb.cc.dd</groupId>
<artifactId>dependencyProj</artifactId>
<version>2.0.0</version>
<type>war</type>
</dependency>
</dependencies>
</dependencyManagement>
</project>
What I am trying to achieve :
When I start a build in Jenkins for Proj1,I should have an option to start a build for dependencyProj and if that succeeds insert the new version(2.0.1) in the pom of the Proj1 and complete the build for Proj 1.So the updated pom (release version) should look like this (before the maven plugin updates it for the development iteration) :
<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>
<parent>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>2.5.1-RELEASE</version>
</parent>
<groupId>com.bb.cc.dd</groupId>
<artifactId>Proj1</artifactId>
<version>0.0.1</version>
<packaging>pom</packaging>
<name>bla bla bla</name>
<description>abcfgd</description>
<!-- Configuration of repositories for dependency resolution -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>aa.bb.cc.dd</groupId>
<artifactId>dependencyProj</artifactId>
<version>2.0.1</version>
<type>war</type>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Note : I tried the "Trigger build" option from the main project and the Post Build Step "Build other projects" from dependency project but none of them update the versions when cheking in to git.Just to add i used the maven release plugin here.
Is it possible to configure jenkins to update the version of the dependent projects in the pom?

Spring Boot maven spring-could-starter-parent Brixton.RELEASE changes hibernate-core dependency

I have a project that depends on hibernate-core 3.6.4.Final, lets call it "MyDatabaseProject".
I have a second project which is a spring-cloud project, it depends on MyDatabaseProject.
The spring cloud project uses spring-cloud-starter-parent Brixton.RELEASE as it's parent pom.
When I check the dependencies (using "mvn dependency:list") I see that I now have a dependency on hibernate-core:4.3.11.Final, not 3.6.4.Final.
If I switch the spring-cloud-starter-parent version back to Angel.SR6, and I check the dependencies (using "mvn dependency:list") I see that I have a dependency on hibernate-core:3.6.4.Final, as I would expect.
It appears to me that something changed in the Brixton.RELEASE that overrides the hibernate-core version.
My question is, is this a bug, or unintentional change in the Brixton.RELEASE?
If it is intentional, what it the correct way to deal with this?
I have tried adding a dependencyManagement section to the spring cloud project pom with the hibernate-core:3.6.4.Final, and that did work, but I don't know if that is the correct way to deal with the problem. It doesn't seem right for the top level project to care about what hibernate version the lower level project uses.
Here are the minimal maven poms for the spring cloud project and the database project:
<?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>example</groupId>
<artifactId>MySpringCloudProject</artifactId>
<version>1.0.0</version>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>Brixton.RELEASE</version>
<!-- <version>Angel.SR6</version> -->
</parent>
<dependencies>
<dependency>
<groupId>example</groupId>
<artifactId>MyDatabaseProject</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
And the database project:
<?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>example</groupId>
<artifactId>MyDatabaseProject</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.6.4.Final</version>
</dependency>
</dependencies>
</project>

Variable dependency of submodule with property from settings.xml

I have a sample maven project with the following structure:
parent
frontend
backend
Frontend depends on Backend.
Backend has a database driver dependency for testing. However, this dependency should be dependent on the developers settings.xml
<dependency>
<groupId>${database.driver.groupId}</groupId>
<artifactId>${database.driver.artifactId}</artifactId>
<version>${database.driver.version}</version>
<scope>test</scope>
</dependency>
In my settings.xml I have this:
<profile>
<id>database</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<database.driver.groupId>mysql</database.driver.groupId>
<database.driver.artifactId>mysql-connector-java</database.driver.artifactId>
<database.driver.version>5.1.9</database.driver.version>
</properties>
</profile>
When I run only the backend the properties are correctly substituted.
However, if I run frontend (or parent) transitive dependencies are not available for frontend because it can't substitute the properties anymore:
[WARNING] The POM for de.phil.mvntest:business:jar:0.0.1-SNAPSHOT is invalid, transitive dependencies (if any) will not be available: 2 problems were encountered while building the effective model for de.phil.mvntest:business:0.0.1-SNAPSHOT
[ERROR] 'dependencies.dependency.artifactId' for ${database.driver.groupId}:${database.driver.artifactId}:jar with value '${database.driver.artifactId}' does not match a valid id pattern. #
[ERROR] 'dependencies.dependency.groupId' for ${database.driver.groupId}:${database.driver.artifactId}:jar with value '${database.driver.groupId}' does not match a valid id pattern. #
The funny part is, that if I move the profile declaration into the parent's pom.xml it works fine!
So my question is, why are the properties of a submodule not substituted when they come from the settings.xml.
Note:
"help:active-profiles -N" shows that the profile from the settings.xml is active.
Note2: The Maven version came with STS and is Embedded 3.0.4
Following the settins.xml and poms
backend
<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>
<parent>
<groupId>de.phil.mvntest</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>backend</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${database.driver.groupId}</groupId>
<artifactId>${database.driver.artifactId}</artifactId>
<version>${database.driver.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
fontend
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>de.phil.mvntest</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>frontend</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>de.phil.mvntest</groupId>
<artifactId>backend</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
parent
<?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>de.phil.mvntest</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<modules>
<module>backend</module>
<module>frontend</module>
</modules>
</project>
settings.xml
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
<profiles>
<profile>
<id>database</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<database.driver.groupId>mysql</database.driver.groupId>
<database.driver.artifactId>mysql-connector-java</database.driver.artifactId>
<database.driver.version>5.1.9</database.driver.version>
</properties>
</profile>
</profiles>
</settings>
Manipulating dependencies in profiles isn't very safe. The only case in which it works fairly well is to run tests against different dependencies, and even that is safer with the maven-invoker-plugin instead. The pom that gets deployed can only have one dependency set.

Categories