Search code examples
javaintellij-ideajavafxjavafx-2javafx-8

How to generate a jar and native bundle (dmg, exe, etc) from the same code in JavaFX


I have a JavaFX app setup in IntelliJ. This app can run from the command line and as a gui from the jar. In addition to the two modes from the jar, I want to also publish a native bundle (for mac in my case, so dmg). I want to do this by just creating an if statement in main() that takes instructions to start the gui or not. This is my class.

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("dummy.fxml"));
        primaryStage.setTitle("TODO");
        primaryStage.setScene(new Scene(root, 400, 400));
        primaryStage.show();
    }


    public static void main(String[] args) {
        if (args[0].equals("user_interface")) {
            //launch gui version
            launch(args);
        } else {
            //Run command line version of the app
            //TODO
        }
    }
}

I created two build artifacts in my intellij project. One for a jar and one for a javafx application to generate the dmg.

The jar works perfectly. It runs in cli and it starts the javafx app, but I don't know how to pass arguments when creating the native bundle so that I can pass in "user_interface". Does anyone know how to pass args when creating a native bundle artifact?

If there is a better way of doing this? The are only two requirements.

  1. There should be two artifacts. A jar and a dmg.
  2. The jar can run in cli or gui mode.

Solution

  • You could create 2 Main classes:

    • Console App --> hide the UI
    • UI App --> show the UI

    Then you can create 2 artifacts: console artifact, ui artifact. Then use of of your main classes.

    Or you could define "Application Parameters" within the Java FX tab in the JavaFx Application Artifact:JavaFX Application Parameters

    It's a simple properties file with "key=value" or only a "key". One entry per line. Then you could get this parameters in your start method:

        @Override
        public void start(Stage primaryStage) throws Exception {
            Parameters parameters = getParameters();
    
            List<String> unnamed = parameters.getUnnamed();
            for (String s : unnamed) {
                System.out.println(s + " (unnamed)");
                Alert al = new Alert(Alert.AlertType.INFORMATION);
                al.setContentText(s + " (unnamed)");
                al.show();
            }
    
            List<String> raw = parameters.getRaw();
            for (String s : raw) {
                System.out.println(s + " (raw)");
                Alert al = new Alert(Alert.AlertType.INFORMATION);
                al.setContentText(s + " (raw)");
                al.show();
            }
    }