Maven plugin dependency cannot use parent pom property - maven

I'm hitting a weird edge use case with Maven & curious why it's behaving the way it does.
I'm defining a property in my parent project like so:
<properties>
<some.property.version>1.0.0.0</some.property.version>
</properties>
Now, in a module, I set a version of a dependency for a plugin like so:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>bob</artifactId>
<version>1.0.0.0</version>
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>example</artifactId>
<version>${some.property.version}</artifactId>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
This causes Maven to spit out an error:
[ERROR] 'build.plugins.plugin[org.apache.maven.plugins:bob].dependencies.dependency.version' for org.example:example:jar must be a valid version but is '${some.property.version}'. # line 350, column 16
What's bizarre to me is if I move the property being defined down into the module itself, Maven compiles just fine. Is this a bug? Or are there restrictions of visibility to parent pom properties in a plugin for a module?

An insanely fast response from the Apache Maven's distribution list! The parent pom had been refactored, and the module was pointing to the stale parent's artifactId. Kudos to Robert!
Hi,
This makes me wonder if the "right" parent is used, so please double
check the groupId, artifactId and version. If both parent and module
are part of the same multi-module, be sure that the relativePath is
correct (defaults to ../pom.xml) You could also use "mvn
org.apache.maven.plugins:maven-help-plugin:2.2:effective-pom" to
verify that the property is really there with the expected value. If
this is all as expected, then it seems to be a bug.
thanks, Robert

Related

Maven copy parents declared in the POMs

My final goal is to create a Maven repository in a certain directory containing only a certain set of artifacts and all their dependencies.
For this I use the following command:
mvn.bat dependency:copy-dependencies -f dependencies.pom
-DoutputDirectory=localRepoDir -Dmdep.useRepositoryLayout=true
-Dmdep.copyPom=true -Dmdep.addParentPoms=true
dependencies.pom being:
<project>
<modelVersion>4.0.0</modelVersion>
<description>Dependencies</description>
<groupId>com.dummy</groupId>
<artifactId>dummy</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>com.dependency1</groupId>
<artifactId>dep1</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.dependency2</groupId>
<artifactId>dep2</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
When doing this, I notice that parents declared in the dependencies' poms are not copied from the .m2 Local maven repository to the destination directory.
Perhaps I'm missing something and there's a better way to do this, since it's kind of a hack to use a pom file to declare the artifacts I want to copy (together with their dependencies).
Turns out that maven was using version 2.8 as default for the dependency plugin. When explicitly indicating it to use the latest version (2.10), it worked just fine.
The addParentPoms parameter was already introduced on 2.8 for copy-dependencies, so I guess it must be a bug in the 2.8 release.
mvn org.apache.maven.plugins:maven-dependency-plugin:2.10:copy-dependencies

maven release:perform with Perforce does not create target/checkout directory

