Maven

Maven parent version

It most cases when we need maven, we need a parent child like structure. I personally like to start my projects with a parent bom file where I manage all my dependencies and plugins.

https://unsplash.com/@vikceo
<?xml version="1.0" encoding="UTF-8"?>
<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>   
    
<artifactId>commons</artifactId>   
<packaging>pom</packaging>   
<version>1.0-SNAPSHOT</version>  
  <parent>     
    <groupId>com.sergiuoltean.test</groupId>     
    <artifactId>bom</artifactId>     
    <version>1.0-SNAPSHOT</version>      
    <relativePath/>  
  </parent>
</project>

Now I need to put the version of the parent which is fine for this situation. But what happens when we need layering of our application. Given a 3 tier architecture we would have 3 maven modules(eg presentation, services and data access). Let’s assume this is a microservice and we need to version it.

Take for example the presentation module definition

 <parent>
    <groupId>com.sergiuoltean</groupId>
    <artifactId>maven-parent</artifactId>
    <version>1.0.0</version>
  </parent>

  <artifactId>presentation</artifactId>
  <version>${project.parent.version}</version>

We see there the parent version tag which is hardcoded. If we remove it maven will complain.

[ERROR] The build could not read 1 project -> [Help 1]
[ERROR]   
[ERROR]   The project com.sergiuoltean:presentation:${project.parent.version} (/Users/sergiuoltean/fun/maven-parent/presentation/pom.xml) has 1 error
[ERROR]     'parent.version' is missing. @ line 7, column 11
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingException

If we try to put an expression maven will complain

 <parent>
    <groupId>com.sergiuoltean</groupId>
    <artifactId>maven-parent</artifactId>
    <version>${prj.version}/version>
  </parent>

  <artifactId>presentation</artifactId>
  <version>${project.parent.version}</version>
</parent>
[ERROR] The build could not read 1 project -> [Help 1]
[ERROR]   
[ERROR]   The project  (/Users/sergiuoltean/fun/maven-parent/presentation/pom.xml) has 1 error
[ERROR]     Non-parseable POM /Users/sergiuoltean/fun/maven-parent/presentation/pom.xml: end tag name </parent> must match start tag name <version> from line 10 (position: TEXT seen ...<version>${prj.version}/version>\n  </parent>... @11:12)  @ line 11, column 12 -> [Help 2]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingException
[ERROR] [Help 2] http://cwiki.apache.org/confluence/display/MAVEN/ModelParseException

If we keep it hardcoded the release will not be as straightforward as we would have liked. We need to go in each module and change the parent version when we prepare a new release. And on top of that there is room for mistakes(eg forget to change the parent to a module which means it may reference the previous parent). Now ideally during development the modules should have a snapshot version in which case maven release plugin may be of help.

There is also Maven CI Friendly Versions. Now we can use the ${revision} placeholder to get what we want. This means we write

<?xml version="1.0" encoding="UTF-8"?>
<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>com.sergiuoltean</groupId>
  <artifactId>maven-parent</artifactId>
  <version>${revision}</version>
  <packaging>pom</packaging>

  <properties>
    <revision>1.0.0</revision>
  </properties>

  <modules>
    <module>presentation</module>
    <module>services</module>
    <module>data-access</module>
  </modules>


</project>

and the child module will change to

<?xml version="1.0" encoding="UTF-8"?>
<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>

  <parent>
    <groupId>com.sergiuoltean</groupId>
    <artifactId>maven-parent</artifactId>
    <version>${revision}</version>
  </parent>

  <artifactId>presentation</artifactId>

</project>

We can now control the version in a single place. But we are not done yet. When we deploy or install the modules we see that the placeholder is still there making the modules unusable. We also need the flatten-maven plugin to fix this.

 <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>flatten-maven-plugin</artifactId>
        <version>${flatten.version}</version>
        <configuration>
          <updatePomFile>true</updatePomFile>
          <flattenMode>resolveCiFriendliesOnly</flattenMode>
        </configuration>
        <executions>
          <execution>
            <id>flatten</id>
            <phase>process-resources</phase>
            <goals>
              <goal>flatten</goal>
            </goals>
          </execution>
          <execution>
            <id>flatten.clean</id>
            <phase>clean</phase>
            <goals>
              <goal>clean</goal>
            </goals>
          </execution>
        </executions>
  </plugin>

When we check the m2 repo we see

<?xml version="1.0" encoding="UTF-8"?>
<project
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
  xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.sergiuoltean</groupId>
    <artifactId>maven-parent</artifactId>
    <version>1.0.0</version>
  </parent>
  <groupId>com.sergiuoltean</groupId>
  <artifactId>presentation</artifactId>
  <version>1.0.0</version>
</project>

Much easier now to control the version.

SOURCE CODE

2 thoughts on “Maven parent version”

  1. Thank you for the article. it is very helpful. I got the version settings of my multi module mvn project work the 1st time. just 1 last question. the definition of revision variable in my parent pom is a variable, and my child 1 module depends on my child 2 module. When building from parent dir, it works all fine if i give a real value to revision; if I leave the definition of revision in parent pom as an env variable, even if the variable is defined, I got complaints building child 1 module saying it cannot find child 2 module of the version ${env.my_version} 😦 Any way to fix that, if not passing additional value to mvn install?

    Like

    1. Hello,

      First of all I would not recommend to use env vars and maven. It’s always better to pass properties as arguments. Having said that I tried to put the revision property as env variable.
      ${env.MY}
      Exported the variable
      export MY=”1.2.3″
      then run mvn clean install with no issues.

      Hope this helps

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.