Environment Variable with Maven - java

I've ported a project from Eclipse to Maven and I need to set an environment variable to make my project work.
In Eclipse, I go to "Run -> Run configurations" and, under the tab "environment", I set "WSNSHELL_HOME" to the value "conf".
How can I do this with Maven?

You can just pass it on the command line, as
mvn -DmyVariable=someValue install
[Update] Note that the order of parameters is significant - you need to specify any options before the command(s).[/Update]
Within the POM file, you may refer to system variables (specified on the command line, or in the pom) as ${myVariable}, and environment variables as ${env.myVariable}. (Thanks to commenters for the correction.)
Update2
OK, so you want to pass your system variable to your tests. If - as I assume - you use the Surefire plugin for testing, the best is to specify the needed system variable(s) within the pom, in your plugins section, e.g.
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
...
<configuration>
...
<systemPropertyVariables>
<WSNSHELL_HOME>conf</WSNSHELL_HOME>
</systemPropertyVariables>
</configuration>
</plugin>
...
</plugins>
</build>

The -D properties will not be reliable propagated from the surefire-pluging to your test (I do not know why it works with eclipse). When using maven on the command line use the argLine property to wrap your property. This will pass them to your test
mvn -DargLine="-DWSNSHELL_HOME=conf" test
Use System.getProperty to read the value in your code. Have a look to this post about the difference of System.getenv and Sytem.getProperty.

You could wrap your maven command in a bash script:
#!/bin/bash
export YOUR_VAR=thevalue
mvn test
unset YOUR_VAR

For environment variable in Maven, you can set below.
http://maven.apache.org/surefire/maven-surefire-plugin/test-mojo.html#environmentVariables
http://maven.apache.org/surefire/maven-failsafe-plugin/integration-test-mojo.html#environmentVariables
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
...
<configuration>
<includes>
...
</includes>
<environmentVariables>
<WSNSHELL_HOME>conf</WSNSHELL_HOME>
</environmentVariables>
</configuration>
</plugin>

Following documentation from #Kevin's answer the below one worked for me for setting environment variable with maven sure-fire plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<environmentVariables>
<WSNSHELL_HOME>conf</WSNSHELL_HOME>
</environmentVariables>
</configuration>
</plugin>

Another solution would be to set MAVEN_OPTS (or other environment variables) in ${user.home}/.mavenrc (or %HOME%\mavenrc_pre.bat on windows).
Since Maven 3.3.1 there are new possibilities to set mvn command line parameters, if this is what you actually want:
${maven.projectBasedir}/.mvn/maven.config
${maven.projectBasedir}/.mvn/jvm.config

There is a maven plugin called properties-maven-plugin this one provides a goal set-system-properties to set system variables. This is especially useful if you have a file containing all these properties. So you're able to read a property file and set them as system variable.

in your code add:
System.getProperty("WSNSHELL_HOME")
Modify or add value property from maven command:
mvn clean test -DargLine=-DWSNSHELL_HOME=yourvalue
If you want to run it in Eclipse, add VM arguments in your Debug/Run configurations
Go to Run -> Run configurations
Select Tab Arguments
Add in section VM Arguments
-DWSNSHELL_HOME=yourvalue
you don't need to modify the POM

You can pass some of the arguments through the _JAVA_OPTIONS variable.
For example, define a variable for maven proxy flags like this:
_JAVA_OPTIONS="-Dhttp.proxyHost=$http_proxy_host -Dhttp.proxyPort=$http_proxy_port -Dhttps.proxyHost=$https_proxy_host -Dhttps.proxyPort=$http_proxy_port"
And then use mvn clean install (it will automatically pick up _JAVA_OPTIONS).

I suggest using the amazing tool direnv. With it you can inject environment variables once you cd into the project. These steps worked for me:
.envrc file
source_up
dotenv
.env file
_JAVA_OPTIONS="-DYourEnvHere=123"

As someone might end up here changing his global Java options, I want to say defining _JAVA_OPTIONS is a bad idea. Instead define MAVEN_OPTS environment variable which will still be picked up automatically by Maven but it won't override everything like _JAVA_OPTS will do (e.g. IDE vm options).
MAVEN_OPTS="-DmyVariable=someValue"

Related

How to exclude a maven variable (same syntax as ksh variable)

i'm facing a sketchy problem, i have a ksh script that gets a ${USER} variable from a configuration file. i can't change the name of the variable, but since it's also the name of an environment variable in UNIX, the value gets replaced by the Maven builder.
Is there a way to exclude this variable from being changed by Maven?
Thanks.
Maven variables : ${var}
ksh variable :${var}
If this file is in src/main/resources and being filtered by the normal Maven resources plugin, you may configure an escape character to prevent this. Add configuration for the resources plugin and define the escape char to use.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version><fillInLatestVersion></version>
<configuration>
...
<escapeString>\</escapeString>
...
</configuration>
</plugin>
Then configure the resources file to escape anything Maven shouldn't replace.
Maven variables : ${var}
ksh variable : \${var}

Passing an options/arguments file to Maven compiler plugin

