I am trying to develop an Application, which should be able to run in CLI-Only Environments as well as on GUI Enabled mode. As some of my work is done by JavaFX Threads, I need to start a JavaFX Main Thread without starting the graphic engine, as this will Crash in CLI-only Environments. How do I do this?
I already wrote a first main class, which will decide with the commandline Args, if the GUI will be started or it should run in CLI Mode. The GUI already works, I just need to figure out how to run the FX Main Thread without GUI in another class.
----- EDIT ------
Further Explanation:
Consider I have 2 UI's, one CLI and one GUI. Code is cut into UI Handling and Operations. The UI Handling does only parsing Commandline Arguments in CLI Mode and Drawing a GUI in GUI Mode. The Button Events will just call Code from within the Operations Classes.
This Question and Answer shows which code is lying beneath in my Operations Segment Code Reference
I am now trying to reuse the Code of the operations within my CLI Interface. The code there is shortened, consider the create Method as more code.
As stated above, CLI Mode is designed for Environments, where Graphic Environment can not be started.
Trying to inherit from Application and implementing the start (Stage s)
Method will result within an
UnsupportedOperationException : unable to open DISPLAY
even if the stage will be ignored within the start method
--- second edit ---
Take the Code described in [here] 1
Consider I want to call createKey(length)
not from an Button, but from an second UI which is Commandline Only
private static void progressBar(Task task) {
task.progressProperty().addListener((new ChangeListener() {
@Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
// Return to line beginning
System.out.print("\r");
int percentage = (int) (100 * task.progressProperty().get());
System.out.format("[%3d%%] %s", percentage, task.messageProperty().get());
if (percentage == 100) {
System.out.println("Finished");
}
}
}));
If I try to run this from a new main class, this will not execute, as the Worker thread waits for an JavaFX Main Thread.
I Need to create a JavaFX Main Thread, which is able to Call progressBar(Task)
but does not try to create a GUI, as this will result in above posted error
---- Edit Three --- I am trying to post this as a minimal example. My Application Startup Looks like this
public static void main(String[] args) {
// If option has been set, start CLI
if (0 < args.length) {
// Start CLI
CLI.Main.execute(args);
} else {
// Trying if GUI can be started
try {
GUI.Main.execute();
}
GUI Main Contains a JavaFX GUI and is working fine, as desired. If we are in an Environment which does not Support drawing a GUI, we have to start the program with arguments. This will invoke the CLI
public class CLI extends Application {
public static void execute(String[] args){
launch(args);
}
@Override
public void start(Stage s) {
progressBar(Creator.createKey());
}
private static void progressBar(Task task) {
task.progressProperty().addListener((new ChangeListener() {
@Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
// Return to line beginning
System.out.print("\r");
int percentage = (int) (100 * task.progressProperty().get());
System.out.format("[%3d%%] %s", percentage, task.messageProperty().get());
if (percentage == 100) {
System.out.println("Finished");
}
}
}));
}
The GUI will call the Creator within a Button Event
private void createKeyPressed(ActionEvent event) {
// Make Progressbar visible
pbKeyProgress.visibleProperty().set(true);
Task<Void> task = Creator.createKey();
pbKeyProgress.progressProperty().bind(task.progressProperty());
lblKeyProgress.textProperty().bind(task.messageProperty());
}
Consider the Creator.createKey() as
public static Task<Void> createKey() {
Task<Void> task;
task = new Task<Void>() {
final int totalSteps = ... ;
@Override
public Void call() throws Exception {
updateProgress(0, totalSteps);
updateMessage("Start");
doStuff();
updateProgress(1, totalSteps);
updateMessage("First");
doStuff();
updateProgress(2, totalSteps);
updateMessage("Second");
// and so on
return null;
}
};
new Thread(task)
.start();
return task ;
}
Within the GUI, the whole code is working as desired. Now I try to make everything working in a non graphic Environment but by using the same Java Version with installed JavaFX. The Creator.createKey should be callable and executable. If I try to execute the CLI on a Machine which supports GUIs, the Commandline Output is as desired and gets updated, the threads are working. If I try it without the JavaFX Extension within the CLI Main Class, the Threads in Creator will not execute, because there is no JavaFX Main Thread. If I try to execute the solution posted above in an Environment which does not allow to draw a GUI, I get an UnsupportedOperationException : Unable to open Display