43

I have a maven dependency in my pom.xml as such:

<dependency>
    <groupId>com.foo</groupId>
    <artifactId>Bar</artifactId>
    <version>1.2.3</version>
</dependency>

And I would like to use the system path to the binary as a property (so I can pass it to an external process that is kicked off by maven). I can do this in an awkward way:

<properties>
    <my.lib>${settings.localRepository}/com/foo/Bar/1.2.3/Bar.jar</my.lib>
</properties>

But I would really like to use a more standard mechanism, such as:

<properties>
    <my.lib>${com.foo:Bar:1.2.3}</my.lib>
</properties>

I something like that possible?

codefinger
  • 10,088
  • 7
  • 39
  • 51
  • I am a bit confused: if you want to refer `Bar.jar` as a system library, you need to specify `system${my.lib}` but it seems you want to use `${my.lib}` somewhere else. Show the complete example of how you want to use `${my.lib}`... – dma_k Mar 01 '10 at 23:40
  • 1
    @dma_k The OP wants to pass the physical path to a dependency to an external process triggered by maven. – Pascal Thivent Mar 01 '10 at 23:44

5 Answers5

63

Here is a correct implementation, using the maven-dependency-plugin properties goal, which can be used anywhere in a pom:

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.stackoverflow</groupId>
    <artifactId>q2359872</artifactId>
    <version>2.0-SNAPSHOT</version>
    <name>q2359872</name>

    <properties>
        <!-- Must be listed in the dependencies section otherwise it will be null. -->
        <my.lib>${org.jmockit:jmockit:jar}</my.lib>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.jmockit</groupId>
            <artifactId>jmockit</artifactId>
            <version>1.11</version>
        </dependency>
    </dependencies>
    <build>
        <defaultGoal>generate-sources</defaultGoal>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.3</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>properties</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <!-- Example usage: -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                        <phase>generate-sources</phase>
                    </execution>
                </executions>
                <configuration>
                    <executable>echo</executable>
                    <arguments>
                        <argument>path to jar=</argument>
                        <argument>${org.jmockit:jmockit:jar}</argument>
                        <argument>my.lib=</argument>
                        <argument>${my.lib}</argument>
                    </arguments>
                </configuration>
            </plugin>
            <!-- end of Example usage -->
        </plugins>
    </build>
</project>

And the output is...

jpyeron@black /projects/wkspc/tmp/foo
$ /cygdrive/c/programs.x86_64/apache-software-foundation/apache-maven-3.1.1/bin/mvn
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building q2359872 2.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.3:properties (default) @ q2359872 ---
[INFO]
[INFO] --- exec-maven-plugin:1.2:exec (default) @ q2359872 ---
path to jar= C:\Documents and Settings\jpyeron\.m2\repository\org\jmockit\jmockit\1.11\jmockit-1.11.jar my.lib= C:\Documents and Settings\jpyeron\.m2\repository\org\jmockit\jmockit\1.11\jmockit-1.11.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.032s
[INFO] Finished at: Wed Sep 17 12:07:18 EDT 2014
[INFO] Final Memory: 10M/153M
[INFO] ------------------------------------------------------------------------
jordanpg
  • 6,386
  • 4
  • 46
  • 70
Jason Pyeron
  • 2,388
  • 1
  • 22
  • 31
  • It might be less confusing if your example used a different dependency. For those interested, if you needed the jar for JMockit, your property would be like this: ${org.jmockit:jmockit:jar} That is to say: ${groupId:artifactId:jar} – GreenSaguaro Sep 15 '14 at 06:56
  • 5
    This should be the accepted answer. The other one is specific to the ant plugin. – Bogdan Calmac Nov 21 '15 at 03:22
  • 7
    Jason, please mention that the key here is to use the maven-dependency-plugin. Initially I just used the ${org.jmockit:jmockit:jar} syntax and it took a long time to realize what the problem was. – Bogdan Calmac Nov 21 '15 at 03:25
  • This worked very nicely for my case where I needed to resolve a dependency path in a superpom to the latest version, allowing Maven's versioning logic to choose the best version for me (no guesswork on where the file ended up). – Benjamin Damm May 24 '16 at 19:42
  • The example you provided works fine. I've added an exe file to a corporate repo and put that in the pom. I also have classifier and type tags. ie_64 exe And I receive an error when trying to run. Invalid file. Somehow, ${groupId:artifactId:exe} is not enough to create the file path. – Gabriel Porumb Apr 06 '17 at 08:55
39

Assuming that the com.foo:Bar:jar:1.2.3 artifact is declared as dependency in your POM, the following property returns the path to the jar in the local repository:

${maven.dependency.com.foo.Bar.jar.path}

Update: Here is a simple POM demonstrating this:

<?xml version="1.0" encoding="UTF-8"?>
<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.stackoverflow</groupId>
  <artifactId>q2359872</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>q2359872</name>
  <properties>
    <my.lib>${maven.dependency.junit.junit.jar.path}</my.lib>
  </properties>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-antrun-plugin</artifactId>
        <executions>
          <execution>
            <phase>process-resources</phase>
            <configuration>
              <tasks>
                <echo>${my.lib}</echo>
              </tasks>
            </configuration>
            <goals>
              <goal>run</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Running mvn process-resources produces the following output:

$ mvn process-resources
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building q2359872
[INFO]    task-segment: [process-resources]
[INFO] ------------------------------------------------------------------------
[INFO] [resources:resources {execution: default-resources}]
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /home/pascal/Projects/stackoverflow/q2359872/src/main/resources
[INFO] [antrun:run {execution: default}]
[INFO] Executing tasks
     [echo] /home/pascal/.m2/repository/junit/junit/3.8.1/junit-3.8.1.jar
