How to put maven zip dependency on classpath for J

2019-06-20 21:21发布

问题:

I have a Java project entirely consisting of junit/integration tests which is managed by maven. One of the dependencies is a zip archive, the contents of which I would like to be available on the classpath when the tests are run. Since maven does not put the content of a zip dependency on the classpath I have had to come up with what I consider to be a hacky workaround. I unpack the zip archive to a temp directory then copy one of the resulting directories into the /test-classes folder. I also had to make the clean step delete the temp directory. Here are the relevant parts of the pom:

<groupId>com.my.package</groupId>
<artifactId>test-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>My Test Project</name>

<properties>
    <config.artifactId>environment-dev</config.artifactId>
    <config.version>2.0.8-SNAPSHOT</config.version>
    <tempDir>${project.basedir}/temp</tempDir>
</properties>

<build>
    <plugins>
        ...
        <!-- clean out our custom temp directory as well as the default dir during clean phase-->
        <plugin>
            <artifactId>maven-clean-plugin</artifactId>
            <version>2.3</version>
            <configuration>
                <filesets>
                    <fileset>
                        <directory>${tempDir}</directory>
                    </fileset>
                </filesets>
            </configuration>
        </plugin>
        <!-- since the config dependency is a zip it does not get added to the classpath.  So we extract
        it to a temp dir, then copy the content we need into a directory on the classpath -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>2.8</version>
            <executions>
                <execution>
                    <id>unpack-config</id>
                    <phase>compile</phase>
                    <goals><goal>unpack-dependencies</goal></goals>
                    <configuration>
                        <includeGroupIds>com.my.package.config</includeGroupIds>
                        <includeArtifactIds>${config.artifactId}</includeArtifactIds>
                        <includeClassifiers>config</includeClassifiers>
                        <outputDirectory>${tempDir}</outputDirectory>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <!-- copy the content of the zip file that we extracted into a directory on the classpath -->
        <plugin>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.6</version>
            <executions>
                <execution>
                    <phase>compile</phase>
                    <goals><goal>copy-resources</goal></goals>
                    <configuration>
                        <outputDirectory>${project.build.directory}/test-classes/TargetDir</outputDirectory>
                        <resources>
                            <resource>
                                <directory>${tempDir}/${config.artifactId}-${config.version}/TargetDir</directory>
                                <filtering>true</filtering>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
<dependencies>
    ...
    <dependency>
        <groupId>com.my.package.config</groupId>
        <artifactId>${config.artifactId}</artifactId>
        <version>${config.version}</version>
        <classifier>config</classifier>
        <type>zip</type>
    </dependency>
</dependencies>

There must be a better way of doing this.

Can I force maven to treat the zip file as if it were a jar? The link I provided has a tantalising hint that this might once have been possible, but I can't find anything relevant in the documentation. This seems like such a simple thing to be able to do, I really hope I've just missed a config parameter somewhere. Can anyone suggest a better way of getting the content of a zip dependency onto the classpath?

回答1:

I would unzip the dependency into a subdirectory of the target directory and add that directory to the additionalClasspathElements configuration of the surefire plugin.

<properties>
    <config.artifactId>environment-dev</config.artifactId>
    <config.version>2.0.8-SNAPSHOT</config.version>
    <unzipDir>${project.build.directory}/addTestClasspath</unzipDir>
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>2.8</version>
            <executions>
                <execution>
                    <id>unpack-config</id>
                    <phase>compile</phase>
                    <goals><goal>unpack-dependencies</goal></goals>
                    <configuration>
                        <includeGroupIds>com.my.package.config</includeGroupIds>
                        <includeArtifactIds>${config.artifactId}</includeArtifactIds>
                        <includeClassifiers>config</includeClassifiers>
                        <outputDirectory>${unzipDir}</outputDirectory>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.17</version>
            <configuration>
                <additionalClasspathElements>
                    <additionalClasspathElement>${unzipDir}</additionalClasspathElement>
                </additionalClasspathElements>
            </configuration>
        </plugin>
    </plugins>
</build>

In this case you can omit the clean plugin config because everything is under the target folder which will be deleted by the clean plugin by default.

Sadly this configuration does only work on the command line and not within eclipse, because the m2e plugin does not honor the additionalClasspathElement. See the jira issue MNGECLIPSE-1213