JavaFX App Walkthrough

JavaFX8/JDK8

JDK 9 and up is where my problems started. By rolling back to JDK 8, I was able to create an application (still using Scene Builder to create the fxml GUI) and deploy it via Java Artifact Build/Deploy (jar deploy.)

The actual code had to be modified a bit. Below is the link to the Github repo:

https://github.com/continuouscoder/JavaFX8PortScanner

Modification of Code

Where I ran into problems with JDK 8 was in the use of concurrency. I couldn’t use the same Runnable syntax as in JDK 11. JavaFX 8 would complain that the Thread created was not a JavaFX Application thread.

In JDK 11 I could write this and JavaFX 11 took it just fine:

The above JDK 11 / JavaFX 11 code allowed me to update the UI on each result in the for loop.

However, it failed in JavaFX 8 when I downgraded. The failures were about this:

%MINIFYHTML5aa717f6b59873089430e661d8b4382e23%
Runnable task = new Runnable() { // Concurrency solution provided by: https://examples.javacodegeeks.com/desktop-java/javafx/javafx-concurrency-example/ @Override public void run() { // Part of the Runnable: // My scanner code gets dropped in the run method of the runnable... scanResultsValues.clear(); for (int i = Integer.parseInt(startingPortValue.getText()); i <= Integer.parseInt(endingPortValue.getText()); i++) { try { Socket socket = new Socket(hostValue.getText(), i); DataOutputStream dout = new DataOutputStream(socket.getOutputStream()); dout.writeUTF("\n\n\n"); dout.flush(); dout.close(); socket.close(); System.out.println("Port " + i + " is open..."); scanResultsValues.appendText("Port open: " + Integer.toString(i )+"\n"); } catch (Exception err) { } } scanResultsValues.appendText("\n## Scan Completed ##"); } }; Thread backgroundThread = new Thread(task); // Concurrency solution: defining a new background thread backgroundThread.setDaemon(true); // Concurrency solution: thread will use a daemon backgroundThread.start(); // Concurrency solution: starting thread
Code language: PHP (php)

The above JDK 11 / JavaFX 11 code allowed me to update the UI on each result in the for loop.

However, it failed in JavaFX 8 when I downgraded. The failures were about this:

https://stackoverflow.com/questions/21083945/how-to-avoid-not-on-fx-application-thread-currentthread-javafx-application-th

Following the solutions around this issue, I converted the looping Code like so:

new Thread(new Runnable() { @Override public void run() { scanResultsValues.clear(); for (int i = Integer.parseInt(startingPortValue.getText()); i <= Integer.parseInt(endingPortValue.getText()); i++) { final String port = Integer.toString(i); try { Socket socket = new Socket(hostValue.getText(), i); DataOutputStream dout = new DataOutputStream(socket.getOutputStream()); dout.writeUTF("\n\n\n"); dout.flush(); dout.close(); socket.close(); System.out.println("Port " + i + " is open..."); Platform.runLater(new Runnable() { @Override public void run() { scanResultsValues.appendText("Port open: " + port +"\n"); } }); } catch (Exception err) { } } scanResultsValues.appendText("\n## Scan Completed ##"); } }).start();
Code language: PHP (php)

Once I call my value in the runLater method I lost my connection to the variable. I would get an error that this variable is in a scope that needs to be declared as final now. The solution is to have the variable defined as final at the top:

final String port = Integer.toString(i);
Code language: JavaScript (javascript)

The key differences above, are that it’s simpler. I have a new Thread that sets up a new Runnable item, which is my for loop. However, at the point of writing out my updated ports found, I put that code in a Platform.runLater method.

That’s it.

Building / Deployment

Once all that’s done, all you do to build or deploy out a Jar, is to setup an artifact like so:

(Using IntelliJ) I go to Project Structure > Artifacts. Here I click the “+” sign and choose “JavaFX Application” > [name of your application].

That will create 4 tabs on the right side of the window: output layout, pre-processing, post-processing and Java FX. Click on the Java FX sub tab.

On this tab we want to point to the class using the Main method, click the folder icon in the field for the “Application Class” field and choose your Main method.

This image has an empty alt attribute; its file name is Screen-Shot-2019-01-14-at-2.56.57-PM.png

Add a title in the Title field. It’s all ready to go now.

Creating a Jar

Now that the Artifact is configured correctly, in IntelliJ we click Build > Build Artifacts and select “Build” from the contextual menu.

A Jar will be created in the /out/artifacts folder of our Project.

If you’re curious about the size of the Jar, in my case it was only 5kb in size! Obviously I have a very slim application, it’s just a port scanner – still that’s pretty damn small!

About Author /

Leave a Comment

Your email address will not be published.

Start typing and press Enter to search