Cannot define absolute path in maven plugin - java

I added the surefire plugin to maven, and need to add jars to the classpath for the tests to work. If the jar is in the same directory as pom.xml, it works fine:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<additionalClasspathElements>
<additionalClasspathElement>jooq-3.11.10.jar</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>
But if I define the absolute path, it doesn't find it. I need to point the jar to the location where it is. Why does this happen and how to make this work?
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<additionalClasspathElements>
// doesn't find this jar
<additionalClasspathElement>c:\my\path\jooq-3.11.10.jar</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>

I would suggest to use test scope dependencies like the following:
<dependency>
<groupId>org.jooq</groupId>
<artifactId>jooq</artifactId>
<version>3.11.10</version>
<scope>test</scope>
</dependency>
That will add the dependency automatically on the classpath for testing only. There is no need to add things like that manually with path in maven-surefire-plugin.

Related

Packaging jar file with source code using Maven so breakpoints can be used in Eclipse

Requirements
I am refactoring a Java application and am trying to move code out of a war file and into a jar file so it can be used across many different web applications. However, one of the requirements is that the developers still need to use breakpoints within the library. To do so I believe I need to package the source with the compiled code. Below is the build lifecycle
Build Lifecycle
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven
defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
Question
When I run mvn package and mvn source:jar package it creates two jar files, respectively
db-0.0.1-SNAPSHOT.jar
db-0.0.1-SNAPSHOT-sources.jar
Then I can attach the source to the dependency.
My question is two-fold
Is there anyway to package the source code into the same jar file as the compiled classes, and
Would this auto-attach the source code to the dependency in Eclipse, so that the developers don't need to do it automatically?
Putting the source code into the JAR is the wrong approach.
You create two JARs (as shown in your question). These JARs go to the repository. Then everyone who uses the JARS will automatically get the -sources as well. In the usual IDEs, like Eclipse and IntelliJ the -sources JAR is automatically used for debugging.
Instead of two Maven runs, you should add the source plugin to your POM. Then the -sources JAR is created during the normal build.

Maven copy-dependencies + shade - classpath management

To package a maven project with its dependencies, among many solutions, one may use maven-dependency-plugin with its goal copy-dependencies to get the dependencies in a folder besides, or one may use maven-shade-plugin to get all the code in a single jar.
I actually do both: I choose to have external dependencies (e.g. apache commons) as external libs, and my own dependencies (I have a multi-module maven parent project) shaded into a unique jar.
And it works, except for the classpath. I copy-dependencies with option excludeGroupIds to exclude my own maven group id. I shade with option to include only my own maven group id. Before that, I jar with option to add classpath to the manifest. All set, it works. But my classpath also contains my own dependencies that were actually shaded in the final jar.
It is no big deal, because the result works even with this erroneous classpath. But I wonder if there is a simple means to have the correct classpath, in order not to expose my internal structure to my users.
Here is a basic example demonstrating the problem:
<groupId>com.foo.bar</groupId>
<artifactId>com.foo.bar.launcher</artifactId>
<dependencies>
<dependency>
<groupId>com.foo.bar</groupId>
<artifactId>com.foo.bar.utils</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
</dependencies>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<excludeGroupIds>com.foo.bar</excludeGroupIds>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>com.foo.bar:*</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
The resulting manifest contains this:
Class-Path: lib/com.foo.bar.utils-0.0.1.jar lib/commons-lang3-3.8.1.jar while the com.foo.bar.utils one does not exist.
If you look into the following mvnrepository link maven shade plugin depends upon maven dependency tree. As per the above pom.xml maven dependency plugin, you have excluded com.foo.bar dependency. You can omit the maven-dependency-plugin to create fat jar. It is not mandatory to use in case of shade plugin.
You can use the following command to check and copy all the dependencies used in the project.
mvn dependency:copy-dependencies
https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-shade-plugin/3.2.1

maven exclude tests with surefire excludeTests option

I have a large project with sub-projects and want to use excludesFile to exclude test failures, and ignore them until the tests are fixed.
I believe there might be a way of achieving this with surefire plugin excludesFile option here.
I am very new to maven and would like get some examples or pointers on how this can be achieved.
To use excludesFile option,
Create a file containing file name patterns of your test files that you want to exclude.Example:Create a file at src/main/resources/exclude.txt with below 2 lines.
**/*1.java
**/*2.java
Add following in your maven-surefile-plugin configuration.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
<excludesFile>src/test/resources/exclude.txt</excludesFile>
</configuration>
</plugin>
</plugins>
You are done. All test files ending with 1.java and 2.java will be excluded.
There is other way also to exclude any tests from execution by using configuration in maven-surefire-plugin.
Example:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
<excludes>
<exclude>**/TestCircle.java</exclude>
<exclude>**/TestSquare.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
More information can be found here.

How to put maven zip dependency on classpath for Java tests

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

Empty directories are not copied during build from `scr/main/webapp`

This question prompted me to post a follow up question. During a maven build, empty directories are not copied from src/main/webapp, even though I have set the pom.xml to include empty directories:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<configuration>
<includeEmptyDirs>true</includeEmptyDirs>
</configuration>
</plugin>
How come empty directories are not copied?
I just met the same problem. This worked for me:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<includeEmptyDirectories>true</includeEmptyDirectories> <!-- since 2.4 -->
</configuration>
</plugin>
Your method didn't work because that "src/main/webapp" was not a resource directory.
The reason is due to bug MWAR-128 in maven. The solution is to upgrade Maven to r1498124. Alternately, you can include a placeholder file (ex. empty.tmp) and filter it like so:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>${maven.war.plugin.version}</version>
<configuration>
<packagingExcludes>**/empty.tmp</packagingExcludes>
</configuration>
</plugin>

Categories