pmd / pmd-designer

The Rule Designer is a graphical tool that helps PMD users develop their custom rules
BSD 2-Clause "Simplified" License
76 stars 17 forks source link

Support JavaFX as module (e.g. via azul jdk+fx) #71

Open oowekyala opened 1 year ago

oowekyala commented 1 year ago

I have trouble launching the designer both from within an IDE, from the maven exec task, and from the binary distribution. I tried with a JDK 11 and 17 packaged by Amazon Zulu, which comes with JavaFX included, and got various errors. I also tried with a manual install of the JavaFX 17 SDK and with the JAVAFX_HOME env var that is recognized by our launch script and got the same errors.

@adangel can you describe your setup to run the designer with JavaFX 17?

Using pmd-dist-bin

Launches with JDK 11, but I get the following warning:

On JRE 9+, the following VM argument makes the controls smarter:
--add-opens javafx.controls/javafx.scene.control.skin=ALL-UNNAMED

Apparently this check doesn't match. The reported $java_vendor $java_ver is openjdk 110.

With JDK 17 I get the following:

PMD Rule Designer (v 7.0.0-rc1) initializing... 
Exception in Application start method
java.lang.RuntimeException: Exception in Application start method
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:893)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.IllegalAccessError: class net.sourceforge.pmd.util.fxdesigner.util.DesignerUtil (in unnamed module @0x26ea8c2b) cannot access class com.sun.javafx.fxml.builder.ProxyBuilder (in module javafx.fxml) because module javafx.fxml does not export com.sun.javafx.fxml.builder to unnamed module @0x26ea8c2b

When adding --add-opens javafx.fxml/com.sun.javafx.fxml.builder=ALL-UNNAMED explicitly I get

Caused by: javafx.fxml.LoadException: 
file:/home/clem/Documents/PMD/pmd/sandbox/pmd-bin-7.0.0-SNAPSHOT/lib/pmd-ui-7.0.0-rc1.jar!/net/sourceforge/pmd/util/fxdesigner/fxml/editor.fxml:143
file:/home/clem/Documents/PMD/pmd/sandbox/pmd-bin-7.0.0-SNAPSHOT/lib/pmd-ui-7.0.0-rc1.jar!/net/sourceforge/pmd/util/fxdesigner/fxml/designer.fxml:118
...
Caused by: java.lang.RuntimeException: Cannot create instance of net.sourceforge.pmd.util.fxdesigner.util.controls.NodeParentageCrumbBar with given set of properties: [prefHeight, stylesheets, designerRoot, id]
    at javafx.fxml/com.sun.javafx.fxml.builder.ProxyBuilder.build(ProxyBuilder.java:272)
    at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:776)

Using the maven task / IDE

./mvnw -Prunning,with-javafx exec:java

With both JDKs I get the following:

Caused by: javafx.fxml.LoadException: 
/home/clem/Documents/PMD/designer/target/classes/net/sourceforge/pmd/util/fxdesigner/fxml/node-details.fxml:20
/home/clem/Documents/PMD/designer/target/classes/net/sourceforge/pmd/util/fxdesigner/fxml/designer.fxml:108

    at javafx.fxml/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2722)
    at javafx.fxml/javafx.fxml.FXMLLoader$InstanceDeclarationElement.constructValue(FXMLLoader.java:1024)
    at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:759)
    at javafx.fxml/javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2853)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2649)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2563)
    at javafx.fxml/javafx.fxml.FXMLLoader$IncludeElement.constructValue(FXMLLoader.java:1155)
    at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:759)
    at javafx.fxml/javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2853)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2649)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2563)
    at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:2531)
    at net.sourceforge.pmd.util.fxdesigner.Designer.start(Designer.java:107)
    at net.sourceforge.pmd.util.fxdesigner.Designer.start(Designer.java:65)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:839)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:483)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:456)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:455)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:316)
    ... 1 more
Caused by: java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
    at javafx.fxml/javafx.fxml.FXMLLoader$InstanceDeclarationElement.constructValue(FXMLLoader.java:1022)
    ... 21 more
Caused by: java.lang.NullPointerException
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
    at net.sourceforge.pmd.util.fxdesigner.util.DesignerUtil.addCustomStyleSheets(DesignerUtil.java:139)
    at net.sourceforge.pmd.util.fxdesigner.util.controls.ToolbarTitledPane.<init>(ToolbarTitledPane.java:50)
    ... 27 more

This exception also happens when I launch the app from within Intellij using the provided run configurations.

Java 17 warning

I get the following warning on app startup with JDK 17

OpenJDK 64-Bit Server VM warning: Ignoring option --illegal-access=warn; support was removed in 17.0
adangel commented 1 year ago

I was starting it from IntelliJ IDEA with the Run Configuration "Designer (JRE 17)" and the profiles

I see these warnings on startup:

OpenJDK 64-Bit Server VM warning: Ignoring option --illegal-access=warn; support was removed in 17.0
WARNING: Unknown module: javafx.controls specified to --add-opens
WARNING: Unknown module: javafx.controls specified to --add-opens
Juni 10, 2023 12:06:24 PM com.sun.javafx.application.PlatformImpl startup
WARNUNG: Unsupported JavaFX configuration: classes were loaded from 'unnamed module @71250d6a'

Note: I'm using openjdk from adoptium.net.

I just noticed, that the run configuration is only local. But it is essentially the same as "Designer (JRE 11)", but using java17 as JRE, not exposing the env var "JAVAFX_HOME" (that's anyway not used).

adangel commented 1 year ago

Starting the designer from the binary dist, I use

I get just the following warning on startup:

[JavaFX-Launcher] WARN javafx - Unsupported JavaFX configuration: classes were loaded from 'unnamed module @7923f745'

That's essentially the problem, we don't use modules and javafx should be used via modules. I've buried this deep down in my TODO list:


oowekyala commented 1 year ago

Thanks for the update!

I tried your with-javafx17 profile but from the IDE I get java.lang.NoClassDefFoundError: org/apache/commons/lang3/SystemUtils after the javafx warnings you also have. For some reason intellij doesn't add the dependencies correctly from the maven config.

The app starts now with JDK 21 (from openjdk), Oracle's JDK 17.0.7 and Graalvm 22, using JavaFX 17.0.7 via JAVAFX_HOME. I suppose there is something wrong with my Zulu SDK...

That's essentially the problem, we don't use modules and javafx should be used via modules. I've buried this deep down in my TODO list:

That would be nice in the long term. Do you know, whether this can be done without migrating all PMD modules to use java modules too?

adangel commented 1 year ago

I've tested it now:

Which probably means, that this internal class changed in an incompatible way.

adangel commented 9 months ago

With be130917c60b87710949c8d1c8bef0a25ac40450 we use now openjfx 17 by default. However, we don't yet support the azul jdk+fx builds, we probably need to use the module system properly: E.g. it is no problem to use oracle's java 8 build, which also includes javafx, because there is no module system, that disallows access to internal classes. But since java 9, these access restrictions are enforced. When using openjfx via classpath (as we do with JAVAFX_HOME), then there are also no enforced restrictions yet.

However, we don't use javafx correctly:

WARNING: Unsupported JavaFX configuration: classes were loaded from 'unnamed module @b121a86'

I guess, the first step would be, to integrate JavaFX as a module. PMD Designer + PMD would be in an unnamed module. We need then to get rid of any hacks and workarounds (e.g. --add-opens is forbidden). Then it might just work with any Java build, that includes openjfx as a module.