Search code examples
springmavenjavafx

JavaFX 12 maven and Spring


I'm trying to add spring to my pom but I'm wondering if my build will look like this. Could someone help me how can I do this spring integration with java fx?

my pom:

    <properties>
        <java.version>12</java.version>
    </properties>

    <dependencies>
       <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>12.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>12.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

main class:

public class App extends Application {
    private static Scene scene;
    @Override
    public void start(Stage stage) throws IOException {
        scene = new Scene(loadFXML("primary"));
        stage.setScene(scene);
        stage.show();
    }
    static void setRoot(String fxml) throws IOException {
        scene.setRoot(loadFXML(fxml));
    }
    private static Parent loadFXML(String fxml) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource(fxml + ".fxml"));
        return fxmlLoader.load();
    }
    public static void main(String[] args) {
        launch();
    } }

I searched and found nothing about integrating javafx with spring Could someone help me how I can integrate spring?

I tried to use what I used in my swing project but it didn't work out


Solution

  • Your main app has to maintain Spring's application context like this.

    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.support.AbstractApplicationContext;
    
    @Configuration // or @SpringBootApplication if you used spring boot.
    public class App extends Application {
        private static Scene scene;
        private AbstractApplicationContext context;
    
        @Override
        public void init() throws Exception {
            this.context = new AnnotationConfigApplicationContext(App.class);
            super.init();
        }
    
        @Override
        public void start(Stage stage) throws IOException {
            SpringFxmlLoader loader = new SpringFxmlLoader(this.context);
            Parent root = loader.loadFromResource("primary.fxml");
            stage.setScene(new Scene(root));
            stage.show();
        }
    
        public static void main(String[] args) {
            launch();
        }
    }
    

    use SpringFxmlLoader for returning a controller as a spring bean.

    import java.io.IOException;
    import java.io.InputStream;
    import java.net.URL;
    
    import org.springframework.context.ApplicationContext;
    
    import javafx.fxml.FXMLLoader;
    
    public class SpringFxmlLoader extends FXMLLoader {
        private ApplicationContext context;
    
        protected SpringFxmlLoader() {
        }
    
        public SpringFxmlLoader(ApplicationContext context) {
            this.context = context;
            setControllerFactory(context::getBean);     // return a spring bean from spring's application context.
        }
    
        public ApplicationContext getContext() {
            return this.context;
        }
    
        public <T> T loadFromResource(String resource) throws IOException {
            return loadFromResource(resource, null);
        }
    
        public <T> T loadFromResource(String resource, Class<?> root) throws IOException {
            URL resourceURL = context.getResource(resource).getURL();
            setLocation(resourceURL);
            if(root != null) setRoot(root);
            try (InputStream fxml = resourceURL.openStream()) {
                return load(fxml);
            }
        }
    }
    

    Your controller should be looked like this as a spring bean.

    @Controller
    @Scope("prototype")
    public class PrimaryController {
        @FXML private Parent rootView;
        @FXML private TitledPane settingPane;
    
        @Autowired private SomeBean someBean;   // now you can autowire spring beans.
        // braa....
    
    }
    

    Don't forget specify the controller class in your primary.fxml with fx:controller attribute.