Maven and copying at test time - maven

How can I have maven copy some resource files from another project right before the junit test cases are run?
I want this because the json files are maintained by the ui team for their testing purposes, so I want to use those same files to run against our layers so that we know we don't break the expected output when we change our code.

One option is to use the maven dependency plugin to selectively "unpack" the files from the project which has those files.
For example say the project in which the resource file is com.foo.bar:myArtifact:jar, so you can do something like
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>unpack</id>
<!-- You could a phase of your choice based on needs -->
<phase>compile</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.foo.bar</groupId>
<artifactId>myArtifact</artifactId>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}</outputDirectory>
<includes>*.json</includes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
This will copy all .json files (just an example) to the current project's build output directory.
You can refer to the dependency plugin for more configuration options.
Hope this helps.

Related

Generate Javadoc for multimodule project

I have read everything I can find on solving this and my attempts still fail. The best I can do is to get the Javadoc of exactly one module to show up--the last one built. (For now, I'm not trying to bundle Javadoc into any JARs. I'm also not trying to do anything "site".) I just want to put Javadoc for easy access into a subdirectory under the project root.
Here's what's in my parent pom.xml:
<build>
<plugins>
.
.
.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<noqualifier>all</noqualifier>
<reportOutputDirectory>${user.dir}/documents</reportOutputDirectory>
<destDir>javadoc</destDir>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
What I'm putting into subordinate pom.xml files is identical to the above except for
<goals>
<goal>javadoc</goal>
</goals>
I have played with replacing the <execution> in the parent and sometimes subordinate pom.xml files with:
<execution>
<id>aggregate</id>
<goals>
<goal>aggregate</goal>
</goals>
</execution>
but it makes no difference.
I think the following configuration is the reason your reports get overwritten:
<configuration>
<reportOutputDirectory>${user.dir}/documents</reportOutputDirectory>
</configuration>
All module builds will be written to the same directory, hence overwriting the previous build.
The solution is to use the default output directory and configure the output directory for the aggregated javadoc instead. This way the reactor build will create javadoc output files in each module's target directory. These can then be used by the aggregate goal to be combined.
This can be done by configuring your parent POM as follows:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<!-- Default configuration for all reports -->
<noqualifier>all</noqualifier>
<destDir>javadoc</destDir>
</configuration>
<executions>
<execution>
<id>aggregate</id>
<goals>
<goal>aggregate</goal>
</goals>
<configuration>
<!-- Specific configuration for the aggregate report -->
<reportOutputDirectory>${user.dir}/documents</reportOutputDirectory>
<destDir>javadoc</destDir>
</configuration>
</execution>
...
</executions>
</plugin>
...
</plugins>
</build>
(there is no need for any additional configuration in the module POM files)
The aggregated javadoc can now be created by running
mvn compile javadoc:javadoc javadoc:aggregate
(note that the compile or package goal is required for reactor to resolve inter-module dependencies)

How to get rid of duplicate class errors in Intellij for a Mavenized project using Lombok

I have a Maven managed Lombok project and I use Intellij. After building, I always get lots of errors in Intellij about duplicate classes because of the generated sources in target/generated-sources/delombok. Is there something I can do to git rid of these errors? Right now I just delete the target folder, but this is really irritating to have to do.
I have the standard configuration in Maven and the Lombok source code in is in src/main/lombok:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.16.8.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>delombok</goal>
</goals>
</execution>
</executions>
</plugin>
<profiles>
<profile>
<id>lombok-needs-tools-jar</id>
<activation>
<file>
<exists>${java.home}/../lib/tools.jar</exists>
</file>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.16.8.0</version>
<dependencies>
<dependency>
<groupId>sun.jdk</groupId>
<artifactId>tools</artifactId>
<version>1.8</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
</profiles>
According to delombok goal documentation: the default output directory is:
${project.build.directory}/generated-sources/delombok
I have found an JetBrains Team member comment stating that:
IDEA automatically excludes the build 'target' folder, providing that there are no generated sources under it, otherwise it excludes all sub-folders but the generated.
If you have some generated code or build artifacts that you want being excluded, you may put it under the 'target' folder.
This means that /generated-sources directory is by default not excluded and if you intend on excluding some files you should place them under parent /target directory and NOT under /generated-sources.
To achieve this you should configure the plugin and provide non-default <outputDirectory>:
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.16.18.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>delombok</goal>
</goals>
</execution>
</executions>
<configuration>
<sourceDirectory>src/main/java</sourceDirectory>
<outputDirectory>${project.build.directory}/delombok</outputDirectory>
<addOutputDirectory>false</addOutputDirectory>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
This will stop IDEA from yielding Duplicate class found in (...) warnings.
I tried Krzusiek's solution but IntelliJ would still mark my source files from src/main/java as duplicated.
After many failed attempts to tweak the lombok-maven-plugin I eventually decided to get rid of the delombok folder after compilation. That folder only server as an intermediary stage for compilation (in my case I needed it to use lombok with AspectJ compiler via the aspectj-maven-plugin) and there's no real need to keep it once your source files have been compiled.
Manually removing the delombok folder after each compilation is a real bummer, so I just configured an additional execution of the maven-clean-plugin which would specifically target the delombok folder.
Your POM should contain:
<build>
<sourceDirectory>${project.build.directory}/generated-sources/delombok</sourceDirectory>
<plugins>
<!-- will delombok source files into /target/generated-sources/delombok -->
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.16.16.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>delombok</goal>
</goals>
</execution>
</executions>
<configuration>
<addOutputDirectory>false</addOutputDirectory>
<sourceDirectory>src/main/java</sourceDirectory>
</configuration>
</plugin>
<!-- other plugins bound to compile phase should go here -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<executions>
<execution>
<id>delombok-removal</id>
<phase>compile</phase>
<goals>
<goal>clean</goal>
</goals>
<configuration>
<excludeDefaultDirectories>true</excludeDefaultDirectories>
<filesets>
<fileset>
<directory>${project.build.sourceDirectory}/com</directory> <!-- assuming your root package is something like com.mycompany -->
</fileset>
</filesets>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The idea is to remove generated-source from sources. I could do it from Project Structure -> Select from the list of packages and in right hand side find the folders that are being used to derive sources for that package. If you find generated-source in that list remove it.
you just need to unmark the folder with generated sources in Intellij and will be fine.
Firstly, you have to apply to Krzysiek's answer - move generated_sources directory under target so it will be /target/generated_sources. The next step is to unmark given directory as generated sources root. Then you have to right click on given project in Intellij, select Maven and then Reload project. After that do the same but this time go Maven -> Generate Sources and Update Folders. If you have multi module project and one module depends on each other i.e. module A depends on B then you have to start with B first.
This solution suggested by Andrey Dernov here worked for me with Maven.
Enable Settings (Preferences on macOS) > Build, Execution, Deployment > Build Tools > Maven > Runner > Enable "Delegate IDE build/run actions to maven" option

