Extending property from parent pom in child pom with maven - maven

I am working in a large project where we have multiple modules, each as their own maven project with a common parent pom.
Among other things, the parent pom defines the Sonar integration on our build server. Our Sonar plugin on the build server evaluates the property "sonar.exclusions" in order to skip files which we do not want to be analysed.
For that purpose, we define a property in the parent pom:
<properties>
<sonar.exclusion>**/generated/**/*,**/migration/**/*</sonar.exclusions>
</properties>
Now, in one of our projects, we want to add to this exclusion list. I do not want to replace those exclusions defined in the parent but I also do not want to repeat them. What I am looking for is something along these lines:
<properties>
<sonar.exclusions>${sonar.exclusions},**/shadow/compare/**/*</sonar.exclusions>
</properties>
In the end, I want the content of ${sonar.exclusions} to be
**/generated/**/*,**/migration/**/*,**/shadow/compare/**/*
However, trying the above results in an error:
pom.xml has 1 error [main] ERROR org.apache.maven.cli.MavenCli - Resolving expression: ${sonar.exclusions}': Detected the following recursive expression cycle in 'sonar.exclusions': [sonar.exclusions]
Is there a way to achieve what I want?

You can define a property <sonar.standard.exclusions> in your parent POM that contains your standard exclusions and set <sonar.exclusions>${sonar.standard.exclusions}</sonar.exclusions>
Then you can overwrite the property in your POM as
<sonar.exclusions>${sonar.standard.exclusions},**/shadow/compare/**/*</sonar.exclusions>

Related

Can a property be expanded relative to its defining POM and not any child(ren)

I am trying to set several properties in a parent aggregation POM project which are therefore available to all module projects:
<modules>
<module>module1</module>
<module>module2</module>
<module>module3</module>
</modules>
<properties>
<module1.dir>${project.basedir}</module1.dir>
<module1.build.dir>4{project.basedir}/build</module1.build.dir>
</properties>
The properties relate to various directories I intended them to be evaluated relative to the parent POM
I want to refer to the above properties in a second module (module2) like so:
${module1.build.dir}
However when I look at the effective POM of module2, the following expansion results:
<module1.build.dir>_project_root_directory_/module2/build</module1.build.dir>
What I would like is the value of ${module1.dir} etc. to be expanded relative to the parent POM (where it is defined). Is there anyway to do this in Maven or am I going to have to set some environment variables in a script to do this?
The reason for trying to do this is that I am doing an unusual build in that module1 is a pure native library, module2 is a JNI library that depends on module1 and module3 is a pure Java library that depends directly on module2.
no, maven does the inheritance 1st (so constructing a leaf pom's effective-pom by combining all of its parents), and only then evaluates properties.
this means properties are always evaluated in the context of the child pom in your case.
this is a requirement for maven to behave properly. look in the super pom and you will see things like:
<build>
<directory>${project.basedir}/target</directory>
...
</build>
which define where sources are looked for and where target classes are written to. they must be evaluated post-inheritance (in the context of a child).
workaround
you could use a property value like ${project.parent.basedir}, or you could "look sideways" by using ../sibling-module/whatever. neither of these is pretty.
alternative
for maven builds involving native components, have you looked at the maven nar plugin? it was developed for these situations specifically.

Maven how set absolute path for parent pom

with maven 3 i have a parent project at 'C:/travail/parent'.
I have several child-projects who, for various reasons, can change locations.
To make a war, the relativePath tag must be set.
<parent>
<groupId>framework.parent</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>C:/Travail/parent/pom.xml</relativePath>
</parent>
Question: How can I put an absolute path for the parent? The following doesn't work.
<relativePath>/C:/Travail/parent/pom.xml</relativePath>
You cannot use an absolute path for your parent pom, the name itself of the configuration entry is quite self explanatory (relative path).
From the official Maven model documentation for this element:
The relative path of the parent pom.xml file within the check out. If not specified, it defaults to ../pom.xml. Maven looks for the parent POM first in this location on the filesystem, then the local repository, and lastly in the remote repo. relativePath allows you to select a different location, for example when your structure is flat, or deeper without an intermediate parent POM. However, the group ID, artifact ID and version are still required, and must match the file in the location given or it will revert to the repository for the POM. This feature is only for enhancing the development in a local checkout of that project. Set the value to an empty string in case you want to disable the feature and always resolve the parent POM from the repositories.
Default value is: ../pom.xml.
You can't even use a shortcut or symbolic link for the same, distributed together with each and every module and pointing at the absolute file location, it would not work (and you shouldn't use such a trick anyway, even if it was going to work).
You can't even use a property as value placeholder of the relativePath element. Something like:
<parent>
<groupId>framework.parent</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>${path.to.parent}</relativePath>
</parent>
And try to inject it at build time like:
mvn clean install -Dpath.to.parent=C:/somewhere/pom.xml
Would simply not work, as also documented by the following Maven tickets:
MNG-2569: Expressions not evaluated inside
MNG-624: automatic parent versioning
The only reasonable use case for this configuration entry is, as mentioned in the official documentation, for flat-structured multi-module projects, where modules and parent project are located at the same directory level.
Otherwise, and more suitable for your use case, you should provide the parent pom as part of the shared Maven repository (if any) or require a maven install (so that it will be available in the local maven cache) of the parent project upfront for any new version before any required maven action on the children/module projects.

