60

I have big Maven (Tycho) project witch about 400 plug-ins.

We have specified version of application in each POM file.

Is there a way how to specify the version for all POM:s only on one place?

I would expect some think like:

<properties>
<buildVersion>1.1.2-SNAPSHOT</buildVersion>
</properties>

....

<version>${buildVersion}</version>

We have parent pom.xml:

<modelVersion>4.0.0</modelVersion>
<groupId>company</groupId>
<artifactId>build.parent</artifactId>
<version>1.1.2-SNAPSHOT</version>
<packaging>pom</packaging>

Then in each POM is reference to parent POM:

<parent>
  <artifactId>build.parent</artifactId>
  <groupId>company</groupId>
  <relativePath>../build.parent/pom.xml</relativePath>
  <version>1.1.2-SNAPSHOT</version>
</parent>

<modelVersion>4.0.0</modelVersion>
<groupId>company</groupId>
<artifactId>artifact</artifactId>
<version>1.1.2-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
Lii
  • 11,553
  • 8
  • 64
  • 88
Jan Pešta
  • 644
  • 1
  • 5
  • 11

9 Answers9

37

If you have a parent project you can set the version in the parent pom and in the children you can reference sibling libs with the ${project.version} or ${version} properties.

If you want to avoid to repeat the version of the parent in each children: you can do this:

<modelVersion>4.0.0</modelVersion>
<groupId>company</groupId>
<artifactId>build.parent</artifactId>
<version>${my.version}</version>
<packaging>pom</packaging>

<properties>
<my.version>1.1.2-SNAPSHOT</my.version>
</properties>

And then in your children pom you have to do:

    <parent>
      <artifactId>build.parent</artifactId>
      <groupId>company</groupId>
      <relativePath>../build.parent/pom.xml</relativePath>
      <version>${my.version}</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <groupId>company</groupId>
    <artifactId>artifact</artifactId>
    <packaging>eclipse-plugin</packaging>

    <dependencies>
        <dependency> 
           <groupId>company</groupId>
           <artifactId>otherartifact</artifactId>   
           <version>${my.version}</version>
or
           <version>${project.version}</version>
        </dependency>
    </dependencies>

hth

Frederic Close
  • 9,389
  • 6
  • 56
  • 67
  • Currently I have a parent pom, but i am required to have version in there, so it means that each pom have specified verison of parent pom. – Jan Pešta Oct 02 '13 at 08:38
  • if I try to remove both version elements, and keep version only in parent, I got following exception: [ERROR] The build could not read 1 project -> [Help 1] org.apache.maven.project.ProjectBuildingException: Some problems were encountered while processing the POMs: [FATAL] 'parent.version' is missing. @ line 6, column 13 – Jan Pešta Oct 02 '13 at 10:07
  • This works correctly with clean maven project. How should be this configured with tycho (eclipse plugins and Manifest.MF file) also in each manifest file is version written – Jan Pešta Oct 02 '13 at 21:07
  • 26
    [WARNING] Some problems were encountered while building the effective model for company:group1:pom:1.1.2-SNAPSHOT [WARNING] 'version' contains an expression but should be a constant. @ company:maven-test:${my.version}, [WARNING] [WARNING] It is highly recommended to fix these problems because they threaten the stability of your build. [WARNING] [WARNING] For this reason, future Maven versions might no longer support building such malformed projects. – Jan Pešta Oct 02 '13 at 21:15
  • So why is that in dependencies you can refer to `${project.version}`, but in `` you can't? – ACV Feb 28 '18 at 00:31
  • 12
    With the new version of Maven this feature will not work anymore! – Blindworks Mar 20 '18 at 11:55
  • 1
    It worked for me with maven 3.5.4, notice that neither 3.5.2 nor 3.6.0 worked. – Searene Mar 07 '19 at 06:12
  • IntelliJ 2020.3 with Maven 3.6.3 is also highly confused by this. Maven on the CLI throws many warnings but ultimately seems to work? – jocull Jan 28 '21 at 17:56
  • 2
    Better follow the other answers, using mvn versions:set - the amout of trouble you're going to run into with versions as properties is just not worth it – Bart Robeyns Feb 27 '21 at 16:59
28