[INFO] Executed tasks
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7 seconds
[INFO] Finished at: Tue Mar 02 14:41:32 CET 2010
[INFO] Final Memory: 7M/68M
[INFO] ------------------------------------------------------------------------
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • 1
    I cannot prove this feature works in Maven. That only works for `maven-antrun-plugin` (see http://jira.codehaus.org/browse/MANTRUN-110). Please, provide a complete pom example, as I suppose, you refer not `` but some other properties. – dma_k Mar 02 '10 at 13:18
  • @dma_k The Jira issue you are mentioning doesn't show anything except that there was a bug in the antrun documentation. Now, feel free to test this solution yourself. And BTW, I always test my answers :) – Pascal Thivent Mar 02 '10 at 13:53
  • @Pascal Thanks for the update! I fully trust you, that it works at your site :) My question was: is it supposed to work in combination with `maven-antrun-plugin`. And you show this in your example, great! And from example I see that this is `maven-antrun-plugin`-specific feature, i.e. if I want to substitute `${my.lib}` variable for resources (without using any additional pugin) - I cannot do it, right? – dma_k Mar 02 '10 at 16:05
  • @dma_k Not sure it wouldn't work outside antrun (I'm just echoing ${my.lib} after all) but I would have to test resources filtering (sometimes, the way property resolution works is a bit obscure for me). – Pascal Thivent Mar 02 '10 at 16:32
  • 4
    @dma_k I did a test and the property is not available during filtering. I don't know if it's the same situation as in http://stackoverflow.com/questions/2246524/how-to-filter-resource-in-maven-replacing-with-a-dependencies-artifactid/2247645#2247645 i.e. if the expression is not available during filtering because filtering and interpolation don't share the same algorithm or if it's an antrun property. – Pascal Thivent Mar 02 '10 at 22:54
  • @Pascal Exactly, that what I meant. The link I've posted at my fisst comment also contains a link to `maven-antrun-plugin` sources, that do that trick. So it is antrun-specific feature, and bmargulies is also right, saying you can do the same in your custom plugin. – dma_k Mar 03 '10 at 08:32
  • Also found out, this works with `maven-antrun-plugin v1.3` and not with `maven-antrun-plugin v1.1`, so also checkout the latest version for this feature to work. – dma_k Mar 08 '10 at 12:45
  • 2
    This is documented here: http://maven.apache.org/plugins/maven-antrun-plugin/examples/classpaths.html – Jon Freedman Jun 25 '12 at 08:38
  • The old format `maven.dependency.groupId.artifactId[.classifier].type.path` is not supported as of version 3.0.0 of maven-antrun-plugin (see https://maven.apache.org/plugins/maven-antrun-plugin/examples/classpaths.html). – Stephan Jun 15 '22 at 09:31
9

There is a plugin which might be what you are looking for... bitstrings.org (home).

gqman69
  • 91
  • 1
  • 1
2

If none of the upper work, you can always use gmaven to agressively dive into MavenProject object and get your artifact infos. In my case, I had the following artifact declared in a profile :

            <!-- Neo4J connector. This dependency is scoped to be usable by maven-exec-plugin 
                which installs it in Glassfish -->
            <dependency>
                <groupId>com.netoprise</groupId>
                <artifactId>neo4j-connector</artifactId>
                <version>${neo4j.connector.version}</version>
                <type>rar</type>
                <!-- Set in test scope to avoid release issues -->
                <scope>test</scope>
            </dependency>

To get its path and put it in a maven property, I wrote the following gmaven script :

                <!-- Small script used to build maven property for neo4j-connector path -->
                <plugin>
                    <groupId>org.codehaus.gmaven</groupId>
                    <artifactId>gmaven-plugin</artifactId>
                    <version>1.3</version>
                    <executions>
                        <execution>
                            <id>get-neo4j-connector-rar-path</id>
                            <phase>validate</phase>
                            <goals>
                                <goal>execute</goal>
                            </goals>
                            <configuration>
                                <source>
                                    <![CDATA[
println "initial value of neo4j.connector.rarPath is \""+project.properties['neo4j.connector.rarPath']+"\""                             

// Duplicate model in a Mavenproject, allowing me to get associated artifact
// So sad I can't get the embdder object

// More info here : http://maven.apache.org/ref/3.0.3/maven-core/apidocs/org/apache/maven/project/MavenProject.html
def mavenProject = new org.apache.maven.project.MavenProject(project)

// More infos on Artifact there : http://maven.apache.org/ref/3.0.3/maven-artifact/apidocs/org/apache/maven/artifact/Artifact.html
def neo4jConnector = mavenProject.getArtifacts().find { artifact -> artifact.getArtifactId()=='neo4j-connector' }
// Now resolve dependency to produce an artifact
// notice maven property interpolation doesn't do toString, so we have to do it ourselves
project.properties['neo4j.connector.rarPath'] = neo4jConnector.getFile().getAbsolutePath()

println "usable neoj4Connector can be found at "+project.properties['neo4j.connector.rarPath']

                                    ]]>
                                </source>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>

It's some kind of brute-force method, but it DO work far better than the previous solutions I've seen there.

Riduidel
  • 22,052
  • 14
  • 85
  • 185
0

You need to write a new maven plugin that sets a property value to the fully-resolved pathname of a dependency. The maven-dependency-plugin won't do that for you.

It will copy your dependency somewhere and then you can refer to it by that pathname.

bmargulies
  • 97,814
  • 39
  • 186
  • 310