spring-bootmaven-3java-11javafx-11

Problem while running Java FX + Spring booot application with JDK 11+


I've been trying to upgrade an existing JavaFX application written in Java 8 to Java 17. I'm still new to the Java Modular system.

Exceptions thrown

2023-02-23 16:48:59.487  INFO 1536 --- [JavaFX-Launcher] o.s.boot.SpringApplication               : Starting application using Java 11.0.16 on CONRAD-PC with PID 1536 (started by Conrad Bekondo in C:\Users\...\IdeaProjects\...)
2023-02-23 16:48:59.493  INFO 1536 --- [JavaFX-Launcher] o.s.boot.SpringApplication               : No active profile set, falling back to 1 default profile: "default"
2023-02-23 16:49:00.014  INFO 1536 --- [JavaFX-Launcher] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Elasticsearch repositories in DEFAULT mode.
2023-02-23 16:49:00.027  INFO 1536 --- [JavaFX-Launcher] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 7 ms. Found 0 Elasticsearch repository interfaces.
2023-02-23 16:49:00.031  INFO 1536 --- [JavaFX-Launcher] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Reactive Elasticsearch repositories in DEFAULT mode.
2023-02-23 16:49:00.033  INFO 1536 --- [JavaFX-Launcher] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 1 ms. Found 0 Reactive Elasticsearch repository interfaces.
2023-02-23 16:49:00.991  INFO 1536 --- [JavaFX-Launcher] o.s.boot.SpringApplication               : Started application in 2.005 seconds (JVM running for 4.386)
java.lang.NoSuchMethodException: com.sun.javafx.scene.control.skin.Utils.getResource(java.lang.String)
    at java.base/java.lang.Class.getMethod(Class.java:2108)
    at com.sun.javafx.css.StyleManager.getURL(StyleManager.java:873)
    at com.sun.javafx.css.StyleManager.loadStylesheetUnPrivileged(StyleManager.java:1088)
    at com.sun.javafx.css.StyleManager.loadStylesheet(StyleManager.java:943)
    at com.sun.javafx.css.StyleManager._setDefaultUserAgentStylesheet(StyleManager.java:1391)
    at com.sun.javafx.css.StyleManager.setUserAgentStylesheets(StyleManager.java:1242)
    at com.sun.javafx.application.PlatformImpl.lambda$_setPlatformUserAgentStylesheet$20(PlatformImpl.java:843)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl._setPlatformUserAgentStylesheet(PlatformImpl.java:842)
    at com.sun.javafx.application.PlatformImpl.setPlatformUserAgentStylesheet(PlatformImpl.java:693)
    at com.sun.javafx.application.PlatformImpl.setDefaultPlatformUserAgentStylesheet(PlatformImpl.java:657)
    at javafx.scene.control.Control.<clinit>(Control.java:80)
    at ca.qbb.qbox.app.StageInitializer.showWindow(StageInitializer.java:19)
    at ca.qbb.qbox.app.StageInitializer.lambda$onApplicationEvent$0(StageInitializer.java:15)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run$$$capture(InvokeLaterDispatcher.java:96)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
    at java.base/java.lang.Thread.run(Thread.java:834)
java.lang.NoSuchMethodException: com.sun.javafx.scene.control.skin.Utils.getResource(java.lang.String)
    at java.base/java.lang.Class.getMethod(Class.java:2108)
    at com.sun.javafx.css.StyleManager.getURL(StyleManager.java:873)
    at com.sun.javafx.css.StyleManager.loadStylesheetUnPrivileged(StyleManager.java:1093)
    at com.sun.javafx.css.StyleManager.loadStylesheet(StyleManager.java:943)
    at com.sun.javafx.css.StyleManager._setDefaultUserAgentStylesheet(StyleManager.java:1391)
    at com.sun.javafx.css.StyleManager.setUserAgentStylesheets(StyleManager.java:1242)
    at com.sun.javafx.application.PlatformImpl.lambda$_setPlatformUserAgentStylesheet$20(PlatformImpl.java:843)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl._setPlatformUserAgentStylesheet(PlatformImpl.java:842)
    at com.sun.javafx.application.PlatformImpl.setPlatformUserAgentStylesheet(PlatformImpl.java:693)
    at com.sun.javafx.application.PlatformImpl.setDefaultPlatformUserAgentStylesheet(PlatformImpl.java:657)
    at javafx.scene.control.Control.<clinit>(Control.java:80)
    at ca.qbb.qbox.app.StageInitializer.showWindow(StageInitializer.java:19)
    at ca.qbb.qbox.app.StageInitializer.lambda$onApplicationEvent$0(StageInitializer.java:15)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run$$$capture(InvokeLaterDispatcher.java:96)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
    at java.base/java.lang.Thread.run(Thread.java:834)
2023-02-23 16:49:01.070  WARN 1536 --- [lication Thread] javafx.css                               : Resource "com/sun/javafx/scene/control/skin/modena/modena.css" not found.
Disconnected from the target VM, address: '127.0.0.1:50156', transport: 'socket'

POM.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <properties>
        <java.version>11</java.version>
        <javafx.version>11</javafx.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-graphics</artifactId>
            <version>11.0.2</version>
        </dependency>
        <dependency>
            <groupId>net.java.openjfx.backport</groupId>
            <artifactId>openjfx-78-backport</artifactId>
            <version>1.8.0-ea-b96.1</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>${javafx.version}</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-base</artifactId>
            <version>${javafx.version}</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>${javafx.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.2</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Project structure

enter image description here

@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        Application.launch(QBoxApplication.class, args);
    }
}

