Update: After spending far too much time trying to get JavaFX 11 working with IntelliJ, as well as jlink, osx and a variety of other blockages… I finally hit a point where I just couldn’t get that executable jar file that I wanted. I was able to get a solution however! By switching back to JDK 8 (and using the integrated JavaFX libraries), I was able to easily get an executable Jar generated. That’s my recommendation at this point. I discuss JDK8 in another article.

Really I had hoped to write an article about how great JavaFX is and how it would be a low cost solution for desktop development, when compared to something like Qt.

Sadly, I have spent the last 20 hours trying to get the most basic function of a desktop/application framework to work: deploying the application.

In the case of desktop development, I should have a variety of choices:

  • A Binary
  • An installer
  • A package
  • An Executable Package (i.e. Jar)

The Good Parts

Before getting to the pain of the problem, I should address the good stuff. I was able to write a simple app, then craft a great UI using Oracle’s Scene Builder.

Scene Builder creates the fxml design for your application. It’s quite amazing! I was done with my code, pulled in the fxml and in 30 min or less I had a fully working application running on my local.

The Bad Parts

I wanted to share this application with others. I wanted either a Jar file, or something similar. I’d settle for almost anything, I just wanted share my application with some developers and get their feedback.

Artifact Attempt – DONESN’T WORK

Googling “how to export JavaFX as a JAR” took me to this wonderful (but silent) YouTube video explain how freaking easy it is:

It’s even in IntelliJ, the same IDE I’m using. How lucky could I get? All I had to do it seems was create a Java Artifact. Artifacts are a configuration concept I’m not familiar with, but this seemed super simple.

WRONG.

The video in question is using a JDK prior to 11, and evidently an older JavaFX as well. Since JDK 11 (what I’m using), the packager used to generate the Artifact has been removed.

Due to removal of the packager, I would get an error about jx:deploy missing required libraries. OK, this should be an easy fix… right? I mean, I just have to bring in the libraries and all will be well?

Some Java developers were actually saying that people in my situation should wait till JDK 12. I thought it insane an option. I mean right there on the openjfx site they claim it’s compatible with JDK 11…. What kind of advise is that….

The official documentation should work, right?

WRONG.

Modules – The JLINK problem

According to the official openjfx documentation one can use a module approach to deployment. It lacks finesse… there’s still a messy way to run the app, but it will pull in the required libraries, bundle them up for distribution.

Great. So the official doc’s mention that I’ll need JDK 11 (got it) and all should be well, we’ll just invoke jlink and….

COMMAND NOT FOUND….

The command jlink was not found on my local system. WTF! I google around and get the common response from stack overflow, “Dude you need the JDK on your path!” But of course my JDK is on my path…

It was such a stupid problem that it stumped me for an hour trying to figure it out… as it turns out there is a KNOWN issue with regards to JDK and some of its binaries (like JLINK) and OSX/Linux. This issue, as it turns out has been around since JDK 9!!!!!!

https://bugs.openjdk.java.net/browse/JDK-8190667

While I could reference the full path to jlink to get it running, I really wanted to fix this, which led me down a rabbit hole of no solution. I tried:

https://stackoverflow.com/questions/46412164/jdk-9-mac-os-jlink

and

https://superuser.com/questions/1255915/java-9-jlink-command-not-found

Neither solution worked and I simply gave up due to time constraints.

Modules – IntelliJ Language Level Restrictions

At this point I felt the sensible thing to do was to follow the official documentation on JavaFX 11 and reference the full path to jlink.

Following the documentation, I created a module-info.java file just above the package in the src folder. IntelliJ complained about this syntax, flagging the module code in red underline.

“This code requires a language level of 9 or above,” it warned. Well that’s new, I never experienced something like that in other languages… so I had to research this… What exactly are language levels… etc.

As it turns out the IDE has a variety of levels we can set for language version access… I don’t get why that’s necessary, isn’t that covered by default when you determine what JDK version you’ll be using?