${project.artifactId} in parent pom.xml resolves odd

I have a bulk full of projects which have the same URLs in their pom.xml:
<url>https://github.com/malkusch/${project.artifactId}</url>
<scm>
<connection>scm:git:git://github.com/malkusch/${project.artifactId}.git</connection>
<developerConnection>scm:git:git#github.com:malkusch/${project.artifactId}.git</developerConnection>
<url>https://github.com/malkusch/${project.artifactId}</url>
</scm>
<issueManagement>
<system>github</system>
<url>https://github.com/malkusch/${project.artifactId}/issues</url>
</issueManagement>
So I thought it's a great idea to put that into a parent pom.xml. But the effective pom produces odd ${project.artifactId}:
<parent>
<groupId>de.malkusch.parent</groupId>
<artifactId>oss-parent</artifactId>
<version>1.1-SNAPSHOT</version>
</parent>
<groupId>de.malkusch.localized</groupId>
<artifactId>localized</artifactId>
<url>https://github.com/malkusch/localized/localized</url>
<scm>
<connection>scm:git:git://github.com/malkusch/localized.git/localized</connection>
<developerConnection>scm:git:git#github.com:malkusch/localized.git/localized</developerConnection>
<url>https://github.com/malkusch/localized/localized</url>
</scm>
<issueManagement>
<system>github</system>
<url>https://github.com/malkusch/localized/issues</url>
</issueManagement>
You notice that only issueManagement.url was resolved correctly. The others are totally strange, especially ${project.artifactId}.git -> localized.git/localized. I'm using Maven 3.0.4. Am I using some undefined feature? Is it a bug?
Yes, this behaviour is confusing.
Perhaps the easiest way to understand this is to consider how Maven itself is built. It's in Subversion, and the reactor poms (the poms with <modules> sections) tend to also be the parent poms of the modules themselves.
project/pom.xml (artifactId: parent)
|-+ module1/pom.xml (artifactId: module1, inherits parent)
|-+ module2/pom.xml (artifactId: module2, inherits parent)
Here, the parent pom (project/pom.xml) contains a <modules> section, and is also inherited by module1 and module2.
Now suppose the SCM URL for parent is svn://host/path/project/: what should maven do so that you don't have to specify the SCM URL again in the two modules?
Well, the SCM URL for module1 is svn://host/path/project/module1, and Maven can compute that by adding the artifactId to the SCM URL it inherits from the parent pom. It simply needs to append the artifactId to the SCM URL. So that's exactly what it does.
So that's the behaviour you're seeing:
${project.artifactId}.git becomes localized.git/localized as follows:
localized -> from ${project.artifactId} in the inherited SCM URL
.git -> from the the inherited SCM URL
/localized -> from adding the artifactId to the inherited SCM URL
You will see this behaviour in the SCM URLs, and (I think) for project.url and the URL in distributionMangement.site.url. However, Maven doesn't assume that the issueManagement URL structure follows your directory structure, which is why you see it inherited correctly.
Since Maven 3.6.1, inheritance can avoid appending any path to parent value by setting model attribute value to false for each url
src : maven-model-builder
You need to append following properties to SCM tag in your POM :
<scm child.scm.connection.inherit.append.path="false" child.scm.developerConnection.inherit.append.path="false" child.scm.url.inherit.append.path="false">...</scm>
It seems IntelliJ shows error, but at then end, it does the job perfect.
Adding to the already great background information given, in order to still deploy with a valid scm url, since Maven 3.5 you can correct the "module" name that gets appended per the project.directory property:
<properties>
<project.directory>${project.artifactId}</project.directory>
</properties>
And then you just simplify your developerConnection to not include the artifactId anymore since it will be appended as the project.directory:
<scm>
<developerConnection>scm:git:git#server:</developerConnection>
</scm>
Assuming this doesn't conflict with any other goals, that should allow a deploy goal to do its job with the correct git url for a non-multi-module Maven project where you've defined the scm.developerConnection in the parent pom.
When I run a deploy, I see maven doing a correct push like:
[INFO] Executing: /bin/sh -c cd /projectDir/proj && git push git#server:proj master:master

