Set `file.encoding` from `pom.xml` - java

What incantation do I put into pom.xml which will be equivalent to
export JAVA_TOOL_OPTIONS='-Dfile.encoding=UTF-8'
in .profile?
I tried
<configuration>
<file.encoding>UTF-8</file.encoding>
</configuration>
in maven-compiler-plugin and
<properties>
<file.encoding>UTF-8</file.encoding>
</properties>
in top level and it did not work.
The main idea is to set this from pom.xml, NOT from the environment
(I have no control over what environment this will be run under).
Again, I am not interested in any solution which modifies .profile et al.

The default solution is to use the following:
<project>
...
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
...
</project>
and the maven-compiler-plugin has a different configuration and in particular uses the above property.

Try the following:
<configuration>
...
<systemProperties>
<systemProperty>
<name>propertyName</name>
<value>propertyValue</value>
</systemProperty>
...
</systemProperties>
</configuration>
This should work. At least it works for me with other maven plugins.

If you want to specify the encoding on unit test level you can use the following solution.
This is set on startup of the plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<skipTests>${skip.unit.tests}</skipTests>
<enableAssertions>true</enableAssertions>
<argLine>${surefireArgLine} -Dfile.encoding=UTF-8</argLine>
</configuration>
</plugin>

Related

How to modify mvn.cmd to get the correct jdk build version in MANIFEST.MF file

