Maven: add a folder or jar file into current classpath - maven-2

I am using maven-compile plugin to compile classes. Now I would like to add one jar file into the current classpath. That file stays in another location (let's say c:/jars/abc.jar . I prefer to leave this file here). How can I do that?
If I use classpath in the argument:
<configuration>
<compilerArguments>
<classpath>c:/jars/abc.jar</classpath>
</compilerArguments>
</configuration>
it will not work because it will override the current classpath (that includes all the dependencies)

This might have been asked before. See Can I add jars to maven 2 build classpath without installing them?
In a nutshell: include your jar as dependency with system scope. This requires specifying the absolute path to the jar.
See also http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

The classpath setting of the compiler plugin are two args. Changed it like this and it worked for me:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<compilerArgs>
<arg>-cp</arg>
<arg>${cp}:${basedir}/lib/bad.jar</arg>
</compilerArgs>
</configuration>
</plugin>
I used the gmavenplus-plugin to read the path and create the property 'cp':
<plugin>
<!--
Use Groovy to read classpath and store into
file named value of property <cpfile>
In second step use Groovy to read the contents of
the file into a new property named <cp>
In the compiler plugin this is used to create a
valid classpath
-->
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>1.12.0</version>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<!-- any version of Groovy \>= 1.5.0 should work here -->
<version>3.0.6</version>
<type>pom</type>
<scope>runtime</scope>
</dependency>
</dependencies>
<executions>
<execution>
<id>read-classpath</id>
<phase>validate</phase>
<goals>
<goal>execute</goal>
</goals>
</execution>
</executions>
<configuration>
<scripts>
<script><![CDATA[
def file = new File(project.properties.cpfile)
/* create a new property named 'cp'*/
project.properties.cp = file.getText()
println '<<< Retrieving classpath into new property named <cp> >>>'
println 'cp = ' + project.properties.cp
]]></script>
</scripts>
</configuration>
</plugin>

From docs and example it is not clear that classpath manipulation is not allowed.
<configuration>
<compilerArgs>
<arg>classpath=${basedir}/lib/bad.jar</arg>
</compilerArgs>
</configuration>
But see Java docs (also https://www.cis.upenn.edu/~bcpierce/courses/629/jdkdocs/tooldocs/solaris/javac.html)
-classpath path Specifies the path javac uses to look up classes needed to run javac or being referenced by other classes you are
compiling. Overrides the default or the CLASSPATH environment variable
if it is set.
Maybe it is possible to get current classpath and extend it,
see in maven, how output the classpath being used?
<properties>
<cpfile>cp.txt</cpfile>
</properties>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.9</version>
<executions>
<execution>
<id>build-classpath</id>
<phase>generate-sources</phase>
<goals>
<goal>build-classpath</goal>
</goals>
<configuration>
<outputFile>${cpfile}</outputFile>
</configuration>
</execution>
</executions>
</plugin>
Read file (Read a file into a Maven property)
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
def file = new File(project.properties.cpfile)
project.properties.cp = file.getText()
</source>
</configuration>
</execution>
</executions>
</plugin>
and finally
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<compilerArgs>
<arg>classpath=${cp}:${basedir}/lib/bad.jar</arg>
</compilerArgs>
</configuration>
</plugin>

We mixed two of the answers found here to solve a similar problem. Our project needs a JAR only in compile stage, but add a local dependency, using system scope, it is unuseful because Maven refuse the artifact publication with an error related to a missing dependency.
The snippets used are the following:
<properties>
<classpathfile>${basedir}/classpathfile.classpath</classpathfile>
</properties>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.9</version>
<executions>
<execution>
<id>build-classpath</id>
<phase>generate-sources</phase>
<goals>
<goal>build-classpath</goal>
</goals>
<configuration>
<outputFile>${classpathfile}</outputFile>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
def file = new File(project.properties.classpathfile)
project.properties.originalClassPath = file.getText()
</source>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<compilerArgs>
<arg>-cp</arg>
<arg>${originalClassPath}${path.separator}${basedir}/../../../bin/POM_RUNTIME_PLACEHOLDER/ExtraJar.jar</arg>
</compilerArgs>
</configuration>
</plugin>
Maven is able to compile and successfully deploy the artifacts.
If anyone is interested the full POM is available in GitHub under project NuReflector, defaultPOM.template under src/NuReflector.

Related

Filter maven resources with filter-file from external dependency

Given a property file in maven project A
I want to use them in project B for resource filtering.
So in Project B I use
<build>
<filters>
<filter>${project.build.directory}/myFile.properties</filter>
</filters>
</build>
To filter my resources based on values in myFile.properties This file is stored in project A. So I include it with
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>process-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>groupa</groupId>
<artifactId>a</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<outputDirectory>${project.build.directory}</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Problem is that the resource filtering happens before the dependency is copied. So filtering does work when copying myFile.properties manually to ${project.build.directory} but it does not work with a mvn clean ...
How can I copy the filterFile before the actual filtering happens?
Maven plugins are executed in the order they appear in the pom. AFAIK the plugins configured in the parent (and the super pom) are executed before the plugins of the pom.
My suggestion is declaring the resources plugin explicitely after the dependency plugin:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<!-- ... -->
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<!-- ... -->
</plugin>
</plugins>
</build>

Not able to generate client code with wsdl2java and maven using CXF

I'm using maven cxf-codegen-plugin to generate client files from wsdl but not able to do so.
I want that all the wsdl files in the folder src/main/wsdl should be scanned and corresponding clients should be generated in separate folders. Please help.
My pom.xml is :
<build>
<finalName>someFileName</finalName>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>2.2.3</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>process-resources</phase>
<configuration>
<sourceRoot>src/main/java</sourceRoot>
<wsdlRoot>${basedir}/src/main/wsdl</wsdlRoot>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
here's how I'm doing it with version 2.7.4, and having the generated code created in different packages :
<build>
<plugins>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${project.build.directory}/generated/src/main/java</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>${basedir}/src/main/wsdl/MyWsdl1.wsdl</wsdl>
<extraargs>
<extraarg>-client</extraarg>
<extraarg>-verbose</extraarg>
<extraarg>-p</extraarg>
<extraarg>urn:mycompany:myproduct1:v1_0=com.my.project.product1</extraarg>
<extraarg>-p</extraarg>
<extraarg>http://www.w3.org/2001/XMLSchema=com.my.project.common</extraarg>
</extraargs>
</wsdlOption>
<wsdlOption>
<wsdl>${basedir}/src/main/wsdl/MyWsdl2.wsdl</wsdl>
<extraargs>
<extraarg>-client</extraarg>
<extraarg>-verbose</extraarg>
<extraarg>-p</extraarg>
<extraarg>urn:mycompany:myproduct2:v1_0=com.my.project.product2</extraarg>
<extraarg>-p</extraarg>
<extraarg>http://www.w3.org/2001/XMLSchema=com.my.project.common</extraarg>
</extraargs>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Here's where you can find out more about the extra-args :
http://cxf.apache.org/docs/wsdl-to-java.html
For an automatic scan of the wsdl folder, this works good too :
<configuration>
<sourceRoot>${project.build.directory}/generated/src/main/java</sourceRoot>
<wsdlRoot>${basedir}/src/main/wsdl</wsdlRoot>
<includes>
<include>**/*.wsdl</include>
</includes>
</configuration>
Hope it helps!
I realize this is an old question, but I just ran into this, so I wanted to reply for the benefit of others. You are right on commenting out the <pluginManagement> tag see here. However for the error in Eclipse that says:
Plugin execution not covered by lifecycle configuration
You will need to install the m2e connector for build-helper-maven-plugin (click on the error, and Eclipse should guide you to install it)
I put plugins tag inside pluginManagement tag and error disappeared:
<pluginManagement>
<plugins>
<plugin>
..........................
</plugin>
</plugins>
</pluginManagement>

How to specify the JAXB version in maven-jaxb2-plugin?

I need to use the latest version jaxb: 2.2.4-1, but maven or maven-jaxb2-plugin seems to pick up the one from the JDK.
I tried specifying the version like this:
<configuration>
<specVersion>2.2</specVersion>
...
</configuration>
but the logs read:
[INFO] [jaxb2:generate {execution: common}]
[INFO] Started execution.
[INFO] JAXB API is loaded from the [jar:file:/opt/jdk1.6.0_24/jre/lib/rt.jar!].
[INFO] Detected JAXB API version [2.1].
I tried to add dependencies to the correct versions of javax.xml.bind:jaxb-api and com.sun.xml.bind:jaxb-impl, but that didn't help.
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.8.0</version>
<dependencies>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.4-1</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>common</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<specVersion>2.2</specVersion>
...
</configuration>
</execution>
</executions>
</plugin>
</plugins>
I also tried using maven-jaxb22-plugin but it also didn't work.
The following code is adapted from the default webapp that netbeans generates. It uses the dependency plugin to copy the jars to a temporary folder and specifies this folder as the endorsed directory to the compiler so it overrides the implementation in the jdk.
<properties>
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
</properties>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<compilerArguments>
<endorseddirs>${endorsed.dir}</endorseddirs>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<outputDirectory>${endorsed.dir}</outputDirectory>
<silent>true</silent>
<artifactItems>
<artifactItem>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.4</version>
<type>jar</type>
</artifactItem>
<artifactItem>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.4-1</version>
<type>jar</type>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
I attempted to use Jörn's solution, but it looks like maven-jaxb2-plugin went ahead and used the rt.jar version anyway, as I got the telling message from the plugin: [INFO] JAXB API is loaded from the [jar:file:/C:/jdk1.6.0_25/jre/lib/rt.jar!].
My unsuccessful version of the solution is slightly different in how it uses the dependency plugin, but that's the one part of the build that succeeds...
<properties>
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
<v.jaxb2-api>2.2.4</v.jaxb2-api>
<v.jaxb2-impl>2.2.4-1</v.jaxb2-impl>
<v.jaxb2-xjc>2.2.4-1</v.jaxb2-xjc>
<v.jaxb2-basics-jaxb>2.1.13.MR2</v.jaxb2-basics-jaxb>
</properties>
...
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>validate</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${endorsed.dir}</outputDirectory>
<excludeTransitive>true</excludeTransitive>
<includeArtifactIds>jaxb-api,jaxb-impl</includeArtifactIds>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<fork>true</fork>
<meminitial>256m</meminitial>
<maxmem>768m</maxmem>
<compilerArguments>
<endorseddirs>${endorsed.dir}</endorseddirs>
</compilerArguments>
</configuration>
</plugin>
</plugins>
</build>
hey just I want to save time of the people.
for the people who work on jaxb-impl, the version jaxb-impl 2.2.4-1 that meant to fix a bug of the version 2.2.4, the pom of istack-commons-runtime under the META-INF Folder contain a reference to its parent pom 2.4-SNAPSHOT when it should be jsut 2.4, due this version isn't a snapshot.
<parent>
<groupId>com.sun.istack</groupId>
<artifactId>istack-commons</artifactId>
<version>2.4-SNAPSHOT</version>
</parent>
so if you don't want to work with snapshot you will smash with this error, unless you want to add everything on your local repository you may have to update manually this version into the pom on the jar.
cheers,
Manuel.

Share test resources between maven projects

There is a clear solution for sharing the common test code between maven projects using test-jar goal of maven-jar-plugin plugin (see here).
I need to do the similar thing with test resources, in particular, I want test resources of project A be available in the classpath of project B during testing.
For project A one need to declare:
<!-- Package and attach test resources to the list of artifacts: -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<jar destfile="${project.build.directory}/test-resources.jar">
<fileset dir="${project.basedir}/test-resources" />
</jar>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>${project.build.directory}/test-resources.jar</file>
<type>jar</type>
<classifier>test-resources</classifier>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
And in project B it will be normal dependency:
<dependency>
<groupId>myproject.groupId</groupId>
<artifactId>myartifact</artifactId>
<version>1.0-SNAPSHOT</version>
<classifier>test-resources</classifier>
<scope>test</scope>
</dependency>
Question: Should it work in all cases? Is it possible to pack resources without maven-antrun-plugin (using more 'lightweight' plugin)?
Just use jar:test-jar and declare the resulting JAR as a dependency (refer to this guide for more details). And while I don't understand the problem of having resources and classes in this jar, you can always exclude all .class files:
<project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>**/*.class</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
And to use it:
<project>
...
<dependencies>
<dependency>
<groupId>com.myco.app</groupId>
<artifactId>foo</artifactId>
<version>1.0-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependencies>
...
</project>
Accepted answer helped me, but it's not quite accurate in case you need regular jar of same project as well. It will delete *.class files from both jars.
Settings below translates to something like:
create me 2 jars: 1 regular, 1 test;
remove *.class files, but only from test jar
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
<configuration>
<excludes>
<exclude>**/*.class</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
Using maven-dependency-plugin we can put the resource needed in the right directory, only modifying the pom on dependent project is needed:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>generate-test-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>dependeeGroupId</groupId>
<artifactId>dependeeArtifactId</artifactId>
<version>dependeeVersion</version>
<type>test-jar</type>
<outputDirectory>${project.build.directory}/test-classes</outputDirectory>
<includes>resourceNeeded.txt</includes>
<overWrite>true</overWrite>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
type is used to get test resource
outputDirectory is used to put the resource usable in tests
Documentation here: https://maven.apache.org/plugins/maven-dependency-plugin/unpack-mojo.html
There is already a goal to build a test jar from maven.
Assuming you need something a little more flexible, you can use the jar plugin to package your test resources and run that goal with the main package goal with something like this.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>test-resources</classifier>
<includes>
<include>**/*.whatever-you-want</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
Whatever you want bundled would be added to the project-name-version-test-resources.jar when the jar goal is run.
You could then include it in a project via the same dependency you use above.

How do I make a Maven module not export a jar?

I have a Maven build with three modules.
Module A exports a jar.
Module B depends on A and exports a jar.
Module C is a set of regression tests that depend on A and B.
The reason the regression tests aren't just part of module B is that they should be able to run against multiple versions of A and B to ensure backwards compatibility. I want to be able to run deploy from the top level build to create A.jar and B.jar, but not C.jar. Is this possible?
<properties>
<maven.deploy.skip>true</maven.deploy.skip>
</properties>
If you don't need to create a JAR at all, you might want to add two more properties:
<jar.skipIfEmpty>true</jar.skipIfEmpty>
<maven.install.skip>true</maven.install.skip>
Note that you still need maven.deploy.skip, otherwise the build will fail during deployment.
The maven deploy plugin includes a skip options that prevents artifact deployment.
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
You can try adding that to project C.
Use below for module C:
<packaging>pom</packaging>
Use a packaging of type pom for C and rebind all required plugins:
<project>
...
<packaging>pom</packaging>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>process-test-resources</id>
<phase>process-test-resources</phase>
<goals>
<goal>testResources</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
</project>