How can I append to the system path for Maven Surefire tests that use DLLs? - maven

I'd like to be able to append a lib directory to the system path to allow Maven to run unit tests that (gah) use DLL native libraries.
I have so far used <argLine>-Djava.library.path=${path.dll}</argLine> to add my DLL path as a library path. However, Windows still wants to resolve DLLs via the path, and I'm getting:
java.lang.UnsatisfiedLinkError
So, is there a way of providing a modified system path to Surefire?
Thanks in advance for your help.

Turns out the following config was necessary:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
...
<environmentVariables>
<PATH>${basedir}\..;${java.library.path}</PATH>
</environmentVariables>
...
</configuration>
</plugin>

Related

Can I set DYLD_LIBRARY_PATH with maven-surefire-plugin?

In a Java project, I depend on a third-party native library that in turn loads dependency dylibs via DYLD_LIBRARY_PATH. I've successfully run tests via Tycho's surefire plugin by setting this with the environmentVariables property of the plugin config, but a similar setup in a non-OSGi project leaves the DYLD_LIBRARY_PATH variable unset.
Here's a snippet of my functioning Tycho configuration:
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-surefire-plugin</artifactId>
<version>0.25.0</version>
<configuration>
<argLine>-Dfile.encoding=UTF-8 -Djava.library.path="${dylib-program}"</argLine>
<environmentVariables>
<DYLD_LIBRARY_PATH>${dylib-program}</DYLD_LIBRARY_PATH>
</environmentVariables>
</configuration>
</plugin>
With that, the tests run correctly, and outputting System.getenv("DYLD_LIBRARY_PATH") shows the set path.
Here's the equivalent snippet from my non-Tycho config:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Dfile.encoding=UTF-8 -Djava.library.path="${dylib-program}"</argLine>
<environmentVariables>
<DYLD_LIBRARY_PATH>${dylib-program}</DYLD_LIBRARY_PATH>
<OtherVar>bar</OtherVar>
</environmentVariables>
</configuration>
</plugin>
When I run this, however, the dependency library doesn't load properly and System.getenv("DYLD_LIBRARY_PATH") returns null. System.getenv("OtherVar"), however, returns "bar", so setting environment variables generally seems to work. That makes me suspect that there's something peculiar about DYLD_LIBRARY_PATH (and the same happened with LD_LIBRARY_PATH, but not PATH).
The behavior is the same when run in Eclipse (either as-is or with the path also set in the Run Configuration environment) and via the command line (again either as-is or with the environment variable explicitly exported before the run). The Tycho and non-Tycho projects are run on the same machine, with the same tools (other than the test plugins). I'm using macOS 10.12.3, Java 1.8.0_111, and Maven 3.3.9.
Is there a general limitation about setting this property, at least on a Mac, or is there a way I can work around this?

How to generate a resource to be included in Jar file with maven?

During my build I need to some files to be generated by an external tool. For my minimal compilable example I reduced my "external tool" to the following script:
mkdir -p target/generated-resources
echo "hello world" > target/generated-resources/myResource.txt
Now I want to execute my external tool during build and the generated resource should be included in the war file. I could not find any documention on how that should be done, so it was just a guess that I need to write my generated resource to target/generated-resources. So maybe that is a problem?
I created a pom.xml file with the following build configuration:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>./createResource.sh</executable>
</configuration>
</plugin>
</plugins>
</build>
If I run mvn package my createResource.sh script gets executed successfully and the myResource.txt file is created. However the myResource.txt file is not included in the resulting .jar file.
I noticed that it works if I add
<resources>
<resource>
<directory>target/generated-resources</directory>
</resource>
</resources>
to my build config, but I fear that this may cause problems if other plugins which may use this directory differently (Do they? I could not really find anything about the conventions of the target directory).
Additionally I'd prefer a solution that works with the usual maven conventions (if a convention for this case exists).
How do I correctly generate a resource to be included in the jar file during build using maven?
Convention (or main usage at least)for Maven is to generate resources inside (target/generated-resources/[plugin/process]).
But unlike generated sources and compiler plugin, generated resources are not handled specifically by the jar plugin, so you do have to add it as a resource (with a new resource like you did or the build-helper-plugin).
If you follow the convention to place everything you generate under a sub-directory of generated-resources, you should have no fear about how other plugins use it.

Configure Maven to look at local directory while running tests

We are using JBehave and while running test we need to add a local folder and jars to the classpath while running the tests.
The problem is the local folder might vary from system to system. We want the tests to run by looking at the jars installed on that system and the resources defined on that system.
How to add a dependency to maven that could change from system to system?
You can use environment variables in your pom.xml using ${env.VARIABLE_NAME}. If you have the path to your local folder in the pom, you could replace it by a variable. If you do so you have to set that variable on every system you execute the maven job on. I have found some guides for linux and windows on how to do that. Hope this fits your problem.
The test are executed by the maven-surefire-plugin. The plugin has only one goal surefire:test and this goal supports the configuration of additionalClasspathElements.
You can find a usage example here. The example configuration on this page looks like this:
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.2</version>
<configuration>
<additionalClasspathElements>
<additionalClasspathElement>path/to/additional/resources</additionalClasspathElement>
<additionalClasspathElement>path/to/additional/jar</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>
</plugins>
</build>
[...]
</project>
I would go this way. To change the local folder location for each system you can use environment variables or different maven profiles.

