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.
Related
I have a project in Windows-1254 file encoding and some of files are in UTF-8 encoding.
<properties>
<project.build.sourceEncoding>Windows-1254</project.build.sourceEncoding>
<project.reporting.outputEncoding>Windows-1254</project.reporting.outputEncoding>
<version.plugin.maven.resources>3.1.0</version.plugin.maven.resources>
<functionAppName>az-app-core</functionAppName>
</properties>
I added plugin in pom and compiles correctly with mvn compile.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
<executions>
<execution>
<id>compile1</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<excludes>
<exclude>**/StringUtil.java</exclude>
<exclude>**/TurkceInputTag_FaceLift.java</exclude>
<exclude>**/TurkceInputTag.java</exclude>
</excludes>
<encoding>Windows-1254</encoding>
</configuration>
</execution>
<execution>
<id>compile2</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<includes>
<include>**/StringUtil.java</include>
<include>**/TurkceInputTag_FaceLift.java</include>
<include>**/TurkceInputTag.java</include>
</includes>
<encoding>UTF-8</encoding>
</configuration>
</execution>
</executions>
</plugin>
But I need to compile project by command not just clean compile but also give all configurations(defined above compile1, compile2 executions) to maven like
maven compile-plugin:compile -Dexecutions/execution1/id=compile1,encoding=Windows-1254,excludes=....
I can't change File types encoding to only UTF-8 or Windows-1254 encoding. I need to compile project using both 2 encoding.
How can maven plugin compiles by command with configurations, encoding,executions etc.?
Unfortunately the command line for Maven is not as flexible as you might like it to be for what you're wanting to achieve. (I have quite a big question about why you're trying to achieve it, and can't just specify that information in the POM as you've demonstrated).
If you look at the goal documentation for maven-compiler-plugin:compile, you'll see that some of the options, like encoding, have a 'user property'. This, prefixed with -D to make it a system property, allow you to configure it from the command line:
mvn <goals/phases> -Dencoding=... -Dmaven.compiler.failOnError=...
But running a goal from the command line will give a single execution, not the set of two that you want. So your options might be:
Run the mvn command twice, with different options on each one. Tricky though as you can't specify inclusions/exclusions.
Split the project into more than one, having different options for encoding in each, and run those from the command line.
Get around whatever limitation it is that is giving you this issue in the first place, and run from the POM as you've defined rather than on the command line.
I second khmarbaise.
All source code files in one project need to have the same encoding. Choose one and convert the other source code files.
EDIT:
You mentioned that you could not convert the files, but unfortunately, you did not tell us why.
Whatever hinders you to do it, you need to solve that issue.
So if your colleagues, managers or customers tell you not to change encoding, then you need to solve this problem by talking to these people, explaining them that a Maven project needs to have one (and just one) source code encoding and convincing them to change that.
Feel free to comment on my answer if I misunderstood you.
When using jlink, a bin/java file is generated. This executable will accept VM options by specifying options on the command line in the usual way (such as -Dsystem.property=value or -Xmx1G).
jlink also provides a --launcher option to create an executable that can be run directly, instead of having to invoke the bin/java executable with a module name.
How do I make the launcher executable pre-configured to use my choice of JVM options?
You can use the add-options jlink plugin.
For example, if you want to set Xmx:
jlink --add-options="-Xmx100m" ...
To see a list of jlink plugins, run jlink --list-plugins.
The add-options plugin is currently documented (JDK14) as follows:
Plugin Name: add-options
Option: --add-options=<options>
Description: Prepend the specified <options> string, which may include
whitespace, before any other options when invoking the virtual machine
in the resulting image.
Beware that some of the plugins are, apparently, unstable (including add-options): https://docs.oracle.com/en/java/javase/12/tools/jlink.html
There are one or two ways of going about this,but mostly I'm going to concentrate on the default java ways.
Actual answer - Use JPackage. JLink is just the image of a runtime. JPackage is your distributable
Support for native packaging formats to give the end user a more natural installation experience. Specifically, the tool will support the following formats:
Windows: msi, exe
macOS: pkg, app in a dmg (drag the app into the Applications directory)
Linux: deb, rpm
The application will be installed in the typical default directory for each platform unless the end-user specifies an alternate directory during the installation process (for example, on Linux the default directory will be /opt).
The ability to specify JDK and application arguments at packaging time that will be used when launching the application
The ability to package applications in ways that integrate into the native platform, for example:
Setting file associations to allow launching an application when a file with an associated suffix is opened
Launching from a platform-specific menu group, such as Start menu items on Windows
Option to specify update rules for installable packages (such as in rpm/deb)
1) - Specify an #Args file
You can make an #args file that you can deploy (bundled) with your jlink app, and reference it when starting the application
java #args -m module/main
2) Use the new environment variable
JDK_JAVA_OPTIONS=--add-opens java.base/java.lang=...... -Xmx1G -Djdk.logging.provider=
https://docs.oracle.com/javase/9/tools/java.htm#JSWOR624
3) Use the JLink/JMod to specify main class in module
https://maven.apache.org/plugins/maven-jmod-plugin/plugin-info.html
<plugin>
<artifactId>maven-jmod-plugin</artifactId>
<version>3.0.0-alpha-1</version>
<extensions>true</extensions>
<configuration>
<module>
<mainClass>mainClass</mainClass>
</configuration>
</plugin>
4) Use JLink to create a custom launcher/Edit JDK_VM_OPTIONS
<plugin>
<artifactId>maven-jlink-plugin</artifactId>
<version>3.0.0-alpha-2-SNAPSHOT</version>
<extensions>true</extensions>
<configuration>
<noHeaderFiles>true</noHeaderFiles>
<noManPages>true</noManPages>
<stripDebug>true</stripDebug>
<verbose>true</verbose>
<compress>2</compress>
<launcher>customjrelauncher=module/mainClass</launcher>
</configuration>
<dependencies>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>${maven.asm.version}</version>
</dependency>
</dependencies>
</plugin>
In the generated .sh/.bat there is a variable to specify any custom addon's
You can also specify the main class descriptor in your module-info using moditect if you are using it:
<plugin>
<groupId>org.moditect</groupId>
<artifactId>moditect-maven-plugin</artifactId>
<executions>
<execution>
<id>add-module-infos</id>
<phase>package</phase>
<goals>
<goal>add-module-info</goal>
</goals>
<configuration>
<overwriteExistingFiles>true</overwriteExistingFiles>
<module>
<mainClass>mainClassLocation</mainClass>
</module>
</configuration>
</execution>
</executions>
</plugin>
According to the Spring boot documentation, it's possible to define additional command when using a remote shell based on Crash.
Default locations for these commands are classpath*:/commands/,classpath*:/crash/commands/
A property can be used to override the default locations but in the provided example, the custom command is located in resources.
In my opinion, custom commands (at least java commands) shouldn't be located in resources but in src/main/java.
It works fine when defining a custom path in resources but how can I define a custom path in src/main/java? Didn't find a way to do it for now!
If they're under src/main/java, they'll be compiled automatically which is not what you need. My solution was to simulate that directory as a resources folder, which in short translates to:
configure the compiler plugin to ignore that particular folder
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<excludes>
<exclude>crash/commands/*</exclude>
</excludes>
</configuration>
</plugin>
copy the files just like any regular resources in the target directory
<resource>
<directory>src/main/java/crash/commands</directory>
<targetPath>crash/commands</targetPath>
<filtering>false</filtering>
</resource>
Minor update & disclaimer:
As you may already know, there are a couple of closures which are executed on login/logout. At least with v1.3.1, which is what I'm blindly inheriting from spring-boot, it will pick the first login.groovy it finds in the classpath. My project's artifact is packaged in an RPM along with all the other dependencies. Since its name begins with r, it comes after crash.shell-1.3.1.jar which is where the defaults reside, so I had to do the following small hack to make it pick up my own scripts instead of the default ones:
<!-- hack to make CRaSH pick up login.groovy from our jar instead of the default one -->
<finalName>0_${project.artifactId}-${project.version}</finalName>
You can try to put your command at src/main/resources/commands/
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.
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"