Search code examples
javakotlinmavenjvm

Maven + Kotlin/Java - programmatically get jar file from local maven repo


I want to read any jar file located in the maven local repo during the tests runtime. For example, the following code will work and will read jar file:

File("/Users/myusername/.m2/repository/log4j/log4j/1.2.17/log4j-1.2.17.jar")

When I get value from "java.class.path" property, I can see that path to jar file is in the list of classpath:

System.getProperty("java.class.path")

Output:

...:/Users/myusername/.m2/repository/io/netty/netty-transport-classes-epoll/4.1.87.Final/netty-transport-classes-epoll-4.1.87.Final.jar:/Users/myusername/.m2/repository/log4j/log4j/1.2.17/log4j-1.2.17.jar

But I cannot understand how to get the same file without specifying full path to the jar file. My goal is to write code that will run on any machine with maven.

I tried to use just filename:

File("log4j-1.2.17.jar")

But it gets nothing, because by default it looks into application classpath directory.

Additional context

I use TestContainers to build and run containers for integration tests. I want to build and run GenericContainer using basic image with Java and executable jar from our company private repository. I have this jar in my pom.xml:

    <dependency>
        <groupId>private.group.id</groupId>
        <artifactId>private.artifact.id</artifactId>
        <scope>test</scope>
        <classifier>exec</classifier>
        <version>${jar.version}</version>
    </dependency>

Here is a code sample to build and run Container:

GenericContainer<Nothing>(
ImageFromDockerfile()
    .withFileFromFile(jarName, File("/Users/username/.m2/repository/groupId/artifactId/version/$jarName"))
    .withDockerfileFromBuilder { builder: DockerfileBuilder ->
        builder
            .from("urlToBaseImageWithJava")
            .copy(jarName,"/app/$jarName")
            .entryPoint("java", "-jar", "/app/$jarName")
            .build()
    }

).apply { withNetwork(myNetwork) start() }


Solution

  • If under "run containers for integration tests" you actually mean running mvn verify, then maven way is to copy required dependencies to known location using maven-dependency-plugin and pass the location(s) to maven-failsafe-plugin via systemProperties, for example:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
            <execution>
                <id>copy-dependencies</id>
                <!-- 
                    should be pre-integration-test, actually, however
                    in that case we will depend on plugin execution order
                -->
                <phase>process-test-classes</phase>
                <goals>
                    <goal>copy</goal>
                </goals>
                <configuration>
                    <artifactItems>
                        <artifactItem>
                            <groupId>private.group.id</groupId>
                            <artifactId>private.artifact.id</artifactId>
                            <scope>test</scope>
                            <classifier>exec</classifier>
                            <version>${jar.version}</version>
                            <outputDirectory>${project.build.directory}</outputDirectory>
                            <destFileName>my-cool-jar.jar</destFileName>
                        </artifactItem>
                    </artifactItems>
                </configuration>
            </execution>
        </executions>
    </plugin>
    
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <configuration>
            <systemProperties>
                <myCoolJarLocation>${project.build.directory}/my-cool-jar.jar</myCoolJarLocation>
            </systemProperties>
        </configuration>
    </plugin>
    

    After that you may discover location of your jar using myCoolJarLocation system property.