Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven: resolve version range to into property

Tags:

maven

I have a Java project that packages some resource files into the artifact jar. The files come from a zip that is versioned and stored in the same artifactory as the project's artifact. The zip is referenced as a dependency with a version-range.

The zip is listed as a dependency:

<dependency>
    <groupId>com.example</groupId>
    <artifactId>resource-files</artifactId>
    <version>[1.68.0,1.68.1)</version>
    <type>zip</type>
    <scope>provided</scope>
</dependency>

Then unpacked with dependency plugin:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.10</version>
    <executions>
        <execution>
            <id>unpack-dependencies</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>unpack-dependencies</goal>
            </goals>
            <configuration>
                <includes>**/*.bin</includes>
                <outputDirectory>${basedir}/import</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

Then added as a resource to the jar:

<resource>
    <directory>${project.basedir}/import/resource-files-${version????}</directory>
    <includes>
        <include>*</include>
    </includes>
    <targetPath>bins</targetPath>
</resource>

How can I determine the exact version of the artifact zip? I would like to skip modifying the pom (like versions:resolve-ranges does), if possible.

like image 249
Gyorgy Szekely Avatar asked Sep 19 '25 11:09

Gyorgy Szekely


1 Answers

Well this was fun...

I found 2 ways to get resolved versions: use a specific plugin, or use a small groovy script to query it from maven.

Plugin

There's a dependencyversion-maven-plugin:

<plugin>
    <groupId>io.reformanda.semper</groupId>
    <artifactId>dependencyversion-maven-plugin</artifactId>
    <version>1.0.1</version>
    <executions>
        <execution>
            <id>set-all</id>
            <goals>
                <goal>set-version</goal>
            </goals>
        </execution>
    </executions>
</plugin>

It creates new properties for each dependency in the format groupId:artifactId:type[:classifier].version with the resolved version value. More details here.

Groovy

The same result can be achieved with a small groovy script:

<plugin>
    <groupId>org.codehaus.gmaven</groupId>
    <artifactId>groovy-maven-plugin</artifactId>
    <executions>
        <execution>
            <phase>initialize</phase>
            <goals>
                <goal>execute</goal>
            </goals>
            <configuration>
                <source>
                    for (art in project.getArtifacts())
                        project.properties['resolvedVersion.' + art.getArtifactId()] = art.getVersion()
                </source>
            </configuration>
        </execution>
    </executions>
</plugin>

Since the groovy-maven-plugin nicely exposes maven internals, all kinds of tricks can be implemented.

Almost there...

Both above solutions define a new set of properties with the resolved version, but unfortunately they are not usable in the <build><resources> block. I haven't found documentation on this, but it seem properties in this block are substituted before the lifecycle starts and the newly defined properties simply not exist yet at that point.

The only workaround I found is to explicitly invoke the copy-resources goal on the resources plugin:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>3.1.0</version>
    <executions>
        <execution>
            <id>copy-resources</id>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <phase>process-resources</phase>
            <configuration>
                <outputDirectory>${project.build.outputDirectory}</outputDirectory>
                <resources>
                    <resource>
                        <filtering>false</filtering>
                        <directory>${basedir}/import/resource-files-${resolvedVersion.resource-files}/lib</directory>
                        <includes>
                            <include>*</include>
                        </includes>
                        <targetPath>bins</targetPath>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>

With this block in place (and replacing <build><resources>), all resources correctly copied, and there's no need to hardcode anything.

Though it might not be the most elegant way...

like image 88
Gyorgy Szekely Avatar answered Sep 22 '25 05:09

Gyorgy Szekely