How to put maven zip dependency on classpath for Java tests - java

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?

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

Related

Using Maven resource plugin on dependecy jar file

Maven has resource plugin that can delimiter a character that can tell it in pom file , for example in the blow config define it that replace "#" character.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>target/filtered-resources/scripts</outputDirectory>
<resources>
<resource>
<directory>src/assemble/resources/scripts</directory>
<filtering>true</filtering>
</resource>
</resources>
<useDefaultDelimiters>false</useDefaultDelimiters>
<delimiters>
<delimiter>#</delimiter>
</delimiters>
</configuration>
</execution>
</executions>
</plugin>
but it work on files that directly exists in my project , i want to do the same job in a jar file , i have a jar file that exists some java script plugins and i want add it to my project but i need replace somethings on it .
and the dependency is something like this :
<dependency>
<groupId>sample.javascript</groupId>
<artifactId>jsLibrary/artifactId>
<version>1.0.0</version>
</dependency>
1) you need to unpack your jar. You can use this plugin: https://maven.apache.org/plugins/maven-dependency-plugin/examples/unpacking-artifacts.html
2) change
<directory>src/assemble/resources/scripts</directory>
to the directory with unpacked jar

Exclude webapp folder from Maven Build

I was trying to achieve a custom directory structure for my war with maven build.
Below is my build command used in pom.xml.
<build>
<finalName>abc</finalName>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<configuration>
<tasks>
<mkdir dir="bin" />
</tasks>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>bin</outputDirectory>
<resources>
<resource>
<directory>src/main/webapp/</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<warSourceDirectory>bin</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
Please find below the current directory structure of war file after unzip the war. Maven is including complete webapp directory under WEB-INF/Classes , But i want only java class files(ndaws directory). I have tried a lot of excluding techniques, But nothing works.
Got the solution, My changes in pom is not reflecting, war is being created from build folder under target.
Thanks
remove resource directory from maven-resources-plugin
and add warSourceDirectory to maven-war-plugin
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<warSourceDirectory>src/main/webapp</warSourceDirectory>
</configuration>
</plugin>
or if using intelij and webapp folder marked 'resoures', select the folder.
open context menu.
Mark Directory as > Unmark as Resources Root
I tryed alot of solutions. In the end I found one that solve my problem... It's a similiar case, but I need to exclude a folder inside the webapp.
I opened my war file using 7zip... The folder that I want to exclude were in the main page.
I used this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
<configuration>
<packagingExcludes>myfolder/**</packagingExcludes>
</configuration>
</plugin>
Just change "myfolder" with the folder that you want to exclude.
If that is more than one folder, multiply this line.

Maven - addjars-maven-plugin to add jars to classpath for an java project build

I am using addjars-maven-plugin to add all the jars present in web-inf/lib to my classpath and i am able to build my web-application and package it as war.
Is there any similar way to add all the jars present in some folder to classpath, while building java classes and package it as jar?
I tried the same plugin as below. But, when i try to build my project, the jars are downloaded to my local repository. But still i get class not found exception.
Kindly help. Thanks in advance!
<build>
<plugins>
<plugin>
<groupId>com.googlecode.addjars-maven-plugin</groupId>
<artifactId>addjars-maven-plugin</artifactId>
<version>1.0.2</version>
<executions>
<execution>
<goals>
<goal>add-jars</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>${project.basedir}/src/main/extlib</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Full pom.xml content:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.xyz</groupId>
<artifactId>testlogger</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
<build>
<plugins>
<plugin>
<groupId>com.googlecode.addjars-maven-plugin</groupId>
<artifactId>addjars-maven-plugin</artifactId>
<version>1.0.2</version>
<executions>
<execution>
<goals>
<goal>add-jars</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>${project.basedir}/src/main/extlib</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
I could achieve adding the jars present in any folder by using addjars-maven-plugin as above but, the only change i had to make is change the version of the plugin from 1.0.2 to 1.0.5. Thanks all for the support!!
I had the same challenge with addjars-maven-plugin. Calling mvn clean install it builds successfully but under eclipse (RAD 9.5) my source files could not be compiled because of missing jars. Now add the maven-compiler-plugin:
<build>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<includes>
<include>${some.dir}/libs/*.jar</include>
</includes>
</configuration>
</plugin>
Nevertheless those jars are not added under Maven Dependencies in the project structure.

maven - how to compile code to jar file and not .class

I am trying to build a groovy project using maven. My packaging type is war file. Maven is building the project and putting all dependent libraries in WEB-INF/lib folder but it is compiling all code into class files and putting it into WEB-INF/classes folder. Is there a way I can tell maven to build jar file for my project also and put it into WEB-INF/lib folder.
My pom.xml looks like this :
<groupId>com.myproject</groupId>
<artifactId>ExampleProject</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>My Example Project</name>
<url>http://maven.apache.org</url>
<dependencies>
...
...
...
</dependencies>
<build>
<resources>
<resource>
<directory>${basedir}/src/main/groovy</directory>
<excludes>
<exclude>**/*.groovy</exclude>
</excludes>
</resource>
<resource>
<directory>${basedir}/src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/groovy</source>
<source>src/main/resources</source>
</sources>
</configuration>
</execution>
<execution>
<id>add-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/test/groovy</source>
<source>src/test/resources</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<finalName>master</finalName>
</build>
In these scenarios the usual approach is to you separate your library code in a different module that will be a dependency from your war module. For this suggestion you can see also how to generate jar and war both in project .
However if you still prefer to go with the solution you mention, you can do it with the following configuration in your pom
<configuration>
..
<attachClasses>true</attachClasses>
<archiveClasses>true</archiveClasses>
</configuration>
(see http://maven.apache.org/plugins/maven-war-plugin/war-mojo.html, and how to use class file from another war)

Maven add jars through systemPath/system but not added to war or anywhere else

I want to add a jar file through the systemPath from the local file-system relative to my project directory structure, not on a remote repository. I added the dependency declaration but maven doesn't do anything else with it.
In the declaration below, I want the jar file copied to my target web-inf/lib directory and also jarred as part of the war file. At present, that doesn't happen. How would I get the jar file copied to my war file?
This is the output from debug maven mode:
DEBUG] cglib:cglib-nodep:jar:2.2:test (setting scope to: compile)^M
DEBUG] Retrieving parent-POM: org.objenesis:objenesis-parent:pom:1.2 for project: null:objenesis:ja
DEBUG] org.objenesis:objenesis:jar:1.2:test (selected for test)^M
DEBUG] org.javap.web:testRunWrapper:jar:1.0.0:system (selected for system)^M
DEBUG] Plugin dependencies for:
...
<dependency>
<groupId>org.javap.web</groupId>
<artifactId>testRunWrapper</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/testRunWrapper.jar</systemPath>
</dependency>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>WebContent</directory>
</resource>
</webResources>
</configuration>
</plugin>
OK, I did this: Note the directory structure at the bottom.
With the approach below, the jar file from the relative project path is treated as a first class citizen like the other jars. The listing below corrects my original problem. With the pom.xml listing below, the jar file is copied to my target directory.
<repositories>
<repository>
<id>JBoss</id>
<name>JBoss Repository</name>
<layout>default</layout>
<url>http://repository.jboss.org/maven2</url>
</repository>
<repository>
<id>my-local-repo</id>
<url>file://${basedir}/lib/repo</url>
</repository>
</repositories>
<dependency>
<groupId>testRunWrapper</groupId>
<artifactId>testRunWrapper</artifactId>
<version>1.0.0</version>
</dependency>
$ find repo
repo
repo/testRunWrapper
repo/testRunWrapper/testRunWrapper
repo/testRunWrapper/testRunWrapper/1.0.0
repo/testRunWrapper/testRunWrapper/1.0.0/testRunWrapper-1.0.0.jar
Using the maven dependency plugin does the job:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>compile</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/lib</outputDirectory>
<includeScope>system</includeScope>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Don't use system. To do what you want, just declare as a regular (compile) dependency and use mvn install:install-file into your local repository. Everything else will work as you want (lib will be copied, etc.) That will mean that the build will only work on your machine, however.
To properly fix this for your (internal) team, you will want to set up a repository (e.g. Artifactory, Nexus, or Archiva). This is almost a must for team use of Maven.
If this is for public (e.g. open source) use you can either mimic a repository via an http server or put up a real repository.
try something like this (using Ant plugin to manually put the jar to output directory):
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<copy file="${project.basedir}/pathToJAR.jar"
todir="${project.build.directory}/outputFileName/WEB-INF/lib"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
AFAIK, system scoped dependencies are somewhat like those with provided scope and thus are not included in the target artifact. Why don't you install the dependency into your local repository instead?
From the doc:
system
This scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository.
In case this answer didn't work for you as it didn't for me and you know that system is a bad scope, you can try this solution where you are Installing the jar by using install-plugin (scroll down a bit), which installs the JAR into your actual local Maven-repository. Basically you only need to add this plugin to your pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<groupId>myGroupId</groupId>
<artifactId>myArtifactId</artifactId>
<version>myVersion</version>
<packaging>jar</packaging>
<file>${basedir}/lib/xxx.jar</file>
</configuration>
</execution>
</executions>
</plugin>
Fill in the appropriate values for groupId, artifactId and version and put your original jar file into the <project-home>/lib-directory and fix file above. You can add more execution-sections, but then don't forget to add ids there, like:
<execution>
<id>common-lib</id>
Everybody who updates from the code-repo needs to call mvn initialize once.
And all Eclipse-enthusiasts may add this to pom.xml, too, to get rid of errors in Eclipse:
<pluginManagement>
<plugins>
<!-- This plugin's configuration is used to store Eclipse m2e settings
only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<versionRange>[2.4,)</versionRange>
<goals>
<goal>install-file</goal>
</goals>
</pluginExecutionFilter>
<action>
<execute></execute>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
The problem with using a reference to the file system is that dependent projects will not be able to globally access this jar file. i.e. the dependent project's ${basedir} is different and thus the .jar file won't be found.
Global repositories on the other hand are universally accessible.

Categories