I have installed 2 version of java on my machine, 1.7 and 1.8.
for building my java projects I'm using maven 3.5.0.
There are some cases when I have to build my java project using java 1.7,
So I'm changing my %JAVA_HOME% environment variable to "C:\Program Files\Java\jdk1.7.0_80" from "C:\Program Files\Java\jdk1.8.0_131".
Then I thought if I can make so, that pom.xml determine the version of java, by which the project should be build.
At first my pom.xml was looked like this
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
...
</plugins>
as you can see there is <source> and <target> tags but this tags does not works for java 1.7,1.8, maybe it worked for earlier versions.
So I had to make some changes in Mavens "settings.xml" and in "pom.xml" files:
settings.xml
<profiles>
<profile>
<id>compiler</id>
<properties>
<JAVA_1_7_HOME>C:\Program Files\Java\jdk1.7.0_80\bin\javac</JAVA_1_7_HOME>
<JAVA_1_8_HOME>C:\Program Files\Java\jdk1.8.0_131\bin\javac</JAVA_1_8_HOME>
</properties>
</profile>
</profiles>
<activeProfiles>
<activeProfile>compiler</activeProfile>
</activeProfiles>
pom.xml
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
<executable>${JAVA_1_7_HOME}</executable>
<verbose>true</verbose>
<fork>true</fork>
</configuration>
</plugin>
...
</plugins>
Then Make build using mvn install and it worked!!! If I changed executable to ${JAVA_1_8_HOME} the size of generated jar file changes.
But there is one Big Issue in MANIFEST.MF. the build version of JDK is 1.8.0_161, so MANIFEST.MF will lie someone, who want to find out build jdk version.
The reason of this is that Maven (mvn.cmd file) looks to %JAVA_HOME% and takes the path of java. if there is no %JAVA_HOME% variable in environment, it takes the default system java -version which is in my case 1.8.0_161 (JRE version).
here is the mvn.cmd code snippet
#REM ==== START VALIDATION ====
if not "%JAVA_HOME%"=="" goto OkJHome
for %%i in (java.exe) do set "JAVACMD=%%~$PATH:i"
goto checkJCmd
Now here is a challenge
how to tell mvn.cmd that it was build by java 7 which is written in pom.xml?
how to make mvn.cmd to write the correct build jdk in MANIFEST.MF file?
I've just tried to use maven-archiver plugin to force a custom MANIFEST.MF and somehow determine the "Build-Jdk" entry. But it seems to always override the java version. If you'd like to have a try, check https://maven.apache.org/shared/maven-archiver/examples/manifestFile.html
I don't think changing maven.cmd can make this script aware of the project peculiarities.
If the point is to avoid changing JAVA_HOME manually before some of your builds, maybe all you need is to make a wrapper batch file for maven
referencing your jdk1.7:
SET "JAVA_HOME=C:\Program Files\Java\jdk1.7.0_80"
mvn.cmd %*
Save this batch file as mvn_j7.bat inside your [MAVEN_HOME]\bin folder.Then you can run it anywhere, just like in the example below:
mvn_j7 clean package
Here's solution, how to fix incorrect JDK version in MANIFEST.MF file . This fix will never let you to build your project incorrectly (if your configuration will correct).
At first it is necessary to remove Java link C:\Program Files\Java\jdk1.7.0_80\bin or %java_home%\bin from environment PATH.
Then you have to add new Profiles in maven settings.xml file
settings.xml
<profile>
<id>buildByJava7</id>
<activation>
<property>
<name>java</name>
<value>7</value>
</property>
</activation>
<properties>
<java-version>1.7</java-version>
<java-1.7>C:\Program Files\Java\jdk1.7.0_80\bin\javac</java-1.7>
<jdk>1.7.0_80</jdk>
<wsimport>C:\Program Files\Java\jdk1.7.0_80\bin\wsimport.exe</wsimport>
</properties>
</profile>
<profile>
<id>buildByJava8</id>
<activation>
<property>
<name>java</name>
<value>8</value>
</property>
</activation>
<properties>
<java-version>1.8</java-version>
<java-1.8>C:\Program Files\Java\jdk1.8.0_131\bin\javac</java-1.8>
<jdk>1.8.0_131</jdk>
<wsimport>C:\Program Files\Java\jdk1.8.0_131\bin\wsimport.exe</wsimport>
</properties>
</profile>
As you can see there is global Properties <java-version>, <java-1.8>, <jdk>, <wsimport>. you can activate Profile using mvn -Djava=7 or mvn -Djava=8 command
Now you have to change Pom.xml in this way
pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<verbose>true</verbose>
<fork>true</fork>
<source>${java-version}</source> <!-- java compile version -->
<target>${java-version}</target> <!-- java compile version -->
<executable>${java-1.8}</executable> <!-- ..\bin\javac.exe file path -->
</configuration>
</plugin>
....
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
<manifestEntries>
<Build-Jdk>${jdk}</Build-Jdk> <!-- jdk version to set in manifest.mf file -->
</manifestEntries>
</archive>
</configuration>
</plugin>
...
in case if you are using wsimport to generate classes from *wsdl, you have to add executable with wsimport.exe file path.
please foresee, that this will not work if you have java link in a %PATH%
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<wsdlDirectory>${basedir}/src/main/resources/wsdl/app</wsdlDirectory>
<packageName>ge.jibo.app.client</packageName>
<sourceDestDir>${basedir}/target/generated-sources</sourceDestDir>
<keep>true</keep>
<bindingFiles>
<bindingFile>${basedir}/src/main/resources/wsdl/app/binding.xml</bindingFile>
<bindingFile>${basedir}/src/main/resources/wsdl/app/jaxb-binding.xml</bindingFile>
</bindingFiles>
<verbose>true</verbose>
<executable>${wsimport}</executable> <!-- ...\bin\wsimport.exe file path -->
</configuration>
</execution>
</executions>
</plugin>
After this modification you can just run command mvn -Djava=8 clean package
This command will activate buildByJava8 profile.
pom.xml will get all java versions and java/wsimport paths from profile, and everything will be compiled and build successfully and correctly.

Append the value of argLine param in maven-surefire-plugin

