How can I set Dfile.encoding=utf-8 when building maven project? - java

System.out.println(Charset.defaultCharset().displayName()); prints ISO-8859-1, so I want to set the defaultCharset to UTF-8.
When tried with java -Dfile.encoding=utf-8 -jar XXX.jar, I checked that default charset is set to UTF-8.
But is there a way to set Dfile.encoding=utf-8 option at maven packaging level, so that I can just run java -jar XXX.jar?
What I tried:
mvn clean package -Dfile.encoding=utf-8
pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<argLine>-Dfile.encoding=utf-8</argLine>
</configuration>
</plugin>
MAVEN_OPTS="-Dfile.encoding=utf-8" mvn clean package
I prefer controlling with pom.xml file.

You can define JDK_JAVA_OPTIONS environment variable as -Dfile.encoding=utf-8 to avoid typing it every time. See the java command documentation for details.
In OpenJDK 18 UTF-8 will be default for all operating systems: JEP 400.

The question is how to pass JVM args for Maven build before runtime.
Starting with Maven 3.3.1+ you can define JVM configuration via ${maven.projectBasedir}/.mvn/jvm.config file which means you can define the options for your build on a per project base. This file will become part of your project and will be checked in along with your project.
So, create .mvn/jvm.config in your project root with content:
-Dfile.encoding=utf-8
See the reference: https://maven.apache.org/configure.html#mvn-jvm-config-file

Related

What do I need to add to my pom.xml to run this specific Java file?

I'm not a Java dev and am unfamiliar with the packaging and building of Java programs. I'm trying to run this file: https://github.com/CodinGame/SpringChallenge2020/blob/master/src/test/java/Spring2020Main.java
by doing
mvn clean install
java -jar .\target\spring-2020-1.0-SNAPSHOT.jar
but I get this error:
no main manifest attribute, in .\target\spring-2020-1.0-SNAPSHOT.jar
I can't figure out for the life of me what I need to add to the pom.xml or whatever else I need to do to get this to work.
Any help will be appreciated.
A few things to understand about Java:
1) If you have a Maven project like this, code is divided between src/main/ and src/test/ directories. src/test/ is intended for unit tests. In your case, Spring2020Main is not actually set up as a unit test, so I'm not sure what the author intended here.
2) When you compile using mvn clean install, a jar (library) is built, but nothing from src/test will be included in the output.
Generally, tests are executed during build. And this one would have been, except it's not set up as a real junit test, so it didn't run during build.
3) You can move the file from src/test/java to src/main/java and it will be built into your resulting jar.
4) In this case, when you run the JVM, you need to specify a classpath. This is a list of all libraries to include when the application starts. You also need to specify the (fully qualified) name of the class to run:
java -cp target/spring-2020-1.0-SNAPSHOT.jar Spring2020Main
...the above won't work directly since there are more unsatisfied dependencies (the top level pom.xml brings in at least 3 other deps you'd also need to provide on the classpath).
As others pointed out, a solution could be to build a self-executing jar, but simplest for you would be to run this from an IDE:
Run this from IntelliJ. If you haven't installed it, install it.
1) File > New From Existing Sources, find the directory where this is coned to.
2) When asked, Import Project from Existing Model (Maven)
3) When the Project view is available (alt-1), or View > Tool Windows > Project, you can expand the structure till you find Spring2020Main in the test directory.
4) Right-click it and select Run.
For me, it exposed a web server running at http://localhost:8888/test.html
You can follow the steps below:
Move Spring2020Main.java to src/main/java/com/codingame directory
Add the following to your pom.xml after the </dependencies>:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.codingame.Spring2020Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Run maven build using mvn clean install
Execute the program using java -jar target/spring-2020-1.0-SNAPSHOT.jar
Info: Apache Maven Shade Plugin helps in building what is called an uber-jar or a fat-jar. This means that all the dependencies are packaged as part of the resultant jar file without the need for any 'libraries' that you'd need to add in the classpath when executing the jar file. As part of the final jar, we need to specify which file needs to be treated as the main file to be executed. This is typically done using META-INF/MANIFEST.MF file inside the uber-jar. That's what the transformer specified inside the configuration of the plugin does for us.
The project you've linked has only a basic setup for compilation (that would be enough to run it from IDE though).
What you need is an executable jar. Check this thread.
As others mentioned (and I failed to notice) the class you linked to is a test class, so it may not be included in a jar by default. Run it through IDE or set it up in a proper source directory.

Eclipse project: Maven Eclipse Plugin set wrong JRE class path container

