1

I am trying to use SpringBoot in javaFX application. I use javafx-weaver-spring-boot-starter, and it works great with java < 9, but there are some problems with java 9+ (modularity). My project structure: enter image description here

AppStarter code:

package test; import javafx.application.Application; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class AppStarter { public static void main(String[] args) { Application.launch(JavaFxApplication.class, args);` } } 

JavaFxApplication Code:

package test; import javafx.application.Application; import javafx.application.Platform; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; import net.rgielen.fxweaver.core.FxWeaver; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.context.ConfigurableApplicationContext; public class JavaFxApplication extends Application { private ConfigurableApplicationContext applicationContext; @Override public void init() { String[] args = getParameters().getRaw().toArray(new String[0]); this.applicationContext = new SpringApplicationBuilder() .sources(AppStarter.class) .run(args); } @Override public void start(Stage stage) { FxWeaver fxWeaver = applicationContext.getBean(FxWeaver.class); Parent root = fxWeaver.loadView(MyController.class); Scene scene = new Scene(root); stage.setScene(scene); stage.show(); } @Override public void stop() { this.applicationContext.close(); Platform.exit(); } } 

MyController code:

package test; import javafx.event.ActionEvent; import net.rgielen.fxweaver.core.FxmlView; import org.springframework.stereotype.Component; @Component @FxmlView("hello-view.fxml") public class MyController { public void onHelloButtonClick(ActionEvent actionEvent) { System.out.println("Hello World"); } } 

modules-info.java:

module test { requires spring.boot.autoconfigure; requires javafx.graphics; requires spring.context; requires net.rgielen.fxweaver.core; requires spring.boot; requires javafx.weaver.spring.boot.starter; requires net.rgielen.fxweaver.spring.boot.autoconfigure; requires net.rgielen.fxweaver.spring; exports test; opens test; } 

pom.xml code:

<?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.6.4</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo2</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo2</name> <description>demo2</description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>net.rgielen</groupId> <artifactId>javafx-weaver-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-controls</artifactId> <version>17-ea+11</version> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-fxml</artifactId> <version>17-ea+11</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>17</source> <target>17</target> </configuration> </plugin> </plugins> </build> </project>1 

When I try to run the application, I get the following exception:

.... Caused by: java.lang.IllegalAccessError: class test.AppStarter$$EnhancerBySpringCGLIB$$e15856c4 (in module test) cannot access class org.springframework.cglib.core.ReflectUtils (in unnamed module @0x4fb0f9) because module test does not read unnamed module @0x4fb0f9 at test/test.AppStarter$$EnhancerBySpringCGLIB$$e15856c4.CGLIB$STATICHOOK1(<generated>) at test/test.AppStarter$$EnhancerBySpringCGLIB$$e15856c4.<clinit>(<generated>) at java.base/java.lang.Class.forName0(Native Method) at java.base/java.lang.Class.forName(Class.java:467) at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:593) at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363) at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:585) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:110) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:108) at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61) ... 21 more ... 

module test does not read unnamed module... how can I fix it?

1

1 Answer 1

1

Spring 5 isn't friendly with the JavaFX Platform Module System

Spring won't really be built for modules until Spring 6/Springboot 3 is released.

Spring Framework 6 is indeed expected to introduce module-info descriptors for all core framework modules, with minimal required dependencies on core Java modules, enabling the JDK's jlink tool to build custom runtime images for Spring setups. There might be constraints with optional third-party libraries and certain configuration strategies, so it is still unclear how popular such explicit module usage will become among Spring users.

For Spring 5-based applications, the framework is not easily compatible with the Java Platform Module System.

So I don't recommend trying to build a modular JavaFX application relying on Spring until:

  1. Spring 6/SpringBoot 3 is released,

    AND

  2. the dependent libraries you use are also made to be easily compatible with the Java module system.

    • For example, when all of your dependencies define a module-info.java.

How to make your project non-modular

However, you can still build a JavaFX 17 application today which relies on Spring 5 by making the JavaFX application non-modular and either providing the JavaFX modules in the base JDK you use or via command-line switches. For more information, see the answer to:

Delete the module-info.java to make the project non-modular. Place only the JavaFX modules on the module path and add them by VM arguments, --module-path and --add-modules. See the openjfx.io for getting started documentation for more information on the settings.

For distribution of your non-modular application, see either:

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.