I am parsing strings representing German-style numbers (i.e., decimal comma and optional full stop for grouping thousands), e.g., "2.804,13"; this is just done using a DecimalFormat based on my desired Locale:
package loc_test;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Locale;
public class ParseNumbers {
static final DecimalFormat df = (DecimalFormat) NumberFormat.getNumberInstance(Locale.GERMANY);
public static void main(String[] args) throws Exception {
for (String s : new String[] { "2.815,53", "2815,53" }) {
System.out.println(String.format("%s \t-> %s", s, df.parse(s)));
}
}
}
This gives the desired output, e.g., when compiled and run from the command line:
2.815,53 -> 2815.53
2815,53 -> 2815.53
However, when I bundle it as a jpackage image (./gradlew jpackageImage using Gradle and the Badass Runtime Plugin) and run the resulting binary, the output seems to indicate that a wrong locale is used:
2.815,53 -> 2.815
2815,53 -> 281553
I have tried out a few things (in vain), and the problem does not seem to be in the code itself:
Added Locale.setDefault(Locale.GERMANY) in the main. Locale.getDefault() will show the German locale, but it has no effect.
Explicitly set -Duser.country=DE and -Duser.language=de via Java command line parameters. System.getProperty(...) shows the expected values, but again, no effect. (Also, from the command line, it also works with these being set to the system defaults.)
Added -Djava.locale.providers=COMPAT,CLDR,SPI to the jpackage Java command line parameters (from this thread). Again, I can verify from the main that the property is set correctly, but it makes no difference. (And seems to have been an issue with earlier Java versions anyway.)
I have seen the problem first using Java 16 with Gradle 7.2; and it has persisted after an update to Java 17 and Gradle 7.3. The problem has occurred both on an English Linux system and a German Windows machine.
Using --info with the jpackageImage command, Gradle shows me which JDK it is using:
Starting process 'command '.../.gradle/jdks/jdk-17+35/bin/jpackage''. Working directory: .../LocTest/app Command: .../.gradle/jdks/jdk-17+35/bin/jpackage --type app-image --input .../LocTest/app/build/install/app/lib --main-jar app.jar --main-class LocTest.App --dest .../LocTest/app/build/jpackage --name app --runtime-image .../LocTest/app/build/jre --java-options -Duser.country=DE --java-options -Duser.language=de --java-options -Djava.locale.providers=COMPAT,CLDR,SPI
When I use that .gradle/jdks/jdk-17+35/bin/java to run the class, i.e., run:
~/.gradle/jdks/jdk-17+35/bin/java -cp app/build/classes/java/main loc_test.App`
With this, the problem does not occur; the numbers are correct.
However, the problem does occur when I use the (supposedly same) JRE bundled with the jpackage image, i.e., I get the wrong numbers using:
./app/build/jpackage/app/lib/runtime/bin/java -cp app/build/classes/java/main/ loc_test.App
Why would the java, when packaged, ignore the locale?
Am I missing something here, or might this be a bug in jpackage or the plugin, or in the Java release itself?
The whole Gradle example project (very small) can be found at Github.
Check what modules are included in your runtime image.
For example when I run java --list-modules on JDK 17 I notice this module:
jdk.localedata
I don't know if it is required for this, but I bet that module isn't being included by jpackage unless it is specifically requested.
Run ./app/build/jpackage/app/lib/runtime/bin/java --list-modules and compare with ~/.gradle/jdks/jdk-17+35/bin/java --list-modules to confirm. Then consider making an image with jlink that includes jdk.localedata if it was missing to test this hypothesis.
Related
I recently ported our Java 11 application to the newly released Java 14 (ZuluJDK). When trying to package our Application with the new JPackage via command line, the only thing that happens, no matter which jpackage-command I'm using, is the following Output:
WARNING: Using incubator modules: jdk.incubator.jpackage
14
An example command (censored some stuff, represented by < > placeholders...):
jpackage --type app-image --verbose --input <path> --main-class <class> --main-jar ./<name>.jar --output runtime-image --name "<name>" --version 2.0.0 --vendor "<company>" --icon <icon-path>.ico
Can somebody help me what could cause this? The Output of the sdk version does not provide much help.
After stripping down argument after argument, I found out that providing the arguments "--version 2.0.0" was causing the issue.
Running
jpackage --help
provided the following information about version, which is described and behaves differently than I expected:
--version
Print the product version to the output stream and exit
So it echoed the JDK Version (14) and, as described, exited. I obviously was looking for --app-version.
Now I get the error that something is wrong with my --output argument, but that is another issue I can hopefully fix on my side. BTW: there is a lot of Logging output once you get it running with the bare minimum arguments required.
Thank you all for your help!
OS: Linux Mint 18.3
The combo I want to run is: Groovy 3.0.+ (app and testing code) & Java 11+ & JavaFX 11+
Having had a little help (see comments here) I can now do this using a gradle.build file (including outputting an executable using the Gradle "installDist" task from the application plugin).
I've also managed to do this from a non-Gradle Groovy-enabled project in IntelliJ, by configuring the classpath and module-path appropriately.
My file javaFXTest.groovy looks like this (NB this is the Groovy script which I get IntelliJ to run):
package core
import javafx.application.Application
import javafx.fxml.FXMLLoader
import javafx.scene.Parent
import javafx.scene.Scene
import javafx.stage.Stage
Application.launch( GrApp, args)
class GrApp extends Application {
#Override
void start(Stage primaryStage) {
Parent root = FXMLLoader.load(getClass().getResource("/dialog1.fxml"))
primaryStage.title = "Hello World"
primaryStage.scene = new Scene(root, 1200, 800)
primaryStage.show()
}
}
I'm just wondering, for the sake of interest, how this is actually done in terms of a CLI groovy command. I thought it might be something like this:
groovy -cp .:/home/mike/.java/JavaFX/javafx-sdk-11.0.2/lib/* --module-path /home/mike/.java/JavaFX/javafx-sdk-11.0.2/lib --add-modules javafx.controls,javafx.fxml core/javaFXTest.groovy
oops:
Caught: java.io.FileNotFoundException: /home/mike/IdeaProjects/JavaFXExp2/AppTest/src/main/groovy/--module-path (/home/mike/IdeaProjects/JavaFXExp2/AppTest/src/main/groovy/--module-path)
... it clearly doesn't recognise --module-path as a configurable option, confirmed by going groovy --help. I searched on this and found nothing. And yet IntelliJ manages to run this script: the --module-path and --add-modules options are added as VM options to the run configuration. Anyone know how this might be done as a CLI command?
On the suggestion by cfrick I found the answer: Intellij does indeed show the whole command in the "Run" view (if you click the '...'):
Turns out this is a giant Java command with all sorts of stuff beyond my understanding, and inclusion of many Groovy .jars for example. I show it in its magnificence for anyone interested: I've split up into lines to show the options a bit more clearly.
/usr/lib/jvm/java-1.11.0-openjdk-amd64/bin/java
-Dgroovy.home=/home/mike/.sdkman/candidates/groovy/3.0.2
-Dgroovy.starter.conf=/home/mike/.sdkman/candidates/groovy/3.0.2/conf/groovy-starter.conf
-javaagent:/home/mike/.local/share/JetBrains/Toolbox/apps/IDEA-C/ch-0/201.6073.9/lib/idea_rt.jar=41350:/home/mike/.local/share/JetBrains/Toolbox/apps/IDEA-C/ch-0/201.6073.9/bin
-Dfile.encoding=UTF-8
-classpath /home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-3.0.2.jar org.codehaus.groovy.tools.GroovyStarter
--conf /home/mike/.sdkman/candidates/groovy/3.0.2/conf/groovy-starter.conf
--main groovy.ui.GroovyMain
--classpath .:/home/mike/IdeaProjects/JavaFXExp2/out/production/AppTest:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-test-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-yaml-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/junit-platform-launcher-1.6.0.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/junit-jupiter-api-5.6.0.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/junit-jupiter-engine-5.6.0.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-templates-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-groovysh-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/jsp-api-2.0.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/ant-1.10.7.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/jackson-dataformat-yaml-2.10.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/javaparser-core-3.15.13.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-json-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/ant-launcher-1.10.7.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-xml-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-testng-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-jmx-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/commons-logging-1.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-dateutil-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/junit-4.13.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/hamcrest-core-1.3.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/xstream-1.4.11.1.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/ivy-2.5.0.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-servlet-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/gpars-1.2.1.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/jcommander-1.72.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/jsr166y-1.7.0.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/ant-antlr-1.10.7.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/multiverse-core-0.7.0.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-jsr223-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-sql-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-groovydoc-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/bsf-2.4.0.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/org.abego.treelayout.core-1.0.1.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/jackson-core-2.10.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/ST4-4.1.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-console-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/jackson-annotations-2.10.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/jansi-1.18.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-datetime-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-astbuilder-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-jaxb-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-ant-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-test-junit5-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-swing-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/qdox-1.12.1.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-cli-picocli-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/javax.servlet-api-3.0.1.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-cli-commons-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-macro-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-nio-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/junit-platform-engine-1.6.0.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/junit-platform-commons-1.6.0.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/testng-6.14.3.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/jackson-databind-2.10.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/ant-junit-1.10.7.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/opentest4j-1.2.0.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-bsf-3.0.2.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/commons-cli-1.4.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/snakeyaml-1.24.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/jline-2.14.6.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/groovy-docgenerator-3.0.2.jar:/home/mike/.java/JavaFX/javafx-sdk-11.0.2/lib/src.zip:/home/mike/.java/JavaFX/javafx-sdk-11.0.2/lib/javafx-swt.jar:/home/mike/.java/JavaFX/javafx-sdk-11.0.2/lib/javafx.web.jar:/home/mike/.java/JavaFX/javafx-sdk-11.0.2/lib/javafx.base.jar:/home/mike/.java/JavaFX/javafx-sdk-11.0.2/lib/javafx.fxml.jar:/home/mike/.java/JavaFX/javafx-sdk-11.0.2/lib/javafx.media.jar:/home/mike/.java/JavaFX/javafx-sdk-11.0.2/lib/javafx.swing.jar:/home/mike/.java/JavaFX/javafx-sdk-11.0.2/lib/javafx.controls.jar:/home/mike/.java/JavaFX/javafx-sdk-11.0.2/lib/javafx.graphics.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/extras-jaxb/jaxb-api-2.3.0.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/extras-jaxb/activation-1.1.1.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/extras-jaxb/jaxb-core-2.3.0.1.jar:/home/mike/.sdkman/candidates/groovy/3.0.2/lib/extras-jaxb/jaxb-impl-2.3.0.1.jar
--encoding=UTF-8
/home/mike/IdeaProjects/JavaFXExp2/AppTest/src/main/groovy/core/javaFXTest.groovy
I hazard a guess that the first -classpath option (with the single dash) is presumably setting that for the "javaagent"... or could it be for the "Groovy starter"...?
This at least solves the conundrum: I had understood that Groovy (even Groovy 3) can't handle Java 9+ modules. So it would make sense that this must be a Java command. Maybe running with a groovy commmand will become possible with Groovy 4, which as I understand it will (hopefully) be able to be able to handle these modules.
I'm trying to run sample JavaFX code (taken from the 5th edition of Java Illuminated) under JavaFX 11 and Java 11, using jGRASP 2 under Windows 10.
I've read through the "Getting Started with JavaFX" guide (https://openjfx.io/openjfx-docs/) extensively, and while I've made some progress, I'm stuck.
I've downloaded the latest ZIP file, unpacked it, and updated the CLASSPATH to include a path to the jar files needed to compile. I can successfully compile the file. However, when I try to run, I get the following error message:
Error: JavaFX runtime components are missing, and are required to run this application
The "Getting Started" guide says that this can be fixed by adding the following options to the runtime call:
--module-path "[path]\lib" --add-modules=javafx.controls,javafx.fxml
I've added the options, but I'm still getting the error message.
Previous StackOverflow articles usually end with the option setting above; alas, I can't figure out what else to do.
As a first time user, I've managed to make it work, but it was not straightforward to me.
I guess there are no many people familiarized with this IDE, so I'm going to post the steps I followed, as a basic tutorial:
Download and install jGRASP version 2.0.5_05 Beta.
Since I have a few JDKs installed, it selected by default JDK 10.0.2, so my first step was to find a way to work with JDK 11. That can be done in Settings -> jGrasp Startup Settings, where I can set the path for my java executable:
Then I restarted jGrasp. You can verify which JDK the IDE is using in Tools -> System Info -> Java Version.
Open HelloFX sample class. I've started with the most basic sample from the OpenJFX docs. The code can be found here.
Build -> compile, as expected, will throw a bunch of errors given that JavaFX is no longer part of the JDK:
Following the OpenJFX docs, we need to download the JavaFX SDK from here, and then add the library to the classpath. Go to Settings -> PATH/CLASSPATH -> Workspace, press New, and add, one by one, the different JavaFX jars from the downloaded SDK/lib folder (at least javafx-base.jar, javafx-graphics.jar and javafx-controls.jar).
Build -> compile should work now.
Next step: Build -> Run. This fails:
----jGRASP exec: java HelloFX
Error: JavaFX runtime components are missing, and are required to run this application
----jGRASP wedge: exit code for process is 1.
----jGRASP: operation complete.
That was expected. According to the docs, we need to set the module-path and add-modules arguments.
First attempt: use Run arguments. After setting:
--module-path /Users/<user>/Downloads/javafx-sdk-11.0.2/lib --add-modules javafx.controls
running again failed with the exact same error message as above, but with one difference in the console log:
----jGRASP exec: java HelloFX --module-path /Users/<user>/Downloads/javafx-sdk-11.0.2/lib --add-modules javafx.controls
What's wrong with that!? Well... if you try that on command line, it will fail as well, because the order of arguments is wrong, the vm arguments should go before the class name.
In conclusion: Run arguments are not VM arguments!
Second attempt: In order to provide the VM arguments, the option I found was to edit Settings -> Compiler settings -> Workspace. By default, it is using jdk (integrated debugger) - generic. You can view it and see that for Run it uses:
java %S -ea %S %<FLAGS2> %<MAIN_CLASS> %<ARGS>
So instead of ARGS we need to find a way to set FLAGS2.
Luckily, next to the Environment tab, there is a Flags/Args tab, and there we can set our vm arguments in FLAGS2:
--module-path /Users/<user>/Downloads/javafx-sdk-11.0.2/lib --add-modules javafx.controls
Apply, close the dialog, and Build -> Run the class, now it will work!
If you see the console log, it contains exactly the command you would use when running on command line:
----jGRASP exec: java --module-path /Users/<user>/Downloads/javafx-sdk-11.0.2/lib --add-modules javafx.controls HelloFX
----jGRASP: operation complete.
I guess the next step will be running a more complex project...
Try simply creating a launcher with only a main Method. It could look something like this:
package application;
import javafx.application.Application;
public class MyAppLauncher {
public static void main(final String[] args) {
Application.launch(MyApp.class, args);
}
}
(you can leave the old main Method unused in your App for the time-being)
This worked for me with JDK 13 & JavaFX 13 & Eclipse 2019-12 under Ubuntu.
(I created the Project using "new/Maven Project/Simple Project" and then just added JavaFX, Logging & other stuff as dependencies in pom.xml, which all landed on the Classpath. Only the JDK was on the Modulepath)
No need to bother about Java Modules.
If that works, you can take time to learn about Java Modularisation another day...
...and remember to vote for this Answer. :-)
I am trying to use a class into a jar using a Nashorn Shebang script with the -cp option (java version "1.8.0_31"). However it does not works. I have perform some test. The following shebang line works:
#!/usr/bin/jjs -scripting
#!/usr/bin/jjs -fv (returns nashorn full version 1.8.0_31-b13)
while the following not:
#!/usr/bin/jjs -cp ./some/lib/lib.jar will return the following error message: "-cp ./some/lib/lib.jar" is not a recognized option.
#!/usr/bin/jjs -scripting -fv will return the error message: "-scripting -fv" is not a recognized option. Use "-h" or "-help" to see a list of all supported options"
All options are theoretically valid. The classpath option should also works as seen on http://www.adam-bien.com/roller/abien/entry/setting_the_classpath_for_nashorn .
More info about nashorn and Shebang: http://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/shell.html#CHDEGHJJ
You ran into an issue which doesn’t have anything to do with Nashorn nor Java. According to this answer the command line argument handling with shebang never was clearly specified and it seems to be a common behavior to treat everything encountered after the first white-space as one single argument.
So one solution would be to write a shell script containing an invocation of jjs with the actual arguments and use that shell script as the interpreter in the shebang line of your Nashorn script.
You can use -Dnashorn.args=-cp in a shebang script. See also https://bugs.openjdk.java.net/browse/JDK-8072138
As it appears you want a way to automatically add JARs to your classpath, I'll highlight a little wrapper I've written which allows you to define Maven co-ordinate dependencies (including transitives) to be added to the classpath of your script, so you can write a script using the "# dep" lines:
#!/usr/bin/env jjs-with-deps
#
# The line below is parsed by the jjs-with-deps script to build a new
# classloader in which the script is really executed, including logback
# and its transitive dependencies.
#
# dep:ch.qos.logback:logback-classic:1.1.2
var log = org.slf4j.LoggerFactory.getLogger("com.example.app.Logger");
log.info("Hello World!");
It does require Maven to be installed somewhere on your PATH, and it does slightly increase startup time (but then again, you're already starting up a JVM ;). First invocation of a given script will be much slower while any dependencies are downloaded to the local M2 repository.
Link is https://github.com/stevestorey/jjs-with-deps
Just today I noticed that I can run java in eclipse with no problems but when I try to run it in the command prompt, I get "cannot find or load main class." The command prompt actually compiles all right, and it outputs a .class file, but then it displays the error msg when trying to execute. (Also, I was able to run java in the cmd a couple weeks ago.)
/* work area for practice
*
*/
package Scrap;
public class experimentational {
public static void main (String [] args) {
System.out.println("welcome to java!");
}
}
Found the answer: (i'm using different code but it is still relevant to this problem)
java -cp . hiThere
output: "Hi there"
I know this is classpath but don't know why it works or what the period does for it. Anyone have an idea?
Use:
javac Scrap/experimentational.java
followed by:
java Scrap.experimentational
try java -cp . [your main class].
Did you install a JDK on the machine outside of Eclipse? If you did, then make sure you set your path variables correctly. Open a command prompt (assuming windows) and type java -version
If the JDK was installed properly and path variables were set properly it should tell you the version of Java that was installed. If it tells you that 'java' is not recognized as a command that you do not have a JDK installed, or it was not installed properly.
The reason your program runs in Eclipse is that Eclipse for Java has its own internal JDK and JVM.
Your other option is to set up your path variables to point to Eclispe's internal JDK.
If you were able to run it from a command prompt previously then most likely your class path was altered. Is this a machine at work? Some companies have SMS tasks that come through periodically and restore default system settings (including path variables) to corporate defaults.
Maybe java and javac isn't in your OS path.
If you are using Microsoft Windows in cmd type path and then enter.
If jdk or jre isn't in path you need to put them to it
I had a similar issue when I copy pasted code into an editor. I removed the package declaration on line 1 and it ran then. So I'd investigate above comments on packages, after trying first to remove the package line.