I have an Eclipse Mars 2 Java8, Maven 3.5.4 based workspace.
I build the project files with mvn eclipse:clean eclipse:eclipse, and watch the following maven output:
[INFO] Adding default classpath container: org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-**1.7**
The default JRE for the workspace isn't Java 7, it is Java 8, like you can see looking at the following Eclipse config file:
<workspace>\.metadata\.plugins\org.eclipse.core.runtime\.settings\org.eclipse.jdt.launching.prefs.
that contains the following data:
org.eclipse.jdt.launching.PREF_VM_XML=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?>
<vmSettings defaultVM\="57,org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType13,1538040823497*">
<vmType id\="org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType">
<vm id\="1431694854640" name\="jdk1.7.0_40" path\="C\:\\Program Files\\Java\\jdk1.7.0_40"/>
<vm id\="1447417000092" name\="jdk1.6.0_45" path\="C\:\\Program Files\\Java\\jdk1.6.0_45"/>
<vm id\="1538040823497" name\="jdk1.8.0_65" path\="C\:\\Program Files\\Java\\jdk1.8.0_65"/>
</vmType>
</vmSettings>
As you may notice by looking at the above configuration, the default VM has the vm id "1538040823497", which is named jdk1.8.0_65, and resides in C\:\\Program Files\\Java\\jdk1.8.0_65.
This VM is correctly registered as Workspace Default in Eclipse Preferences, Java/Installed JREs, is marked as a "perfect match" within the Execution Environment JAVASE-1.8.
I cannot see anything why Maven Eclipse Plugin considers
org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7 as the correct choice, and not JAVASE-1.8.
I already deleted all JREs and registered them newly.
Now there's exactly one 1.6, 1.7 and 1.8 Environment, each with a "perfect match", and 1.8 is checked as default (as you can see above).
I have to manually correct the project each time I generated it (Edit Build Path, change JRE library from 7 to 8), since all files using Java 8 features like streams or lambda functions signal compiler errors unless I assign the correct JRE manually.
I already tried and manipulate org.eclipse.jdt.launching.prefs, redefine all JREs, pray, curse or ask an Ouija board, to no avail, always Java 7 is assigned by the eclipse plugin (version 2.10, by the way).
Any ideas, anyone?
In your pom file, try to use this:
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
You may also reference this link:
https://dzone.com/articles/maven-eclipse-and-java-9
Or if all fails, try eclipse oxygen, a newer version (not the newest release but much better than Mars IMO) that has Maven Integration plugin pre-installed, all you need is to add a m2e-connector plugin.

Can't execute jar with init.d startscript

I followed this Tutorial:
As init.d service
The executable jar has the usual start, stop, restart, and status
commands. It will also set up a PID file in the usual /var/run
directory and logging in the usual /var/log directory by default.
You just need to symlink your jar into /etc/init.d like so
Assuming that you have a Spring Boot application installed in
/var/myapp, to install a Spring Boot application as an init.d service
simply create a symlink:
$ sudo ln -s /var/myapp/myapp.jar /etc/init.d/myapp
Then start the Service with:
/etc/init.d/myapp start
When I do this exactly like it is described there, I get following error in the Ubuntu 14.04 console:
ubuntu#spring:/var/myapp$ /etc/init.d/myapp start
-bash: /etc/init.d/myapp: cannot execute binary file: Exec format error
You can't run a jar this way, since it's just a binary file. You have to run it with the installed java (as it's mentioned in the MrPsion's answer)
java -jar /var/myapp/myapp.jar
But you can't create a symlink to such a command. You can create a bash script, with the command above, make it executable and create a symlink to this script.
Alternatively, in Ubuntu you may use a binfmt-support. Just install it first
sudo apt-get install binfmt-support
Then make your jar executable
chmod a+x myapp.jar
And then you can run it (and use for the symlink) just as:
/var/myapp/myapp.jar
Update:
Since you have a Spring Boot application, check whether your jar is build with the executable property set to true
springBoot {
executable = true
}
This should let you run your jar the way you wanted, whitout make it an executable or require any additional libraries.
One more, according to the comments, the plugin version you're using doesn't support this feature yet. You have to update a plugin version in order to get an executable jar. According to the plugin sources and commit history you need atleast 1.3 version
The answers are incorrect, you can indeed launch a spring boot application jar as a service with init.d. There is even a spring tutorial explaining how to do it, as pointed out by Stanislav: https://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html
The problem was probably in your maven file. I had the same issue and solved it adding the following to my maven file:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.5.7.RELEASE</version>
<configuration>
<executable>true</executable>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Detailed instructions here: https://springjavatricks.blogspot.com/2017/11/installing-spring-boot-services-in.html
You need to "execute" the jar using java
java -jar /var/myapp/myapp.jar
and init scripts are not generally links to executable.
This post will show you how to create an init script for java applications.
Run a Java Application as a Service on Linux

Arquillian test with custom jre (using Maven dependency)