I can not make the maven-release plugin work with Perforce. The release:prepare seems to work correctly: a Perforce label is created and it contains the correct files. Yet when I run release:perform it fails because the target/checkout directory is empty.
I've done some experiments. If I only sync to my pom.xml and then run
mvn scm:checkout
then my other files are checked out into the P4 root directory just as if I had done a
p4 sync ...
Yet Maven outputs
[INFO] Checkout working directory: /home/chris/perforce/pips/target/checkout
[INFO] sync -f //depot/pips/...
Maven thinks it's checking out the target/checkout but it is not. I dug into the P4Maven code a little bit and noticed this in P4Executor.java
public String getRepoPath(P4ScmProviderRepository repo, File basedir) {
// Handles a case where executing release:prepare on a module with an
// invalid SCM location. The release.properties contains the invalid URL
// for checkout during release:perform and the basedir is not the module
// root. So, the trailing target/checkout directory must be removed.
if (basedir.toString().replace('\\', '/').endsWith("/target/checkout")) {
String dir = basedir.toString();
basedir = new File(dir.substring(0, dir.length()
- "/target/checkout".length()));
if (getLogger().isDebugEnabled()) {
logger.debug("Fixing checkout URL: " + basedir);
}
}
This code is pretty clear. P4Maven won't check things out to target/checkout. If you tell it to checkout to target/checkout it will simply remove the "target/checkout" and checkout to the root directory. This is consistent with what I see being done. I also see the "Fixing checkout URL" message when I run release:perform
How then do people work around this?
Below is my pom.xml. I am using
Perforce Server version: P4D/LINUX26X86_64/2014.2/935585 (2014/09/16). p4d is running locally. Authentication is disabled and I don't need a password.
Nexus 2.10.0-02 running locally.
Ubuntu Linux.
Maven 3.2.3
java 1.7.0_55
Thanks.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.ap
ache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.icap</groupId>
<artifactId>pips</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>pips</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<scm>
<connection>scm:p4:192.168.1.8:1666://depot/pips</connection>
<developerConnection>scm:p4:192.168.1.8:1666://depot/pips</developerConnection>
</scm>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-scm-plugin</artifactId>
<version>1.4</version>
<dependencies>
<dependency>
<groupId>com.perforce</groupId>
<artifactId>p4maven</artifactId>
<version>[2011,2012)</version>
</dependency>
</dependencies>
<configuration>
<connectionType>connection</connectionType>
<username>chelck</username>
<includes>**</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.1</version>
<dependencies>
<!-- P4Maven -->
<dependency>
<groupId>com.perforce</groupId>
<artifactId>p4maven</artifactId>
<version>[2011,2012)</version>
</dependency>
</dependencies>
<configuration>
<connectionType>connection</connectionType>
<username>chelck</username>
<includes>**</includes>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<fork>true</fork>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<distributionManagement>
<repository>
<id>deployment</id>
<name>Internal Releases</name>
<url>http://localhost:8081/nexus/content/repositories/releases/</url>
</repository>
<snapshotRepository>
<id>deployment</id>
<name>Internal Releases</name>
<url>http://localhost:8081/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
</project>
I have struggled for several days on perforce / maven / release integration and finally got it working. Here are my findings, they might help you and others with similar issues.
Do not use the perforce plugin as described on perforce.com (http://www.perforce.com/perforce/r11.1/manuals/p4maven/index.html). Although it is the first link to come out of a search on google, my understanding is that this plugin is outdated.
In your configuration, if you refer to scm:p4:... you are using the com.perforce plugin. Instead, use org.apache.maven.scm/maven-scm-provider-perforce which uses scm:perforce:... syntax. Your <scm> should look like this:
<properties>
<p4path>//perforce-path/toyour/project</p4path>
</properties>
<scm>
<connection>scm:perforce:yourp4server:1666:${p4path}</connection>
<developerConnection>scm:perforce:yourp4server:1666:${p4path}</developerConnection>
<url>perforce:yourp4server:1666:${p4path}</url>
</scm>
The newer plugin does not require username/password, it will use your active P4 credentials.
I am using maven 3.2.5 and did not have to specify any plugin dependency. The built-in scm recognized the :perforce: scm and downloaded maven-scm-provider-perforce 1.9.2 which is the latest as of this writing. You can make sure you are using an up to date plugin by deleting the maven-scm-provider-perforce folder in .m2\repository\org\apache\maven\scm and then doing a mvn scm:status - it will download the missing plugin and you can see which one it picked.
Here is my maven-release-plugin definition:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.1</version>
</plugin>
I do not have a maven-scm-plugin definition in my pom (I used the default settiings from the superpom).
Test on a non-module project.
You should be able to do the following without error:
- mvn scm:status to check that your scm setup is working correctly
- mvn release:prepare
- mvn release:perform
If you get errors, rollback (mvn release:rollback), make sure everything is back to normal, and rerun with mvn -X to get more details.
In my case, a non-modular project worked without much trouble.
Test on the parent of a reactor project.
There are a few things that were not obvious to me at first and that I found out:
When the is defined in the parent pom, the child module name gets appended to the path for the child module. If your child is not physically under the parent (in my case, it was beside), you need to redefine a configuration in the child pom. In my case, I was using a property (p4path above), simply changing its value was not enough. This was counter-intuitive since the parent pom is normally just a "include", and I expected the parent definitions to be "copy-pasted" in the child module, but in this particular case, it is modified to include the module name at the end of the scm path when it is copy-pasted. [More on modules that do not sit under the parent directory below]
A temporary client spec is created by the perforce scm plugin. This was also counter intuitive, I expected the scm plugin to use my current client-spec. Instead, it will create a new one on the fly, and populate it with the path you provided only and name it username-hostname-MavenSCM-localpath. I was initially surprised by that and tried to change it so it would use by client-spec by customizing the maven.scm.perforce.clientspec.name property, this behaviour was actually correct. With this temporary client-spec, the plugin can limit the lookup for changes, the submit and tagging to this directory. It also makes it easy to track what was done by this plugin in the perforce history.
Creation of the temporary client spec will fail if the modules are not under the parent directory. As I described above, my modules were sitting beside the parent. My <module> tag in the parent pom referred to them using <module>../mymodule</module> which worked fine in eclipse for everything else. The scm perforce plugin includes modules in the client spec by appending the path to the module to the path of the parent. Since Maven resolves the ../ to an absolute path, the client spec ends up containing something like this: //perforce-path/toyour/project/C:\Path\To\Your\Project/mymodule/ and the client spec fails. I could not find a work around for this issue other than moving my modules under their parent. Since the client spec was invalid, I had no file being checked-out under target/checkout. You will get the content of your generated client spec on the console by using mvn -X when invoking release:perform.
Moral of the story: You want to make sure that all your modules sit under their parent directory. When you do this, everything becomes simple and magical: you can leave the declaration in your parent pom and the module path gets magically appended for the module scm paths. You can refer to your modules using <module>mymodule</module> which gets correctly appended in the client-spec. Tagging of the parent in perforce ends up also tagging the modules since they are contained within.

Update maven properties after a new release, using versions plugin

Im having a problem with a multimodule project in maven/jenkins.
For example my structure is like this:
---ProjectA
----pom.xml
--------ModuleA
---------pom.xml
--------ModuleB
---------pom.xml
---ProjectB
-----pom.xml
For example ModuleA has a dependency for something in ProjectB which is defined in ModuleA's pom except for the version which is only defined as property and is inherited from ProjectA's properties section.
I want to automate the release process to get rid of all the manual update of versions in all the poms. So after making a release of ProjectB I what to bump all references in ProjectA.
EDIT
More accurate I want to Release ProjectB which has to include a release of ProjectA (because of dependencies) and in the new Snapshots of ProjectA I want references to the newest ProjectB there is.
The maven plugin versions does this pretty well if one would specify the dependency and the version number in the same pom. My problem as you can see is that (I'm speculating) when version plugin tries to check the property field in ProjectA's pom the property can't be associated with a dependency. And I guess that versions plugin looks on the effective pom because it CAN find that the dependency in ModuleA's pom should be updated. It just can't update it due to the fact that its not defined there.
Would be much obliged for a solution which could keep my properties in the parent pom.
Thanks
Ok. SO I think I've worked something out, but i'll post it here for others to see.
So the thing I think is the problem is that the autoLinkItem only searches the current file for linkage and if you want a property to get assosiated with a dependency not specified in the same file one could explicitly tell the plugin in this.
Like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>1.2</version>
<configuration>
<properties>
<property>
<name>basis.version</name>
<dependencies>
<dependency>
<groupId>com.mycompany.app.basis</groupId>
<artifactId>ModuleBasis</artifactId>
</dependency>
</dependencies>
</property>
</properties>
<includeProperties>basis.version</includeProperties>
<generateBackupPoms>false</generateBackupPoms>
<allowSnapshots>true</allowSnapshots>
</configuration>
</plugin>

maven release plugin with parameterized version

is it possible to use the maven release plugin with a multi-module project, where some of the inter-module dependencies are specified using a parameter from the parent pom?
When I try to call release:prepare i get the following error:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-release-plugin:2.1:prepare (default-cli) on project forest-parent: The version could not be updated: ${some.version} -> [Help 1]
Here is my plugin definition:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.1</version>
<configuration>
<goals>deploy</goals>
<tagBase>https://svn.domain.com/svn/project/tags</tagBase>
<autoVersionSubmodules>true</autoVersionSubmodules>
<tagNameFormat>#{project.version}</tagNameFormat>
</configuration>
</plugin>
Thanks in advance!
The plugin currently doesn't support parameterized versions from parent (tried v2.2.2 as well). The solution was to use {project.version}.
TL;DR: Accepted answer does not help; Known defect in maven-release-plugin; New CI-Friendly versions in maven 3.5 help somewhat (but don't really solve the OPs issue)
Long version:
The accepted answer doesn't work. I experimented and found the results commented by #Dormouse. Adding this answer for more clarification:
Prefixing the variable name with "project." gets maven release:prepare past the original error, but it will update the version of the custom-versioned module to match all the others
So, as #Dormouse states, the property is useless because after the first maven release call it will no longer refer to the correct version of the module.
For example - some excerpts from a demonstration:
parent pom.xml:
<version>1.0-SNAPSHOT</version>
<properties>
<!-- note the custom property starts with "project" to pass release:prepare -->
<project.version.custom>1.2-SNAPSHOT</project.version.custom>
</properties>
<modules>
<module>custom-versioned-module</module>
<module>dependent-module</module>
</modules
custom-versioned-module/pom.xml:
<parent>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>custom-versioned-module</artifactId>
<!-- this module has 1.2-SNAPSHOT instead of 1.0-SNAPSHOT like the rest -->
<version>1.2-SNAPSHOT</version>
dependent-module/pom.xml
<parent>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>dependent-module</artifactId>
<dependencies>
<dependency>
<artifactId>custom-versioned-module</artifactId>
<!-- experiment with variable version -->
<version>${project.version.custom}</version>
</dependency>
</dependencies>
Now try mvn release:prepare -DdryRun=true and examine the files created. (You can see what the release:perform would do by looking at pom.xml.next - this is used to replace pom.xml if you do not use -DdryRun)
You will see that the version property is left intact, as is the dependency (we wouldn't expect the maven-release-plugin to mess with those), but the actual version of custom-version-module is changed!
custom-versioned-module/pom.xml.next:
<parent>
<version>1.1-SNAPSHOT</version>
</parent>
<artifactId>custom-versioned-module</artifactId>
<version>1.1-SNAPSHOT</version>
The parent version is increased from 1.0 to 1.1, but the module version is decreased from 1.2 to 1.1 (it's simply made the same, not specifically decremented)
Meanwhile the property itself remains at 1.2 so if you actually release, the next build will fail.
Note that this is logged as maven defect here: https://issues.apache.org/jira/browse/MRELEASE-782
And it is somewhat mitigated by the CI-Friendly versioning in 3.5:
https://maven.apache.org/maven-ci-friendly.html

Maven settings.xml property is not resolved in transitive dependency

I have a property in settings.xml,
fwk.version = "2.0.001"
Other side, a multiproject with two projects, earmodule and ejbmodule.
ejbmodule has a dependency:
<dependency>
<groupId>shared-lib</groupId>
<artifactId>proxi2.fwk.comuns</artifactId>
<version>${fwk.version}</version>
<type>pom</type>
</dependency>
and it's works correctly
but earmodule has a dependency on ejbmodule
<dependencies>
<dependency>
<groupId>projectGroup</groupId>
<artifactId>ejbmodule</artifactId>
<version>1.0</version>
<type>ejb</type>
</dependency>
</dependencies>
and it tries to solve the dependency and it fails:
[WARNING] Missing POM for shared-lib:proxi2.fwk.comuns:pom:${fwk.version}
instead trying to download
shared-lib:proxi2.fwk.comuns:pom:2.0.001
It happens when i try to package parent project.
Looks like a bug in Maven3
Do you know why?
Thx
EDIT:
Our solution/workaround has been defining in parent pom a dependencyManagement section because in this level works ok.
Then in subproject ejbmodule, we have an "independent version" dependency because uses parent definition in dependencyManagement
settings.xml:
<fwk.version>2.0.001</fwk.version>
parent pom:
<dependencyManagement>
<dependency>
<groupId>shared-lib</groupId>
<artifactId>proxi2.fwk.comuns</artifactId>
<version>${fwk.version}</version>
<type>pom</type>
</dependency>
</dependencyManagement>
ejbmodule pom:
<dependency>
<groupId>shared-lib</groupId>
<artifactId>proxi2.fwk.comuns</artifactId>
<type>pom</type>
</dependency>
I hope this would help other
Looks like there is an open maven bug related to this.
I see a similar problem only in a different situation. I used a property to define a URL where to send my created javadocs like this
<distributionManagement>
<site>
<id>javadocs</id>
<name>Java Documentation</name>
<url>scp://${javadocs.url}/${project.groupId}/${project.artifactId}/${project.version}</url>
</site>
</distributionManagement>
And of course I set the property in my settings.xml in a profile
</settings>
.
.
<profiles>
<profile>
<id>develop</id>
<properties>
<environment.type>develop</environment.type>
<javadocs.url>javadocs.server.com/home/javadocs/javadocs</javadocs.url>
</properties>
.
.
<activeProfiles>
<activeProfile>develop</activeProfile>
</activeProfiles>
</settings>
The distributionManagement section was put into the pom of project parent which was used as parent in the project child
When doing
mvn site-deploy
in the child project I got this error:
[ERROR] Failed to execute goal
org.apache.maven.plugins:maven-site-plugin:3.0:deploy (default-deploy)
on project child: Error uploading site: Cannot connect. Reason:
java.net.UnknownHostException: ${javadocs.url} -> [Help 1]
So clearly the property was not set anymore.
The only workaround I can think of is to put the properties in the parent pom. I know this is terrible because if you want to change them you need to redeploy.
Following the fact that this issue seems due a bug of Maven and it is apparently not expected to be fixed soon, I have found a simple workaround that seems work for me.
Instead that defining a variable with dot notation like fwk.version, try a snake case like fwk_version. I tried it tp define in my settings.xml url of repositories and it works.
Reference: I found this from this post http://maven.40175.n5.nabble.com/Settings-properties-not-resolved-when-used-in-repository-element-td5746974.html
I hope it can help also in transitive dependencies.

Resources