Regardless, I went into the Project Structure > Project and changed the language levels from 6 to 9. Note: my JDK was set to 11, but the language level defaulted to 6.

Great, so I’m all set, right?

WRONG.

Yet another error….

Modules – Kotlin Complaints in IntelliJ

Now I got a build error about Kotlin.stdlib or something not being defined… I’m not using Kotlin as far as I know…

I spent maybe two hours trying to figure out what was going on. More Googling sent me down various rabbit holes about Kotlin development and then (after an hour or more later) I found this:

https://intellij-support.jetbrains.com/hc/en-us/community/posts/360000891860-Kotlin-Compile-Error

This is a known issue. One solution (simple one) was to simply do a Build > Rebuild, and so I did….

All should be fine now, right?

WRONG.

Modules – JavaFX Generic Error about zip file

Rebuilding resolved the Kotlin error, but now I’m getting a new error… this time it’s so generic I have no idea what’s wrong:

Error:java: /Applications/javafx-sdk-11.0.1/lib/src.zip

To my limited experience here, I thought this was complaining that the src.zip wasn’t found… and it expected it for some reason. But sure enough the file existed.

This issue cost me several more hours, as it really is so generic it took me into too many unrelated issues… go and google that stupid error and see what you find…. Most responses I found assume the problem is a basic “I didn’t download the JavaFX 11 SDK…” or “your VM options are all wrong.”

After hours of this stupidity, I reached out to JetBrains. The first then they did was simply reply, “read this” and they sent me to this stack overflow:

https://stackoverflow.com/a/52470141/104891.

I was pretty pissed that this was a support response. If you check that out, it’s not even the same error and it again assumes I’m not using JavaFX as a downloaded library. I was nice however, and held myself back from an angry response. I told the fellow that I did everything suggested.

The next support reply I got was to basically “download the latest version of IntelliJ….” along with “could you share your code with me?”

I downloaded the latest IntelliJ (2018.3.3) at the time of this writing… and still no help. Same error. I put the project up on Github and shared it with the support person from JetBrains.

I gave him all the steps to reproduce… and that’s when he responded, “Yes, I’m able to reproduce it and I see the problem.”

As it turns out, it isn’t that the src.zip wasn’t found, the error was due to the src.zip file in the lib folder of JavaFX 11 – IntelliJ didn’t expect a non-jar and didn’t know how to deal with it, and just stopped.

The support team opened a ticket on this issue I found… I linked the ticket below for reference, but it got me thinking:

https://youtrack.jetbrains.com/issue/IDEA-205274

I found it odd though that I’m the first to report this… does no one use IntelliJ with JavaFX 11? Is this stack too bleeding edge?

SOLUTION: The support team said I could either delete the src.zip or pull in all the jar’s into the library, omitting src.zip.

Feeling angry, I just opted to delete the *#!#ing file.

Deleting the src.zip should resolve everything now… right?

WRONG.

Modules – Location is Required Error

Now I’m able to use jlink (full path) and can build without error. Things are lookin up.

Following the CLI instructions (now stepping outside the IDE as I’m pissed off with all the IDE issues) from OpenJFX.io I ran this on the command line:

fxportscanner/bin/java -m portscanner/portscanner.Main

which produced a stacktrace. The key to the problem seemed to be:

 Caused by: java.lang.NullPointerException: Location is required.

But location to what? Not even a line number in my code was referenced. This was all Java internal stuff. Googling that I came across dozens of people with this issue, but all their solutions failed for me.

The failure of these solutions was about a myopic focus on thinking this error relates to loading of the fxml file:

https://stackoverflow.com/questions/20507591/javafx-location-is-required-even-though-it-is-in-the-same-package

As it turns out – it has nothing to do with that – at least in my case. But I went down so many rabbit holes, creating sub packages like described, moving the fxml into said packages… referencing it differently… even changing the folder housing the fxml to a “resource” folder via the IDE.