The correct answer is this (example version):

  • In parent pom.xml you should have (not inside properties):

    <version>0.0.1-SNAPSHOT</version>
    
  • In all child modules you should have:

    <parent>
        <groupId>com.vvirlan</groupId>
        <artifactId>grafiti</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    

So it is hardcoded.

Now, to update the version you do this:

mvn versions:set -DnewVersion=0.0.2-SNAPSHOT
mvn versions:commit # Necessary to remove the backup file pom.xml

and all your 400 modules will have the parent version updated.

Community
  • 1
  • 1
ACV
  • 9,964
  • 5
  • 76
  • 81
  • 4
    And this modified the pom.xml files, meaning that the subsequent build happens from modified source code, which I find objectionable. – Bob Bell Mar 13 '19 at 19:22
  • @BobBell it is not possible to update the version without modifying pom files. – ACV Sep 05 '19 at 15:57
  • 6
    @ACV That is not true. You can build with alternative version of you use `${revision}` and pass `-Drevision` on the command line. – Bob Bell Sep 06 '19 at 17:54
  • @BobBell , i am passing through command line oly, but in .m2 folder pom is not updated with placeholder value. could you please help me to resolve this issue – Dev Nov 04 '20 at 06:40
  • 1
    @Dev Are you using `-Drevision`, or `-DnewVersion`? Only limited properties can be updated via the command line. See https://maven.apache.org/maven-ci-friendly.html – Bob Bell Nov 05 '20 at 18:43
16

Using a property for the version generates the following warning:

[WARNING]
[WARNING] Some problems were encountered while building the effective model for xxx.yyy.sandbox:Sandbox:war:0.1.0-SNAPSHOT
[WARNING] 'version' contains an expression but should be a constant. @ xxx.yyy.sandbox:Sandbox:${my.version}, C:\Users\xxx\development\gwtsandbox\pom.xml, line 8, column 14
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]

If your problem is that you have to change the version in multiple places because you are switching versions, then the correct thing to do is to use the Maven Release Plugin that will do this for you automatically.

  • 1
    Can you explain how the maven release plugin fixes this issue? – Basil Musa Dec 14 '15 at 19:35
  • Well, it actually does not fix the problem reported because that is not the right way of doing things, so you should not set the version of your project in a property. If your project has multiple modules then the right thing to do is to let the Release plugin do the work of changing the version in all pom.xml files for you. – Constantino Cronemberger Dec 16 '15 at 10:38
  • 2
    I would say that using Maven release plugin is the correct way. In our case we use update POM command to set version of all modules to parent like so: `mvn release:update-versions -DautoVersionSubmodules=true` – Mihkel Selgal May 04 '16 at 07:58
  • 3
    This involves modifying the POM, meaning that a source code controlled file is now modified, which I find objectionable. – Bob Bell Mar 13 '19 at 20:00
  • 1
    The objective is to change the version. The discussion here is whether is can be done in a single place or not. – Constantino Cronemberger Mar 14 '19 at 10:50
15

See the Maven - Users forum 'version' contains an expression but should be a constant. Better way to add a new version?:

here is why this is a bad plan.

the pom that gets deployed will not have the property value resolved, so anyone depending on that pom will pick up the dependency as being the string uninterpolated with the ${ } and much hilarity will ensue in your build process.

in maven 2.1.0 and/or 2.2.0 an attempt was made to deploy poms with resolved properties... this broke more than expected, which is why those two versions are not recommended, 2.2.1 being the recommended 2.x version.