I am using maven-surefire-plugin + Sonar together and I would like to add some extra value to argLine parameter of the maven-surefire-plugin.
So I did it:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20.1</version>
<configuration>
<argLine>-DCRR.Webservice.isSimulated=true -D...</argLine>
</configuration>
</plugin>
...
</plugins>
</build>
But in this case I am overwriting the original value of the argLine parameter and Sonar does not generate jacoco.exec file.
I can see in the maven debug log (-X) that the value of argLine param without overwriting its value is -javaagent:/opt/jenkins/.../myproject-SONAR/.repository/org/jacoco/org.jacoco.agent/0.7.4.201502262128/org.jacoco.agent-0.7.4.201502262128-runtime.jar=destfile=/opt/jenkins/.../myproject-SONAR/target/jacoco.exec.
What is the proper way to APPEND the original value of this parameter (keep the original + add extra values)?
I am using Apache Maven 3.5.0, Java version: 1.8.0_131, vendor: Oracle Corporation.
The official documentation calls that late replacement.
If you do the following you will overwrite the value of the argLine parameter which is set by another plugins before, so DO NOT DO THIS:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-D... -D...</argLine>
</configuration>
</plugin>
The proper way to keep the existing values and add your configuration is to use #{...} syntax:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>#{argLine} -D... -D...</argLine>
</configuration>
</plugin>
OR you can set argLine as a property in your pom.xml file:
<properties>
<argLine>-DCRR.Webservice.isSimulated=true -D...</argLine>
</properties>
Both solutions above works properly.
Update for Apache Maven 3.8.3.
In my case only combination of both #zapee suggestions works, in other words it's important to add <argLine/> to <properties> and #{argLine} to configuration section. Example:
<properties>
<!-- This is required for later correct replacement of argline -->
<argLine/>
</properties>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>#{argLine} -D... -D...</argLine>
</configuration>
</plugin>
Hope, it helps somebody.
Thanks!
In my case it was:
<argLine>${tycho.testArgLine} -D...</argLine>

Stacking properties by specifying multiple Maven profiles on the command line

I finally got my test automation running using JUnit4 #Category for each test; they are marked as either PriorityHigh, PriorityMedium, or PriorityLow.
In my pom.xml I have each set up as a profile:
<profile>
<id>PriorityHigh</id>
<properties>
<testcase.category>com.categories.PriorityHigh</testcase.category>
</properties>
</profile>
<profile>
<id>PriorityMedium</id>
<properties>
<testcase.category>com.categories.PriorityMedium</testcase.category>
</properties>
</profile>
<profile>
<id>PriorityLow</id>
<properties>
<testcase.category>com.categories.PriorityLow</testcase.category>
</properties>
</profile>
Which is then used in the plugin section:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
<configuration>
<groups>${testcase.category}</groups>
<systemPropertyVariables>
<automation.driver>${browser.name}</automation.driver>
</systemPropertyVariables>
</configuration>
</plugin>
My issue is when I want to test both Medium and High, I specify
-P PriorityHigh,PriorityMedium
But instead of adding/concatenating, they overwrite and so only Medium tests run. To add extra difficulty, since pom.xml complains that ${testcase.category} only exists in profiles, and no default, I had to add this:
<testcase.category>com.categories.PriorityHigh,com.categories.PriorityMedium,com.categories.PriorityLow</testcase.category>
in case no profile is specified.
So two questions:
How to get the profiles to stack correctly in the "groups" node?
A better way to work it if no profile is specified (all tests should run)?
The easiest thing to do would be to ditch profiles and just use system properties:
<properties>
<testcase.category>com.categories.PriorityHigh,com.categories.PriorityLow</testcase.category>
</properties>
...
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<groups>${testcase.category}</groups>
...
</configuration>
</plugin>
Then:
mvn verify -Dtestcase.category=com.categories.PriorityHigh
# runs PriorityHigh tests
mvn verify -Dtestcase.category=com.categories.PriorityHigh,com.categories.PriorityLow
# runs PriorityHigh and PriorityLow tests
mvn verify
# runs PriorityHigh and PriorityLow tests
If you don't want to have to specify the fully qualified category class name on the Maven command line, you could use the Build Helper plugin to qualify the names for you:
<properties>
<testcase.category>PriorityHigh,PriorityLow</testcase.category>
</properties>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>build-fq-testcase-category</id>
<goals>
<goal>regex-property</goal>
</goals>
<configuration>
<name>fq.testcase.category</name>
<regex>([^,]+)</regex>
<value>${testcase.category}</value>
<replacement>com.categories.$1</replacement>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<groups>${fq.testcase.category}</groups>
</configuration>
</plugin>
Then:
mvn verify -Dtestcase.category=PriorityHigh
# just run PriorityHigh tests
mvn verify
# run PriorityLow and PriorityHigh tests
# etc.

