How to force maven to always download parent pom - maven

I am using a parent pom to share dependencies and plugins across multiple projects. The parent pom is deployed to our nexus repository. In child project, parent pom is included like this:
<project>
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>app-parent</artifactId>
<version>1.0.0</version>
</parent>
<groupId>com.mycompany.app</groupId>
<artifactId>app-web</artifactId>
<version>1.2.0</version>
<repositories>
<repository>
<id>my-internal-site</id>
<url>http://nexus/repo</url>
</repository>
</repositories>
</project>
When parent pom gets updated, would like to keep the same version so child project automatically gets the updated dependencies without updates. However, it seems parent pom is not updated even if I use
mvn clean -U
How do I force maven (maven 3) to always download parent pom from remote repo even if it is already in local repository?

If you have defined such parent which is a release it will be downloaded exactly once. Afterwards it will not downloaded a second time cause release are imutable. As already mentioned you mind need to think about using SNAPSHOT's instead.

you should re-install parent project into your local repo, try run mvn install under app-parent directory!

FWIW I had a case where maven was not downloading a parent but just a .lastUpdated file (which listed a download failure). Even if I ran help:effective-pom it seem to just ignore the fact the parent was undownloadable and absent, and continue on its merry way.
Fix was to upgrade from maven 3.3.3 to 3.3.9

Related

Relative path for Maven pom versions

Forgive my ignorance here, as I'm new to maven. I have a Remote Repository that my project pom is using to download dependencies from. A general structure of my pom.xml is like this:
<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>MVNProject</groupId>
<artifactId>MVNProject</artifactId>
<version>0.0.1</version>
<packaging>war</packaging>
<dependency>
<groupId>org.scala-lang.modules</groupId>
<artifactId>scala-parser-combinators_2.11</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
</project>
Now I know that if I have to get a new version of the dependency scala-parser-combinators I just have to specify the new version. Something like this:
<dependency>
<groupId>org.scala-lang.modules</groupId>
<artifactId>scala-parser-combinators_2.11</artifactId>
<version>1.0.1</version>
</dependency>
But what I would like to do is, without making any change to pom.xml I'd like to replace my old jar with the upgraded jar in my remote repository(which I'm able to do).
So what I'd like to know is whether there is a way to specify in pom to take whatever version is available in the remote repository for a particular artifact i.e., something like this(and this is just a guess):
<dependency>
<groupId>org.scala-lang.modules</groupId>
<artifactId>scala-parser-combinators_2.11</artifactId>
<version>${CurrentVersion}</version>
</dependency>
Some guidance would be very much appreciated.
If you are using maven2, then using LATEST or RELEASE value in version tag can solve the dependency updation automatically. Albeit , this solution will not work in maven3 (it is deprecated).
If you are using maven3, then you have to update the settings.xml a bit. The snapshots repository will get an addition updatePolicy tag. Something like this:-
<repositories>
<repository>
<id>you-snapshots</id>
<url>http://host/nexus/repos/snapshots</url>
<snapshots>
<updatePolicy>always</updatePolicy>
</snapshots>
<releases>
<updatePolicy>always</updatePolicy>
</releases>
</repository>
</repositories>
Also , There is a Versions plugin for Maven which allows you to update your pom to the latest greatest SNAPSHOTS in visible repositories. It does this by inspecting your pom and comparing against remote repositories and then modifying as required.
It is a useful tool but I would definitely like to see an equivalent to the deprecated LATEST option. I find this kind of dependency particularly useful in continuous integration scenarios.
Some things to notice:
You should not delete a specific release version of an artifact from a remote repository and replace it, like having 1.0.1 in your remote repository, removing it and uploading a different artifact under 1.0.1 again. Maven caches release versions in the local repository, so you will never know which artifact you get.
If you have a newer version, give it a newer version number (like 1.0.2).
Now the way to go is not to use RELEASE or LATEST, but to use the versions plugin to update your dependencies (like versions:use-latest-releases).

Maven looks for jar that isn't present in the repository

I have a repository set up on Artifactory for my Maven projects. I have declared this repo in the <repositories> tag of my settings.xml for one of the projects, I have created a dependency on some other prooject (Say projectA) in my POM for a snapshot version. For this projectA, there is only POM artifact on the Artifactory and not a jar. Still when I compile my POM, Maven tries to download the jar for this project and fails saying it couldn't find it.
I shall paste the exact POM, error, settings.xml and repo view soon. Any idea what could be wrong?
If you would like to have a dependency of pom type, you need to explicitly declare it. For example:
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>my-artifact</artifactId>
<version>1.0</version>
<type>pom</type>
</dependency>
If type is not specified, Maven would use the default value which is jar.
Edit from OP: Just a caution, I use IntelliJ and even though I had the settings right in place, it was using some old (probably cached) settings.xml. I ran from commandline and it picked up the right one.

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

How can I deploy only the pom file to my snapshot repository in Maven?