Where do generated DEPENDENCIES files come from?

In quite a lot of Apache project there is a file called DEPENDENCIES which is generated from the POM and all POMs of transitive dependencies. However I couldn't find any information about how these files are generated. I suspect there is a Maven plugin for this...
Here is an example:
https://raw.githubusercontent.com/sonatype/maven-demo/master/DEPENDENCIES
How can I generate such a file?
I have made an example to show how this works:
<build>
<plugins>
<plugin>
<artifactId>maven-remote-resources-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<resourceBundles>
<resourceBundle>org.apache:apache-jar-resource-bundle:1.4</resourceBundle>
</resourceBundles>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The tricky plugin is the maven-remote-resouces-plugin which can handle velocity templates which will to the trick here.

Run JUnit Tests contained in dependency jar using Maven Surefire

I have a jar in my maven repository that contains junit tests, which should be run in different projects, because it is able to inspect the project and test for certain features of it. Unforunately surefire doesn't pick up tests that are contained in a jar, as this Feature Request shows.
In the feature request they propose to unpack the jar to be then executed by surefire.
I successfully unpacked the jar using the maven-dependency-plugin, but the contained tests are not executed anyway. This is how I configured the maven-dependency-plugin to unpack my jar:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>process-test-classes</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>de.mwx.test</groupId>
<artifactId>selenium-test-base</artifactId>
<version>0.1</version>
<overWrite>true</overWrite>
<outputDirectory>
${project.build.directory}/classes
</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
Any help would be appriciated.
There is a way of running a test in maven from another jar.
from maven-surefire-plugin version 2.15 you can tell maven to scan your test jars for tests and run them.
You don't need to extract the tests jar.
Just add a dependency to your test jar and:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<dependenciesToScan>
<dependency>test.jar.group:test.jar.artifact.id</dependency>
</dependenciesToScan>
</configuration>
</plugin>
Took this stuff from https://gist.github.com/aslakknutsen/4520226
And https://issues.apache.org/jira/browse/SUREFIRE-569
As expected, this works for JUnit and Testng. Will probably work for anything that surefire can run.
(This is just restating what is in a comment above from khmarbaise, but since it wasn't clarified, I think it's worth restating):
Use the test-classes directory instead of the classes folder as outputDirectory:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>process-test-classes</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>de.mwx.test</groupId>
<artifactId>selenium-test-base</artifactId>
<version>0.1</version>
<overWrite>true</overWrite>
<outputDirectory>
${project.build.directory}/test-classes
</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
As described in the issue you need to have a Suite which is contains in your project which is NOT located in the test jar.

How to use artifactId with different filename in dependencies

Using Artifactory and Maven, how can one refer to a dependency with the correct group/artifactId/version but use a filname that differs from the artifactId-version.end style?
The problem comes with a dll that cannot be renamed, and the mandatory? Artifactory naming convention.
edit
found one possible expensive way for this specific problem where the filename cannot include the dash-sign: creating a new Artifactory repository layout for which the pro-version is needed - so unfortunately, that is not an option!
partly solution for jUnit tests
using the maven-dependency-plugin and the maven-surefire-plugins one can make jUnits work. unfortunately, it does not solve the problem that the specific sapjco3.dll cannot be found when deployed within a war to a server.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<id>copy</id>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>sapjco</groupId>
<artifactId>sapjco3</artifactId>
<version>3.0.7</version>
<type>dll</type>
<classifier>win32</classifier>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</artifactItem>
</artifactItems>
<stripVersion>true</stripVersion>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemProperties>
<property>
<name>java.library.path</name>
<value>${project.build.directory}/lib</value>
</property>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
Maven does not care for filenames, it cares for their coordinates. Add your DLL correctly to your remote repo and maven will do the rest.
A dependency snippet might be:
<dependency>
<groupId>com.company</groupId>
<artifactId>my.artifact</atifactId>
<version>1.0</version>
<type>dll</type>
<classifier>win32</classifier>
</dependency>
After you have done this, use either dependency:copy-dependencies or dependency:copy to change the filename at build time.

Resources