maven: parent-version

I don't understand what is the parent version and for what it should be good?
We use svn in our team and when I did update for the project the last time I notcied that the parent version is changed:
local pom.xml
<parent>
<artifactId>foo</artifactId>
<groupId>bar</groupId>
<version>0.42-SNAPSHOT</version>
</parent>
svn pom.xml
<parent>
<artifactId>foo</artifactId>
<groupId>bar</groupId>
<version>0.45-SNAPSHOT</version>
</parent>
When does parent version change and for what it should be good?
A parent POM contain settings that apply to all child modules. This may include declaring plugin settings or choosing dependency versions.
A parent POM is no different to any other Maven artifact. It can change and when it does the version number must increment. Typically you want to always be using the latest available version of your parent.
You can use the Maven versions plugin to help manage versions, including forcing an update to the latest available parent version.
Parent pom and child pom come into picture if you have a multi-module project. For example like the below
/myapp
|- pom.xml --> parent pom
|+ module1/
| - pom.xml --> child pom
| - src/
|- module2/
There can be several such hierarchies. There are 2 ways to define this inheritance
Add a xml block in parent pom to tell it which are the dependent modules. OR
Add a xml block in a module to tell whose is it's parent. (This is your case)
This means that, the child pom is dependent on parent and will try to find the the concerned artifact with 0.45-SNAPSHOT version. This version has changed probably due to a newer build of parent has taken place replacing the version.

Maven - Access properties on parent pom from a child pom

In a multi module project structure as
myApp
|-moduleA
|---pom.xml
|-moduleB
|---pom.xml
|-pom.xml
If i have the following properties in the parent.pom
<properties>
<moduleA.version>4.67</moduleA.version>
<moduleB.version>4.68</moduleB.version>
</properties>
How can i access the properties in the parent pom from any of the child poms? I tried this on the child pom but it didnt work.
<groupId>com.test</groupId>
<artifactId>moduleA</artifactId>
<version>${moduleA.version}</version>
If you have a real multi-module build you should never define the modules to have different versions. They should have the same version which make releasing possible and other things as well. Otherwise you should not use the multi-module setup than use simple single modules which are separated.
This should work. One possible reason I can think of is that perhaps you don't actually inherit the pom where these properties are defined (i.e. it's not defined as your <parent> directly or indirectly), but you only have a main pom that aggregates your projects. It's a guess, though.

Resources