Maven how set absolute path for parent pom - maven

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.

Related

Relative Path in Maven parent definition

In defining a parent artifact, do I need to include the in the child's pom? For example,
Is the <relativePath> optional or required?
<parent>
<groupId>org.hibernate.tutorials</groupId>
<artifactId>hibernate-tutorials</artifactId>
<version>5.1.0.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
It is not required. From the docs:
relativePath: The relative path of the parent pom.xml file within the check out. If not specified, it defaults to ../pom.xml. [...]
This means that you can omit this element and it will default to exactly what you already have, i.e. Maven will look for the parent POM in ../pom.xml which is one directory up.
according to the maven doc :
Notice the relativePath element. It is not required, but may be used as a signifier to Maven to first search the path given for this project's parent, before searching the local and then remote repositories.

Maven Company POM name

I want to set up a (master/parent) company pom that will be used for projects. Now what is the most common name approuch for this?
Name the artifact after the company name or is using an artifact like "pom" also good?
<groupId>com.company</groupId>
<artifactId>company</artifactId>
<version>1.0</version>
<groupId>com.company</groupId>
<artifactId>pom</artifactId>
<version>1.0</version>
Because you have to make a seperated VCS for it also. And when you go for the first option (company/company) that repository can't be used for anything else. Or making a branch (named: pom) will solve this? Maybe it's just better to make a new repo for the pom?
https://github.com/company/company.git
https://github.com/company/pom.git
A couple of points here:
don't call it a 'master', master is a common shortening for 'aggegration-pom'. What you want is a parent.
It is good practice to:
include the word -parent in your parent name
use the realm/scope of the parent in the name (company in your case)
also: the artifactId should be understandable by itself
give single version numbers (1 or 10 or 15 instead of 1.0) because you will seldom if ever use a bugfix version
use a single repository for your parent (yes, it is quite empty). But if it has a separate lifecycle, it should have a separate repository.
so, don't call it pom or company, because both is misleading:
<groupId>com.company</groupId>
<artifactId>company-parent</artifactId>
<version>1</version>
If your company does other projects besides maven projects, it might also make sense to name the repository (not the artifactId) company-maven-parent.

Get version from directory name

I have bunch of projects. All of them must have the same version = branch directory name("7.15.0" for example).
To achieve that, i make one parent pom with code:
<version>${branch}</version>
<properties>
<branch>${project.file.parentFile.parentFile.parentFile.name}</branch>
</properties>
Most of my projects and subprojects are in directories, where ../.. is branch directory. Their poms contains this:
<parent>
<groupId>parentPomGroupId</groupId>
<artifactId>parentPomArtifactId</artifactId>
<version>${branch}</version>
</parent>
But not all projects is on the same level, so i must control and check where they is, and if needed add to their pom correct branch path:
<properties>
<branch>${project.file.parentFile.parentFile.name}</branch>
</properties>
also when project builds, in the log i see :
[INFO] Building appcore-utils ${project.file.parentFile.parentFile.name}
If i set constant in branch - log contains version. Tell me please, how can i resolve property "branch" only once in my parent pom? So if i use ${branch} in child project, it resolves to constant, which already calculated in parent pom. Or maybe there is another way to use branch directory name in version of projects?
I don't think that the goal you're trying to achieve is valid in terms of the current (3.1+) maven. The version tag now should be filled with a constant despite the fact that a while ago it could be possible to use an expression there as described in Maven version with a property , look at the last comment by #JanPeta. BTW the solution by Frederic Close doesn't work anymore (for maven-3.1.1 installed in my system).
Alternatively you can change the version of the artifacts generated in your project, and I have a working solution for that (instead of taking version from a directory name, I use git describe... output) but it's really, really ugly and now I think it's not worth the time I spent fixing all the issues with this approach.

Tell Maven to look in repos for parent pom before looking in file system

Per Maven documentation Maven will only look in local and remote repos for a parent pom after it fails to find it locally. The best solution I've found to dummy this out is by adding
<relativePath>.</relativePath>
which is obviously a kludge and produces warnings (as it well should). Maven seems to be like file-system coupling when dealing with parent modules and multi-module projects so this is the only way I see to have both of those co-exist without something that feels obviously wrong (e.g. inheriting from a filesystem child).
You reference the parent pom using the tag:
<parent>
<groupId>com.mycompany</groupId>
<artifactId>my-parentpom</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
You must install the parent pom into your local repo using the mvn install -N command from the directory that contains the parent POM.

Maven: Selecting Parent Project Based On Profile

I have a maven project - it is a plugin for jenkins. It's parent should be a:
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>1.414</version>
</parent>
But at the same time this plugin can be also used for hudson, without changing any line of code. But the parent project for it should be:
<parent>
<groupId>org.jvnet.hudson.plugins</groupId>
<artifactId>hudson-plugin-parent</artifactId>
<version>2.0.1</version>
</parent>
Can I specify 2 different profiles for that and use them to build plugin for jenkins or hudson accordingly? So that I call something like that:
mvn package -P jenkins
or
mvn package -P hudson
I have tried to specify properties in profiles, but those are not replaced by their values inside the <parent> tag. So is there any other possibility to build plugin for both, but with as much as possible common code and files?
Added: So, if I cannot do that, what should I do then? How to refactor? What the new structure should be?
As already mentioned, this is not possible.
Also, it is not possible to set a property for the parent's version as the interpolation for that happens a lot earlier than the handling of the profiles.
I would suggest that you create a masterbuild project as follows:
master
|-plugin-jenkins
|-plugin-hudson
|-plugin-assembly
The master should build all three as usual. However, in the assembly, you could add each of the two plugins as dependencies in separate profiles. And... each of these plugins can have the parent you like.
This is obviously somewhat a deviation from the Maven convention, but I believe it is a solution to your problem.
It's not possible because the tag "parent" is not available in the profiles section of the pom.
Currently we decided to stick with 1 repository and 2 separate pom.xml files, giving maven key which pom.xml use to build the project.
mvn package -f pom-jenkins.xml
mvn package -f pom-hudson.xml
No you cannot do that. you will have to refactor somehow to avoid the necessity.
As mentioned already not possible. I would suggest to make separate projects for jenkins plugin and hudson plugin. I assume that in not that far future that will not work anymore cause Hudons and Jenkins will diverge.
In general, you should be able to set the {group,artifact}Id and version of the parent POM via Java System Properties or Environment Variables, but it seems there is a Bug in Maven which will only be fixed in 4.x:
https://issues.apache.org/jira/browse/MNG-624
Another solution is to delegate the inclusion of the parent POM to your own parent POMs which you reference in the relativePath element, and change the content of the target e.g. via a symlink or cp command.
So in the main POM you would write:
<parent>
<groupId>org.mycompany.project</groupId>
<artifactId>foo-artifact</artifactId>
<version>1.0.0</version>
<relativePath>./my-parent.pom</relativePath>
</parent>
And in my-parent-jenkins you would just put:
<groupId>org.mycompany.project</groupId>
<artifactId>foo-artifact</artifactId>
<version>1.0.0</version>
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>1.414</version>
</parent>
The same project information with the block for hudson you put in my-parent-hudson.pom.
No you can either use
ln -s my-parent-jenkins.pom my-parent.pom
or
ln -s my-parent-hudson.pom my-parent.pom
to include the respective parent POM without the need to maintain two different main POM files for your project.
In case POM does not exist at the place referenced in relativePath, Maven will look up the POM in the remote repository[1], which is also an easy way to overwrite a parent POM locally.
[1] http://maven.apache.org/components/ref/3.3.9/maven-model/maven.html#class_parent

Resources