JavaFx in headless mode

2019-01-18 14:27发布

问题:

Is it possible to run JavaFx in headless mode(in Java 7)? It is being used to generate images on the server but is asking for an X-Server. Does there exist something like java.awt.headless in JavaFx ?(I can't use Xvfb )

回答1:

Here is how I solved this problem for server-side image geneartion on Ubuntu linux environment with jetty application server. It uses xvfb but only as a "library" - without any additional special actions on server:

apt-get install xvfb

// then on application server start:

export DISPLAY=":99"

start-stop-daemon --start --background --user jetty --exec "/usr/bin/sudo" -- -u jetty /usr/bin/Xvfb :99 -screen 0 1024x768x24

You can see the details of my server-side image generation solution in this SO question.



回答2:

Answer by Shreyas Dave didn't work for me anymore. Though I don't know why, here is what I did:

public static void main(String[] args) {
    // to avoid
    // [JRSAppKitAWT markAppIsDaemon]: Process manager already initialized: can't fully enable headless mode.
    System.setProperty("javafx.macosx.embedded", "true");
    java.awt.Toolkit.getDefaultToolkit();
    // end
    launch(args);
}

This was also pointed out here: JavaFX screencapture headless exception on OSX



回答3:

This is a kind of problem which I encountered while capturing images in Mac OS.

I have solved this issue by using

static {

        System.setProperty("java.awt.headless", "false");
}

See for reference : Headless environment error in java.awt.Robot class with MAC OS



回答4:

If you have the source code of the JavaFX application you could also try to use TestFX run the application in a headless mode, to control it and to make screenshots. To run your TestFX application in headless mode you have to start it with the following JVM parameters (to enable Monocle):

-Dtestfx.robot=glass -Dglass.platform=Monocle -Dmonocle.platform=Headless -Dprism.order=sw

Moreover you might need to install Monocle first. See Headless testing with JavaFx and TestFx for more information.



回答5:

I have an application that can be used interactively (displaying JavaFx dialogs) but also must be able to run non-interactive on a server without display.
Even though no GUI element is used in non-interactive mode, we got

    Caused by: java.lang.UnsupportedOperationException: Unable to open DISPLAY
    at com.sun.glass.ui.gtk.GtkApplication.<init>(GtkApplication.java:68)

This happens as soon as a class derived from javafx.application.Application is instantiated, which you normally do with your main class.

Here is the way I solved the problem:

  • I created an additional class GuiAppExecution:

    import java.util.List;
    
    import javafx.application.Application;
    import javafx.stage.Stage;
    
    /**
     * JavaFx launch class for {@link AppExecution}.
     */
    public class GuiAppExecution extends Application {
    
      @Override
      public void start(Stage stage) throws Exception {
        List<String> parameters = getParameters().getRaw();
        AppExecution appExecution = new AppExecution();
        appExecution.launch(parameters);
      }
    
      /**
       * Launches the {@link AppExecution} as JavaFx {@link Application}.
       *
       * @param parameters program parameters
       */
      public void launchGui(String[] parameters) {
        launch(parameters);
      }
    }
    
  • In the main class AppExecution I created a method
    public void launch(List<String> parameters) {
    which parses the parameters and launches the application for both interactive and non-interactive execution.

  • The main method looks like this:

    public static void main(String[] parameters) {
      List<String> parameterList = Arrays.asList(parameters);
      if (parameterList.stream().anyMatch(p -> p.equalsIgnoreCase(BATCH_PARAMETER))) {
        AppExecution appExecution = new AppExecution();
        appExecution.launch(parameterList);
      }
      else {
        GuiAppExecution guiAppExecution = new GuiAppExecution();
        guiAppExecution.launchGui(parameters);
      }
    }
    

    with

    private static final String BATCH_PARAMETER = "-batch";
    

    as the program option that request the non-interactive execution.

Since GuiAppExecution (which is derived from javafx.application.Application) is not instantiated for non-interactive execution, the JavaFx environment is not started.



标签: javafx