Gerold Broser
  • 14,080
  • 5
  • 48
  • 107
  • First as this is end project, there is no risk with dependencies resolving .) Second, we already moved out of this with pomless build, which I would really recomend. Third, do not know how to insert line in comment without sending it directly:( – Jan Pešta Mar 28 '19 at 16:21
  • @JanPešta What do you mean by "_pomless build_"? Comments here at SO do not support explicit new lines. – Gerold Broser Aug 10 '21 at 12:29
  • As I mentioned this is tycho based project where everythink is defined in manifest files, and we used pom only for building. so pomless build is a way where pom are generated from manifest and they do not need to be stored in repo – Jan Pešta Aug 16 '21 at 08:18
  • @JanPešta I see. It's called _POM first_ vs. _MANIFEST first_. See also [_Should I use POM first or MANIFEST first when developing OSGi application with Maven?_](https://stackoverflow.com/q/11373009/1744774). – Gerold Broser Aug 16 '21 at 08:29
  • It is not, MANIFEST first require pom for bundles and to be in sync with manifest, but pomless does not require pom for every bundle. – Jan Pešta Aug 18 '21 at 06:10
  • @JanPešta I see. I was irritated by _Maven build without a POM_ which is a contradiction in itself. :) I think it's one of the advantages of Maven that the build config of a project is stored in the project's SCM repo (since with the declarative nature of POMs it's also a description of and a documentation for the entire project). That, for instance, also is what the relatively new SCM-stored `Jenkinsfile`s on Jenkins are about (for e.g. reproducable builds). I agree that some things are more complicated as soon as OSGi comes into play. – Gerold Broser Aug 18 '21 at 13:38
12

With a Maven version of 3.5 or higher, you should be able to use a placeholder (e.g. ${revision}) in the parent section and inside the rest of the POM, you can use ${project.version}.

Actually, you can also omit GAV properties outside of <parent> which are the same, as they will be inherited. The result would look something like this:

<project>
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>build.parent</artifactId>
        <groupId>company</groupId>
        <version>${revision}</version>  <!-- use placeholder -->
        <relativePath>../build.parent</relativePath>
    </parent>

    <artifactId>artifact</artifactId>
    <!-- no 'version', no 'groupId'; inherited from parent -->
    <packaging>eclipse-plugin</packaging>

    ...
</project>

For more information, especially on how to resolve the placeholder during publishing, see Maven CI Friendly Versions | Multi Module Setup.

Gerold Broser
  • 14,080
  • 5
  • 48
  • 107
Kariem
  • 4,398
  • 3
  • 44
  • 73
  • 3
    This is producing warnings and asking to use constant version, but still depending on this – Davut Gürbüz Jan 30 '19 at 14:56
  • @DavutGürbüz It does not here (with Maven 3.6.0 and if you follow the instructions on the the linked page [Maven CI Friendly Versions](https://maven.apache.org/maven-ci-friendly.html)). – Gerold Broser Mar 27 '19 at 16:29
5

If you're using Maven 3, one option to work around this problem is to use the versions plugin http://www.mojohaus.org/versions-maven-plugin/

Specifically the commands,

mvn versions:set -DnewVersion=2.0-RELEASE
mvn versions:commit

This will update the parent and child poms to 2.0-RELEASE. You can run this as a build step before.

Unlike the release plugin, it doesn't try to talk to your source control

rince
  • 1,988
  • 1
  • 20
  • 24
0

I have two recommendation for you

  1. Use CI Friendly Revision for all your artifacts. You can add -Drevision=2.0.1 in .mvn/maven.config file. So basically you define your version only at one location.
  2. For all external dependency create a property in parent file. You can use Apache Camel Parent Pom as reference
Hemang
  • 1,351
  • 1
  • 10
  • 20
0

I have successfully resolved the issue thus:

In parent pom.xml I have sited the version as usual (not inside properties):

<version>0.0.1-SNAPSHOT</version>

In all child modules I used:

<parent>
   <groupId>com.example</groupId>
   <artifactId>parent-module</artifactId>
   <version>0.0.1-SNAPSHOT</version>
</parent>

Then I changed the parent to:

<version>0.0.2-SNAPSHOT</version>

Now, to update the version I executed in the command line:

mvn -N versions:update-child-modules

The children have been updated automatically to:

<parent>
   <groupId>com.example</groupId>
   <artifactId>parent-module</artifactId>
   <version>0.0.2-SNAPSHOT</version>
</parent>

In other words I have used the versions:update-child-modules goal.

I have found this solution here.

Angelina
  • 1
  • 1
-4

The version of the pom.xml should be valid

<groupId>com.amazonaws.lambda</groupId>
<artifactId>lambda</artifactId>
<version>2.2.4 SNAPSHOT</version>
<packaging>jar</packaging>

This version should not be like 2.2.4. etc

Sandun Susantha
  • 1,010
  • 1
  • 10
  • 11