The solution came to me in some answer, after many hours of research. It turns out it is related to the configuration of the project. The VM options were mentioning the path with mods appended, like:

–module-path ${PATH_TO_FX}:mods/production –add-modules=javafx.controls,javafx.fxml

But the compiler output was configured as:

/Users/bwarner/JavaProjects/FXPortScanner/out

Changing the compiler output path from out to mods, resolved this.

So now I’m good to go… and I should be able to now produce a distribution package/installer right?

WRONG.

Modules Problems

Following the official instructions, I am still struggling to get this to work. While the IDE no longer complains, the command line modular arguments (as given in example on the instructions) fail.

 $JAVA_HOME/bin/jlink –module-path $PATH_TO_FX_MODS:mods/production –add-modules=portscanner –output portscannerfx

Although I have a module-info.java config file setup in the project, just above the package (as the official documentation says I should) and that file has the config as such:

module portscanner {
    requires javafx.controls;
    requires javafx.fxml;

    exports portscanner;
}

I’m getting an error:

Error: Module javafx.fxml not found, required by portscanner

NON-Module Approach

The non-module approach, mentioned in the official documents, fails for me as well. Removing the module and reattempting throws dozens of errors on references to packages and symbols relating to JavaFX.

Gradle or MVN?

I resisted going down the Gradle or Maven approach, simply as I didn’t want to add in more problems. I wanted a simple solution for a very simple application.

One solution that is passed around a lot is this one via Medium:

https://medium.com/@adam_carroll/java-packager-with-jdk11-31b3d620f4a8

This is perhaps the way to do it… I dont know… but Gradle is a beast I know little about…. Maybe in time, I’ll try that approach. Right now I feel I’ve been flogged by the JavaFX and JetBrains teams.

You Win – I’ll Downgrade!!

I made a new project, attempting to use JDK 8 and avoid the pitfalls of JDK 11 and JavaFX 11. But I stopped as I realized I really would like to get this to work in Java JDK 11… I really would like to see this work as it’s documented on the official documents.

I’m beaten. I will most likely have to downgrade to make this work – going back to JDK 8 and using embedded JavaFX. I have no idea if new problems and pitfalls await this approach… but it’s probably the best option for JavaFX at this time.

Conclusion

I put in over 20 hours on this, over the weekend. It took me only 45 minutes to write some code and about 20 hours to try and make a deployable form of it.

My source for this sample project is linked via Github below:

https://github.com/continuouscoder/FXPortScanner

While some of my errors were IDE related and one was OSX/Linux related, I’m down to the JDK and JavaFX layer itself as resisting the deployment of the project. Running from within the IDE, all libraries are found and the app runs, in all it’s glory. Trying to make a deployable from the command line results in numerous package not found issues. I honestly give up.

Using an alternative like the Qt C++ framework I was able to write similar code for the same functionality (a desktop app that is a port scanner) and to build it out for different OS’s was a one liner on the command line – no errors in any of it.

I suppose some here will blame OSX, or IntelliJ… and while OSX did have a minor issue with jlink, and while several issues were IntelliJ specific, I still can’t get this basic deployment process to work right.

Even if the example on openjfx works, to run the app you still have to invoke it in a rather convoluted process:

[project name]/bin/java -m [module]/[module name].[file with Main method]

The above is hardly user friendly. Where’s the executable JAR? Where’s the option to make an installer….? With packager no longer in the JDK and now as a standalone library, the whole process seems broken to such a degree I can’t imagine it works at all in JDK 11/JavaFX 11…. or maybe I simply lack the years of experience to resolve this.

Either way I simply am giving it a rest, and I’ll focus on using C++ with the Qt framework for Application Development.

If any readers wants to check out my code and take a crack and generating a deployment fat Jar or package, feel free. It’s up at:

https://github.com/continuouscoder/FXPortScanner

Comments are closed

Archives
Categories