The javac command can be configured with a file by specifying that file on the command line with #:
javac #compileargs
I want to use that syntax in Maven so I can collect parts of the command line arguments in such a file instead of Maven's pom.xml.
The Maven compiler plugin does not seem to have a specific tag for that, so I tried compilerArgs:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<compilerArgs>
<arg>#compile-args</arg>
</compilerArgs>
<fork>true</fork>
</configuration>
</plugin>
But then javac complains:
javac: invalid flag: #compile-args
Usage: javac <options> <source files>
use --help for a list of possible options
If I get the actual command Maven is executing (with -X) and call that myself it works, though.
I recently had a similar problem with spaces in compiler options so I assume a similar process is screwing with me here.
Background info: The maven-compiler depends on the plexus compiler.
If the build process gets forked it will take all specified arguments and create a temporary config file on its own (see the code). The argument file will also include the user defined argument file, but the documentation points out that:
Use of the at sign (#) to recursively interpret files is not supported.
This means referencing an options file from Maven is not possible.

change classpath in Appassembler - Maven Plug-In

I'm using default appassembler configuration for generating execution script:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<configuration>
<programs>
<program>
<mainClass>SomeMainClass</mainClass>
<name>data-generator</name>
</program>
</programs>
</configuration>
</plugin>
after generating, my execution script contains lines such as:
set CLASSPATH = C:\Program Files (x86)\my-program\bin\\..\repo"\junit\junit\4.10\junit-4.10.jar
The goal is to change this paths to the following:
set CLASSPATH = C:\Program Files (x86)\my-program\bin\..\lib\junit\junit\4.10\junit-4.10.jar
Is there some good way to achieve this?
I've seen there are many optional parameters for this plugin but I'm not sure how to use it.
Could you bring more details to your question?
If you want to change default repository folder name, which is "repo", you can add following to configuration section
<repositoryName>lib</repositoryName>
All of your dependencies will be put to lib folder, so CLASSPATH will be also changed.
If you would like to shorten your CLASSPATH, you may add this option
<useWildcardClassPath>true</useWildcardClassPath>
Please tell me, if it solved your problem.

Alternate Output Directory for JavaDoc

I'm trying to configure an alternate output location for the JavaDocs in my multi-module maven project. I configured the maven-javadoc in the parent POM to look like this:
<build>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9</version>
<configuration>
<noqualifier>all</noqualifier>
<reportOutputDirectory>
${project.reporting.outputDirectory}/api
</reportOutputDirectory>
<destDir>api</destDir>
</configuration>
</plugin>
...
</build>
And then here is where I set the project.reporting.outputDirectory.
<properties>
<project.reporting.outputDirectory>
./module-webapp/src/main/webapp/docs
</project.reporting.outputDirectory>
</properties>
However, Maven doesn't seem to care for the above configuration, and is outputting the JavaDoc in the default directory notwithstanding. Why is this?
Also, I used a relative path for my project.reporting.outputDirectory variable. Will this relative path mean the same thing when I run mvn javadoc:javadoc in the sub-modules as when I run it in the parent module?
Thanks in advance... much appreciated!
You need to change the name of your variable. project.reporting.outputDirectory is a built-in variable and maven is overriding your setting of it.
Note that you might still need to set the directory relative to project.reporting.outputDirectory, or something like ${basedir} to actually get this to work.
Also keep in mind, based on my reading of the documentation, your final directory will be ./module-webapp/src/main/webapp/docs/api/api, which may not be exactly what you want
as far as relative directories and submodules go, each build tends to be self-contained, so it will deposit javadocs relative to each sub build.
Found out what was wrong. For some reason, when I remove ${project.reporting.outputDirectory} and type in the path directly, it works. For some other reason, when I use any other variable name (other than the above) it works.

Encoding issue when building with mvn

I'm currently working on a Maven plugin that uses JAXB. The problem is that whether I launch a clean install in IntelliJ or in a console, I don't get the same results. JAXB is reading an XML file encoded in UTF-8, which contains special characters.
In IntelliJ, these characters are read without any problem.
But in the console, these characters are replaced with '?' (I can see it if I do a sysout).
I found the source of my problem, but I don't really understand it and I don't know how to solve it: when IntelliJ runs mvn, it adds an extra parameter -Dfile.encoding=UTF-8
java -classpath /usr/share/maven/boot/plexus-classworlds-2.4.jar -Dclassworlds.conf=/usr/share/maven/bin/m2.conf -Dmaven.home=/usr/share/maven -Dfile.encoding=UTF-8 org.codehaus.plexus.classworlds.launcher.Launcher clean install
When I run mvn in command line, I can add this extra parameter but it will appear after the class name:
java -classpath /usr/share/maven/boot/plexus-classworlds-2.4.jar -Dclassworlds.conf=/usr/share/maven/bin/m2.conf -Dmaven.home=/usr/share/maven org.codehaus.plexus.classworlds.launcher.Launcher -Dfile.encoding=UTF-8 clean install
In both cases, if I sysout the content of System.getProperty("file.encoding"), I get the same value "UTF-8", but a different behaviour.
Of course I configured my pom.xml correctly using a property like this:
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
I also tried to add a second property named "file.encoding" but it does not help.
My question is: why does the position of this system property change the behaviour of my program, and how can I fix my problem when I run mvn from command line?
Thanks in advance.
Maybe try including this XML in your pom.xml file:
<project>
[...]
<build>
[...]
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.3</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</source>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</build>
</project>
As suggested in other questions, the JVM starts with a default file encoding (usually the system file encoding) which is used every time Readers and Writers are used without an explicit encoding. Overriding the system property file.encoding at runtime does not change this behavior, you really have to specify -Dfile.encoding when starting the JVM if you want it to be the default encoding.
To fix my issue, I reused project.build.sourceEncoding in my Maven plugin (I had this problem in a custom plugin) to override file.encoding at runtime, and use this file.encoding to instantiate InputStreamReader and OutputStreamWriter with an explicit encoding as 2nd parameter.
As resources were correctly copied by the maven-resource-plugin in UTF-8, my problem was gone :D.

Categories