I have a project which use a specific JRE : that contains some additionnal lib and custo java.security entries... and i want to run test in other machine which i don't have access to update JRE with my specific configuration.
What I want to do :
get JRE distribution and put it in target folder : using Maven dependency
with Maven plugin : update this JRE with my specific configuration
set $JAVA_HOME with my custom JRE in target using arquillian.xml configuration file
It is possible to do that with Arquillian ?
Have you any other suggestion ?
Thank you !
For the first both steps you can use the Maven dependency plugin.
For the integration test you can use the failsafe plugin, there is a parameter called jvm. There is no need to override the jvm with the arquillian.xml.
Option to specify the jvm (or path to the java executable) to use with the forking options. For the default, the jvm will be a new instance of the same VM as the one used to run Maven. JVM settings are not inherited from MAVEN_OPTS.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<jvm>path to jvm or java executable</jvm>
</configuration>
</plugin>

Find Java options used by Maven

How can I find which Java options (Xmx, Xms, Xss, etc) are being used by Maven?
I've found out that a way to set them is via the environment MAVEN_OPTS. Now I want a way to be assured it's getting the right settings.
EDIT: I believe it´s different to this question as I don´t want to see the value of an environment variable. I rather want to see which settings are actually being used by Maven, whether it comes from a env var, settings.xml or other means.
EDIT2: I'm also interested in other ways of setting Java options for a Maven build
You can set Java options for Maven in different points and level (globally or via plugins configuration):
Plugin configuration: just for Compilation
Using the Maven Compiler Plugin configuration for compiling application code and test code, you can set the required Xmx, Xms, Xss options via the compileArgs configuration entry, available for both compile and testCompile goals. An official example is available here and on other SO answers like this one.
An example is also shown below on the third point.
Plugin configuration: just for Tests execution
Using the Maven Surefire Plugin configuration for tests executions, you can set the required Java options to be used at runtime via the argLine configuration entry of the test goal. An official example is available here.
An example is also shown below on the third point.
Plugin configuration: via Properties (and profiles)
You can combine the two options above (in case of common Java options) as a property value to pass to both compileArgs and argLine configuration entry or have different properties per configuration (according to your needs).
<property>
<jvm.options>-Xmx256M</jvm.options>
</property>
[...]
<build>
[...]
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<compilerArgs>
<arg>${jvm.options}</arg>
</compilerArgs>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<argLine>${jvm.options}</argLine>
</configuration>
</plugin>
</plugins>
[...]
</build>
[...]
Using properties gives you also an two extra advantages (on top of centralization): you can use profiles then to personalize it based on different desired behaviours (and example in this SO answer) and you can override them via command line as well, like:
mvn clean install -Djvm.options=-Xmx512
Global/Project configuration: Options file
Since Maven 3.3.1, you can specify your options in a .mvn/jvm.config file per project. It's an alternative to MAVEN_OPTS and a more narrowed scope (per project). However, since it sis a new Maven feature, people should be aware of it, otherwise troubleshooting and maintenance may be impacted.
Global/Env configuration: MAVEN_OPTS
Maven well-known environment variable to set global execution options, however applied to all Maven builds sharing that environment (i.e. per logged user).
When running Maven using the -X option (debug enabled), you will have the following output as part of your build:
[DEBUG] properties used {java.vendor=Oracle Corporation, ... , env.MAVEN_OPTS=-Xmx256M, ...
Update
After all, the executed mvn command is an OS script. Having a look at it in Windows, I found the possibility of using the MAVEN_BATCH_ECHO option which, if enabled (value set to on), will echo any command executed by the script and as such also the invocation of the java command, where you can see if your options (the MAVEN_OPTS) are picked up correctly together with the full list of parameters passed to it.
Here is an execution I tested on Windows:
set MAVEN_BATCH_ECHO=on
set MAVEN_OPTS=-Xmx256M
mvn compile > output.txt
NOTE: the output.txt will contain quite a lot of text, providing build output and additional echos executions. As part of it, it provided:
>"path_to_\jdk1.7\bin\java.exe" -Xmx256M -classpath "path_to\apache-maven-3.1.1\bin\..\boot\plexus-classworlds-2.5.1.jar" "-Dclassworlds.conf=path_to\apache-maven-3.1.1\bin\..\bin\m2.conf" "-Dmaven.home=path_to\apache-maven-3.1.1\bin\.." org.codehaus.plexus.classworlds.launcher.Launcher compile
As you can see, the -Xmx256M option was picked up correctly. If the maven script for other OS doesn't provide this option, then you can simply add it to the script (a simple echo before the java execution, showing the command, would also be enough).
You can find the maven script in your maven installation folder, under the bin subfolder.
Update2
Furthermore, since Maven is a Java tool after all and as you can see from its script it invokes the java command, you could see all the available options as suggested in this SO answer by slightly changing the Maven script and use the jinfo command which should really give you the answer according to this other SO answer.
Maybe it helps to start Maven with verbose debug output (-debug, I think?). Otherwise just do a ps aux | grep java and check the arguments of the process (assuming *nix).

Categories

Resources