How to embed archetype project version in Maven archetype?

I tried something rather stupid and it seems to have worked. I added the following to my META-INF/maven/archetype-metadata.xml file:

<requiredProperties>
    <requiredProperty key="archetypeVersion"> </requiredProperty>
</requiredProperties>

You would think it would know about it by default but it doesn't so this seems to remind it to use it. Perhaps it is due to a bug in maven.


I asked the above question on the Maven mailing list a few days ago and got tumbleweeds. Fortunately, I eventually figured it out on my own. Here's at least one sane way to accomplish this:

Use Maven filtering on your src/main/resources/archetype-resources/pom.xml file to substitute in the current project version when building the archetype.

Here's how that's done:

Modify your archetype/pom.xml file to enable filtering on the archetype-resources/pom.xml file and not on anything else (because your archetype files will naturally have ${variable}s all over the place and you don't want those to be substituted at build time, you want them to be substituted when the archetype is created).

<resources>
  <resource>
    <directory>src/main/resources</directory>
    <filtering>true</filtering>
    <includes>
      <include>archetype-resources/pom.xml</include>
    </includes>
  </resource>
  <resource>
    <directory>src/main/resources</directory>
    <filtering>false</filtering>
    <excludes>
      <exclude>archetype-resources/pom.xml</exclude>
    </excludes>
  </resource>
</resources>

Enable an escape character for use when filtering, so that you can escape all the variables in your archetype pom that need to remain as-is so that they can be substituted at archetype generation time:

<pluginManagement>
  <plugins>
    ...
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-resources-plugin</artifactId>
      <version>2.5</version>
      <configuration>
        <escapeString>\</escapeString>
      </configuration>
    </plugin>
  </plugins>
</pluginManagement>

(Note the <resources> and <pluginManagement> elements shown above should be placed inside the <build> element of your POM.)

Use ${project.version} in your archetype pom, where you want the version of your archetype project to be inserted, and escape all of the other variables that should remain unsubstituted until archetype generation time:

<?xml version="1.0" encoding="UTF-8"?>
<project ...>
  <modelVersion>4.0.0</modelVersion>

  <groupId>\${groupId}</groupId>
  <artifactId>\${artifactId}</artifactId>
  <version>\${version}</version>
  <packaging>jar</packaging>

  <dependencies>
    <dependency>
      <groupId>com.foo</groupId>
      <artifactId>origin-core</artifactId>
      <version>${project.version}</version>
    </dependency>
  </dependencies>

</project>

An alternative solution to the accepted answer is to filter a default property in the archetype's descriptor/metadata file

This is done like so:

The maven filtering only filters this file:

<resources>
<resource>
    <directory>src/main/resources</directory>
    <filtering>true</filtering>
    <includes>
        <include>META-INF/maven/archetype-metadata.xml</include>
    </includes>
</resource>
<resource>
    <directory>src/main/resources</directory>
    <filtering>false</filtering>
    <excludes>
        <exclude>META-INF/maven/archetype-metadata.xml</exclude>
    </excludes>
</resource>
</resources>

The archetype meta data file:

<archetype-descriptor ...>
    <requiredProperties>
        <requiredProperty key="projectVersion">
            <defaultValue>${project.version}</defaultValue>
         </requiredProperty>
    </requiredProperties>

    ...
</archetype-descriptor>

and the archetype's POM would be similar to before except that it would use the projectVersion required property value as the project version:

<?xml version="1.0" encoding="UTF-8"?>
<project ...>
  <modelVersion>4.0.0</modelVersion>

  <groupId>${groupId}</groupId>
  <artifactId>${artifactId}</artifactId>
  <version>${version}</version>
  <packaging>jar</packaging>

  <dependencies>
    <dependency>
      <groupId>com.foo</groupId>
      <artifactId>origin-core</artifactId>
      <version>${projectVersion}</version>
    </dependency>
  </dependencies>

</project>

This approach has the advantage that it avoids having to escape all the property values in the archetype's POM and the resource plugin configuration that goes with it. Personally, I find all of that quite ugly and error prone.

It does mean that the user is asked to confirm or alter the project version when generating the archetype. Depending on the scenario, I guess this could be considered a good or a bad thing.