QBoxApplication.java

public class QBoxApplication extends Application {
    private ConfigurableApplicationContext applicationContext;

    public QBoxApplication() {
    }

    @Override
    public void init() {
        ApplicationContextInitializer<GenericApplicationContext> initializer = applicationContext -> {
            applicationContext.registerBean(Application.class, () -> QBoxApplication.this);
            applicationContext.registerBean(Parameters.class, this::getParameters);
            applicationContext.registerBean(HostServices.class, this::getHostServices);
        };

        applicationContext = new SpringApplicationBuilder()
                .sources(MainApplication.class)
                .initializers(initializer)
                .run(getParameters().getRaw().toArray(new String[0]));
    }

    @Override
    public void stop() {
        applicationContext.close();
        Platform.exit();
    }

    @Override
    public void start(Stage stage) {
        applicationContext.publishEvent(new StageReadyEvent(this, stage));
    }
}

StageInitializer.java

@Component
public class StageInitializer implements ApplicationListener<StageReadyEvent> {
    @Override
    public void onApplicationEvent(StageReadyEvent event) {
        Platform.runLater(() -> showWindow(event));
    }

    private void showWindow(StageReadyEvent event) {
        var parent = new StackPane(new Label("Hello World"));

        var scene = new Scene(parent);
        var stage = event.getStage();

        stage.setScene(scene);
        stage.show();
    }
}

Setup

I followed the steps in these videos

As output however, a blank window opens while the exception above appears instead of a "Hello World" appearing at the center of the window. I'm not sure what I'm getting wrong. I look forward to any pointers


Solution

  • This is very strange. The method exists (at the end) but somehow the reflection/classloader does not see it from Java 11 or 17. Anyway, I took out the backport dependency and it started fine.

    Interesting message in the startup: WARNING: Unsupported JavaFX configuration

    pom

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.7.1</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.car</groupId>
        <artifactId>car</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>car-demo</name>
        <description>Demo project for Spring Boot</description>
        <properties>
            <java.version>19</java.version>
            <javafx.version>19</javafx.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-graphics</artifactId>
                <version>${javafx.version}</version>
            </dependency>
            <dependency>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-controls</artifactId>
                <version>${javafx.version}</version>
            </dependency>
            <dependency>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-base</artifactId>
                <version>${javafx.version}</version>
            </dependency>
            <dependency>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-fxml</artifactId>
                <version>${javafx.version}</version>
            </dependency>
            <dependency>
                <groupId>javax.annotation</groupId>
                <artifactId>javax.annotation-api</artifactId>
                <version>1.3.2</version>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <excludes>
                            <exclude>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                            </exclude>
                        </excludes>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <source>${java.version}</source>
                        <target>${java.version}</target>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    

    logs:

    JRE Oracle Corporation/19.0.2 is not supported, advanced source lookup disabled.
    Feb 26, 2023 12:01:37 PM com.sun.javafx.application.PlatformImpl startup
    WARNING: Unsupported JavaFX configuration: classes were loaded from 'unnamed module @5bdbda00'
    
      .   ____          _            __ _ _
     /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
    ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
     \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
      '  |____| .__|_| |_|_| |_\__, | / / / /
     =========|_|==============|___/=/_/_/_/
     :: Spring Boot ::                (v2.7.1)
    
    2023-02-26 12:01:38.754  INFO 14876 --- [JavaFX-Launcher] o.s.boot.SpringApplication               : Starting application using Java 19.0.2 on NB-3HP3HG3 with PID 14876 (started by WilliamsJ in C:\workspaces\stackoverflow_workspace_\springboot2.7.8)
    2023-02-26 12:01:38.760  INFO 14876 --- [JavaFX-Launcher] o.s.boot.SpringApplication               : No active profile set, falling back to 1 default profile: "default"
    2023-02-26 12:01:39.436  INFO 14876 --- [JavaFX-Launcher] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Elasticsearch repositories in DEFAULT mode.
    2023-02-26 12:01:39.453  INFO 14876 --- [JavaFX-Launcher] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 11 ms. Found 0 Elasticsearch repository interfaces.
    2023-02-26 12:01:39.462  INFO 14876 --- [JavaFX-Launcher] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Reactive Elasticsearch repositories in DEFAULT mode.
    2023-02-26 12:01:39.464  INFO 14876 --- [JavaFX-Launcher] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 2 ms. Found 0 Reactive Elasticsearch repository interfaces.
    2023-02-26 12:01:40.068  INFO 14876 --- [JavaFX-Launcher] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
    2023-02-26 12:01:40.078  INFO 14876 --- [JavaFX-Launcher] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
    2023-02-26 12:01:40.078  INFO 14876 --- [JavaFX-Launcher] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.64]
    2023-02-26 12:01:40.253  INFO 14876 --- [JavaFX-Launcher] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
    2023-02-26 12:01:40.253  INFO 14876 --- [JavaFX-Launcher] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1429 ms
    2023-02-26 12:01:41.198  INFO 14876 --- [JavaFX-Launcher] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
    2023-02-26 12:01:41.209  INFO 14876 --- [JavaFX-Launcher] o.s.boot.SpringApplication               : Started application in 2.882 seconds (JVM running for 4.22)