maven prevent denpendency compile

I have a custom jar which including java sources; Maven tries to compile when it builds. How do I skip source compile in the jar file? I have tried such as exclude with some pattern in the compiler-plug in and source directory define but I have not get any luck. Thanks!
C05
This is a normal behavior of javac that searches the whole classpath for source files to compile unless the -sourcepath option is given (and this would be the solution here).
Unfortunately, there is a Jira issue about -sourcepath not being passed to javac by the Maven Compiler Plugin (see MCOMPILER-98). But there is a workaround:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArguments>
<sourcepath>${project.basedir}/src/main/java</sourcepath>
</compilerArguments>
</configuration>
</plugin>

Where should I put application configuration files for a Maven project?

I'm using the Maven Application Assembler plugin to generate stand-alone executables from my Java project. The application reads in configuration files, including Spring files. The Application Assembler plugin has an option (activated by default) to add a etc/ directory to the application's classpath, but what should I do to have the plugin copy my configuration files to this directory?
Or more generally, where is in Maven the kosher location for application configuration files that should NOT be packaged in the artifact?
You can also use resource filtering:
http://maven.apache.org/guides/getting-started/index.html#How_do_I_filter_resource_files
turn on filtering:
...
<build>
...
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
</build>
...
make a file under src/main/resources like: application.properties
application.properties
configprop.1=${param1}
configprop.2=${param2}
Then setup a profile and set some properties perhaps in a settings.xml
that sets different properties depending on if this is a dev or production build.
see: http://maven.apache.org/guides/introduction/introduction-to-profiles.html
I have different properties set depending on if this is the build server, dev or a production deployment
mvn -Denv=dev || mvn -Denv=dev-build || mvn -Denv=production
The maven link has a pretty good description.
For folks who have come to this more recently there is, since version 1.1 of the Application Assembler Plugin, the optional parameters configurationSourceDirectory and copyConfigurationDirectory. Please find them in an example POM.xml extract below:
<configuration>
<!-- Set the target configuration directory to be used in the bin scripts -->
<configurationDirectory>conf</configurationDirectory>
<!-- Copy the contents from "/src/main/config" to the target
configuration directory in the assembled application -->
<copyConfigurationDirectory>true</copyConfigurationDirectory>
<!-- Include the target configuration directory in the beginning of
the classpath declaration in the bin scripts -->
<includeConfigurationDirectoryInClasspath>
true
</includeConfigurationDirectoryInClasspath>
...
</configuration>
More information is here
You could try the maven assembly plugin. I used it in conjunction with the appassembler plugin.
Configure appassembler to point to whatever name you want for your configuration directory, if you don't want 'etc'. The assembly plugin assembles everything in its own output directory, so I configure the assembly plugin to copy the bin and repo dirs from the appassembler directory into its output dir, then I have it copy the config files (mine are in src/main/config) into the expected config dir. There is some duplication in this, because you are copying the appassembler outputs, but that didn't really bother me.
So what you have after executing the assembly plugin is your bin, repo, and config dir are all peer directories under the assembly output directory. You can configure it to have a different structure if you prefer, I just wanted mine to mirror the appassembler structure.
The nice thing is that you can also configure the assembly plugin to change your binaries to executables, which I could't see how to do with appassembler. And, if you then bind appassembler:assemble and assembly:single goals to the package phase, all you have to do is 'mvn package', and it assembles everything.
I don't know if I understand you correctly. But what I have done in the past for a project where I needed to copy configuration files, is use the Maven AntRun plugin. What I did is execute the plugin in the process-resources phase and copied my configuration files to the specified directory using the Ant copy task. The Assembler plugin executes in the package phase so it should pick up your configuration files if you put it in the right place. Hope this answers your question a little bit.
I had been looking for an answer to what I think is your question, or at least a very similar question. Maven allows you to specify directories for resources using the maven-resources-plugin. I have a few configuration files in one of my resource directories. I've noticed that by putting copies of those files in the etc/ directory that you mention (which is at the beginning of my CLASSPATH) I can change values in those files for use at run time. I then wanted to have that etc/ directory created with copies of everything from my resource directory by default. The copy-resources goal from the maven-resources-plugin allowed me to do that. This stanza from Examples > Copy Resources on the left sidebar (I'm limited to 2 links in this post) is what did it for me:
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/extra-resources</outputDirectory>
<resources>
<resource>
<directory>src/non-packaged-resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
...
</build>
...
</project>

Resources