I would like to be able to deploy only the POM artifact (file) without the main artifact (JAR, WAR, etc), when running mvn deploy and version is a SNAPSHOT version.
Why?
We several developers working on multiple Maven projects. We have a Hudson server with a job per Maven project and version (e.g. foo-1.2, foo-1.3). Each job builds the project and deploys it to a Nexus server (upon success). Maven projects under development are marked as such by using -SNAPSHOT postfix in the version. For example: 1.2-SNAPSHOT, 1.3-SNAPSHOT.
Here's a sample scenario how a developer work is damaged due to this architecture.
Assume two Maven projects: foo-core and foo-webapp, both at version 1.2-SNAPSHOT.
Developer A is working on foo-core, made several changes and compiled it.
Developer A continues to work, but on foo-webapp.
Developer B started working and changing foo-core. It commits his work and pushes it to the SCM.
Hudson is triggered by SCM; Builds foo-core and deploys it to the snapshot repository in Nexus.
Developer A is running mvn install on foo-webapp. Maven is checking with Nexus, and finds that there is a newer version of foo-core in Nexus. It downloads it (filled with developer B changes) and than it fails compilation, since the changes made by developer A are not in the jar located in the local repository. The download overrides the file installed there by developer A.
Existing Solutions
I looked into maven-deploy-plugin, but this plugin deploys all artifacts attached to the project. If they had a way to configure which artifacts to deploy, it would have been great.
Question: Is there any way to solve this without resorting to writing my own deploy plugin, based on maven-deploy-plugin?
Basically to the -Dfile parameter, instead of the artifact, pass the pom.xml. Run the command and yay! mvn deploy won't give you any issues now. Here's a sample deploy command :
$ mvn deploy:deploy-file -DpomFile=pom.xml -Dfile=./pom.xml -DgroupId=my.group.id -DartifactId=artifact-id -DrepositoryId=bigdata-upload-snapshots -Durl=http://maven.mymaven.com/content/repositories/snapshots/
A prerequisite for this is that the repository be added in your settings.xml
[Edit]: I have supplied the parameters -DgroupId and -DartifactId of the project in the sample deploy command but they're not required (refer to Zac's comment below)
I never heard of such a possibility and also would be very astonished if that would be possible. As the pom and the resulting artifact are some kind of unit it would make no scence (to me) to deploy only parts of them.
Nevertheless you should consider to make a separate pom project which specified dependencies and plugins you might want to use on your JAR/WAR projects like this:
<groupId>foo.bar</groupId>
<artifactId>my-pom</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
and then inherit that pom project by your JAR/WAR projects like this:
<parent>
<groupId>foo.bar</groupId>
<artifactId>my-pom</artifactId>
<version>1.0.0</version>
</parent>
This is called project inheritance. You can change and deploy your pom project independent of the "child" artifacts.
EDIT after reading motivation:
As I understand you want to prevent maven to resolve SNAPSHOT artifacts from a repository (so that local version won't be overwritten). Have you ever tried to use the mvn -nsu option (see mvn -help)?
-nsu,--no-snapshot-updates Suppress SNAPSHOT updates
I never tried it but found this reported issue. Nevertheless I would give it a try (as the issue is not commented yet).
This works for me for deploying a pom file only (e.g next to an existing jar):
(Note: you need to specify packaging also, otherwise it will be uploaded as an .xml file which is not what you want.)
mvn deploy:deploy-file \
-Dfile=pom.xml \
-Dpackaging=pom \
-DgroupId=com.mycompany.package \
-DartifactId=my-artifact \
-Dversion=2.0.1 \
-DrepositoryId=serverIdFromSettingsXMLForCredentials \
-Durl=http://repositoryserver/myrepo/
Not exactly the answer these folks were asking for. My situation was I wanted to deploy only the parent pom. I'm using the spring-boot-thin-layout in a child module. This requires the parent module be deployed into artifactory. I added the following into my project. It enables skipping of install and/or deploy phase.
In my parent pom:
<properties>
<disable.install>true</disable.install>
<disable.deploy>true</disable.deploy>
<enable.deployAtEnd>true</enable.deployAtEnd>
</properties>
<profiles>
<profile>
<id>deploy-parent</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<disable.install>true</disable.install>
<disable.deploy>true</disable.deploy>
<deployAtEnd>${enable.deployAtEnd}</deployAtEnd>
</properties>
<build>
<finalName>${project.version}</finalName>
</build>
</profile>
</profiles>
And the in my child pom(s) or any module you don't want deployed with parent:
<properties>
<maven.install.skip>${disable.install}</maven.install.skip>
<maven.deploy.skip>${disable.deploy}</maven.deploy.skip>
<deployAtEnd>${enable.deployAtEnd}</deployAtEnd>
</properties>
So effectively when I run mvn deploy on the parent pom, it will compile all the modules, not run install on anything, and then at the end deploy any module not having `

Resources