How do I set in the pom to not compile tests?

How do I set in the pom to not compile tests in Maven? I've tried:
<properties>
<skipTests>true</skipTests>
</properties>
but in that case, Maven compile the tests but don't run them. I need Maven don't compile my tests.
You have to define maven.test.skip to true.
<properties>
<maven.test.skip>true</maven.test.skip>
</properties>
http://maven.apache.org/surefire/maven-surefire-plugin/examples/skipping-test.html
In my case a solution was to put tests in a profile (e.g. runTests), so when I want to run these tests, I add the parameter -PrunTests. Thanks for the replies.
Configure maven-compiler-plugin to skip the compilation.
Once again, I do not recommend it.
<project>
<properties>
<maven.test.skip>true</maven.test.skip>
</properties>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<executions>
<execution>
<id>default-testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<skip>${maven.test.skip}</skip>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
</project>
If you are using the surefire-plugin for executing tests, you can configure it to skip them based on a naming pattern:
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.14</version>
<configuration>
<includes>
<include>%regex[.*[Cat|Dog].*Test.*]</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
[...]
</project>
This, however, requires the tests file names to conform to the desired pattern(s). At work we are using this approach, and have our tests end with ..UnitTest or ..IntegrationTest, so that we can easily turn each of them off by modifying the regex in the corresponding build profile.
Take a look at Apache's documentation on the surefire plugin. You may find something more useful or better suited for your case.

Maven project dependency against JDK version

I have projects that need to be build with a specific version of the JDK.
The problem isn't in the source and target parameters but in the jars of the runtime used during compilation.
In some cases I get a compilation error if I try to compile with the wrong JDK, but sometimes the build is successful and I get runtime errors when using the jars.
For example in eclipse I have the ability to establish the execution enviroment for the project in the .classpath file.
Is there a way to handle such situation in maven?
What I would like to have is the ability to handle JRE dependency like other dependencies of the project in the POM file.
UPDATE:
The accepted solution was the best one when I asked this question, so I won't change it. Meanwhile a new solution to this kind of problems has been introduced: Maven Toolchain. Follow the link for further details.
I've found this article:
http://maven.apache.org/plugins/maven-compiler-plugin/examples/compile-using-different-jdk.html
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.1</version>
<configuration>
<verbose>true</verbose>
<fork>true</fork>
<executable>${JAVA_1_4_HOME}/bin/javac</executable>
<compilerVersion>1.3</compilerVersion>
</configuration>
</plugin>
</plugins>
[...]
</build>
[...]
</project>
I have projects that need to be build with a specific version of the JDK.
You can use the Maven Enforcer plugin to enforce the use of a particular version of the JDK:
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-versions</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireJavaVersion>
<version>1.5</version>
</requireJavaVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
</project>
But I'm not sure I really understood the question. If this is not what you want, maybe you could declare your JDK specific dependencies in profiles and use an activation trigger based on the JDK version. For example:
<profiles>
<profile>
<activation>
<jdk>1.5</jdk>
</activation>
...
</profile>
</profiles>
This configuration will trigger the profile when the JDK's version starts with "1.5".
I believe that this can be solved with following plugin in your pom:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
Here you target version 1.6 , or write your own version

Categories