Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make Spring use JavaFX Application Thread in initializing Node beans?

I am trying to create a client application using JavaFX as the UI framework, integrated with Spring to leverage modern UI, dependency injection, AOP, and rich REST API. In the init() method of my JavaFX Application, a SpringApplication is created to autowire Node beans needed for the Scene. These Node beans are annotated with @Component annotation, and also with init() method with @PostConstruct annotation to initialize, and design each nodes after construction. Now I realize that most of these init() methods need JavaFX Application Thread. How could I enforce Spring to use JavaFX Application Thread in initializing these nodes? I might need to refactor my codes here.

Sample code

@Configuration
@EnableAsync
@EnableScheduling
@EnableCaching
// Component scanning for JavaFX Nodes
@ComponentScan("path.to.view.nodes")
public class MyConfiguration {

   // bean definitiions here
}

public class MyApplication extends Application {

    private ConfigurableApplicationContext configurableApplicationContext;

    @Autowired
    private RootPane rootPane;

    @Override
    public void init() throws Exception {
        SpringApplication application;
        application = new SpringApplication();
        application.getSources().add(MyConfiguration.class);
        application.setWebEnvironment(false);
        application.setShowBanner(false);
        application.setRegisterShutdownHook(true);
        configurableApplicationContext = application.run();
        ConfigurableListableBeanFactory beanFactory;
        beanFactory = configurableApplicationContext.getBeanFactory();
        beanFactory.registerSingleton(getClass().getSimpleName(), this);
        beanFactory.autowireBean(this);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setScene(new Scene(rootPane));
        primaryStage.centerOnScreen();
        primaryStage.show();
    }

    @Override
    public void stop() throws Exception {
        configurableApplicationContext.close();
    }

    public static void main(String... args) {
        Application.launch(MyApplication.class, args);
    }

}

@Component
public class RootPane extends BorderPane {

    @PostConstruct
    public void init() {
        setRight(new Button("Click me"));
    }

}
like image 501
Warren Nocos Avatar asked Sep 10 '26 06:09

Warren Nocos


1 Answers

Now I realize that most of these init() methods need JavaFX Application Thread.

This assumption is wrong, you can initialize nodes off of the JavaFX application thread.

You cannot modify nodes in an active scene graph off of the JavaFX application thread. But, you only ever have an active scene graph once the Application start() method is called, which doesn't happen until after the init() method is complete. Read the JavaFX Application javadoc for more information.

In an Application init() method, there is no active scene graph and it doesn't matter what you do with nodes on whichever thread, you will not violate any JavaFX threading rules as long as all of the work is done before a scene is attached to the stage provided in the start() method.

The only exception I know to this rule (for JavaFX 8) is WebView, which must be created and accessed solely from the FX thread.

So, I am not answering your original question, but perhaps it does not need to be answered.

like image 116
jewelsea Avatar answered Sep 12 '26 09:09

jewelsea



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!