Setup of a plugin to use JavaFX for its GUI (Sw

Hello,


I'm trying to embed the JavaFX WebView inside a toolwindow and have problems instantiating this class.

One approach I got "working" is by embedding the javart.jar file (from JRE7) into the plugin, which I don't think is a good solution and doesn't work with JRE8.

Otherwise I get the "ClassNotFound" Exception from the Stacktrace below.
I know that IntelliJ supports running on JREs without JavaFX, but the plugin is part of a proof-of-concept prototype - updating to Oracle's JRE8 or adding vmoptions would be less of a problem.



Thanks for any help,
Peter




[  21112]  ERROR - llij.ide.plugins.PluginManager - javafx/beans/value/ChangeListener
java.lang.NoClassDefFoundError: javafx/beans/value/ChangeListener
    at plg.actions.quicktesting.registerHtmlToolwindow.actionPerformed(registerHtmlToolwindow.java:42)
    at com.intellij.openapi.actionSystem.ex.ActionUtil.performActionDumbAware(ActionUtil.java:164)
    at com.intellij.openapi.actionSystem.impl.ActionMenuItem$ActionTransmitter$1.run(ActionMenuItem.java:266)
    at com.intellij.openapi.wm.impl.FocusManagerImpl.runOnOwnContext(FocusManagerImpl.java:926)
    at com.intellij.openapi.wm.impl.IdeFocusManagerImpl.runOnOwnContext(IdeFocusManagerImpl.java:124)
    at com.intellij.openapi.actionSystem.impl.ActionMenuItem$ActionTransmitter.actionPerformed(ActionMenuItem.java:236)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
    at com.intellij.openapi.actionSystem.impl.ActionMenuItem.fireActionPerformed(ActionMenuItem.java:105)
    at com.intellij.ui.plaf.beg.BegMenuItemUI.doClick(BegMenuItemUI.java:512)
    at com.intellij.ui.plaf.beg.BegMenuItemUI.access$300(BegMenuItemUI.java:44)
    at com.intellij.ui.plaf.beg.BegMenuItemUI$MyMouseInputHandler.mouseReleased(BegMenuItemUI.java:532)
    at java.awt.Component.processMouseEvent(Component.java:6505)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3320)
    at java.awt.Component.processEvent(Component.java:6270)
    at java.awt.Container.processEvent(Container.java:2229)
    at java.awt.Component.dispatchEventImpl(Component.java:4861)
    at java.awt.Container.dispatchEventImpl(Container.java:2287)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
    at java.awt.Container.dispatchEventImpl(Container.java:2273)
    at java.awt.Window.dispatchEventImpl(Window.java:2719)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:694)
    at java.awt.EventQueue$3.run(EventQueue.java:692)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:708)
    at java.awt.EventQueue$4.run(EventQueue.java:706)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
    at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:697)
    at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:520)
    at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:335)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
Caused by: java.lang.ClassNotFoundException: javafx.beans.value.ChangeListener PluginClassLoader[com.sketchlink.idea, 1.1]
    at com.intellij.ide.plugins.cl.PluginClassLoader.loadClass(PluginClassLoader.java:68)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 45 more
[  21114]  ERROR - llij.ide.plugins.PluginManager - IntelliJ IDEA 13.1.4  Build #IC-135.1230
[  21114]  ERROR - llij.ide.plugins.PluginManager - JDK: 1.7.0_51
[  21114]  ERROR - llij.ide.plugins.PluginManager - VM: Java HotSpot(TM) Client VM
[  21114]  ERROR - llij.ide.plugins.PluginManager - Vendor: Oracle Corporation
[  21114]  ERROR - llij.ide.plugins.PluginManager - OS: Windows 8
[  21114]  ERROR - llij.ide.plugins.PluginManager - Last Action: sketchlink.registerHtmlToolwindow

8 comments
Comment actions Permalink

Any luck getting a javafx gui into intellij? I'm considering it myself.

0
Comment actions Permalink

Sadly, I didn't.

I chose another solution that works for me, because:
- JavaFX needs Oracle JRE 7 or higher, but the OSX version of IntelliJ only uses JRE 6 by default, due to a Runtime Bug
  This is supposed to change with JRE 9  some time in the future, but not forcing a certain JRE won in the end
- Likewise, OpenJDK/OpenJRE (afaik) does not contain JavaFX by default, which is probably the most common runtime for those Linux guys out there
- One "solution"/hack that only worked for the same OS & JRE the plugin was build on (by adding the JavaFX libraries and setting to 'compile'), threw
  hard errors when visiting some sites (e.g. youtube html5 playback). This always killed the JRE, closing the current IntelliJ session.
- I only had limited time to test it and wasn't able to get it working during that period, so I switched to a specialized solution (it was about rendering & editing SVGs)


Some tips as pointers that might help (or might not work at all and point in the wrong direction):
- JavaFX seems to (need?) be set up in some way (preloader) and embedding JavaFX inside a Swing GUI needs some extra steps.
  Oracle Tutorial about JavaFX in Swing (programming): https://docs.oracle.com/javafx/2/swing/swing-fx-interoperability.htm#CHDIEEJE
      -and-
  Oracle Tutorial about Deploying JavaFX in Swing: https://docs.oracle.com/javafx/2/deployment/deploy_swing_apps.htm#A1283379

  I don't understand Ant build scrips well enough to integrate these changes to the automatic generated build scrips for IntelliJ plugins. Same for
setting up "artifacts" in IntelliJ's "Project Settings" Dialog.

- The ClassNotFound Errors (etc) used the linenumber of the import-statement, not of the first time it's used.
- IIRC some JavaFX specific import statements did not produce errors, but I'm not sure which ones or if it was deterministically important

0
Comment actions Permalink

HI Peter,

I using your ugly approach (embeded javafx into plugin).
Sadly I have a problem with Platform.invokeLater (it is never invoked).
Any advice?

Thanks,
Krzysztof

0
Comment actions Permalink

Try ApplicationManager.getInstance().invokeLater() (or runLater or something like that) OR
UIUtils.invokeLaterIfNeeded(), which are afaik the two recommended ways for IntelliJ plugins to run code in the UI thread.

Other than that, is the code around "invokeLater" executed?



Addendum to the Topic:
I've noticed that the normal JRE jars are NOT part of the classpath for normal plugins. Only IntelliJ jars and the tools-library from the original jdk is added.

I'm not sure if its a Java configuration error on my end (if so, why do other standart libraries work?),
but I haven't found a way to add the Java-JRE classpaths to the plugin's classloader (short of dynamically loading jar's, which seems to come with another set of issues).

Adding the jfxrt.jar as a library and setting it to "provided" doesn't work. So the current problem can probaby be rephrased to: "How can I add the JRE classpath (or any classpath) to the plugin without embedding the jar?"

It would be nice if adding <depends optional="false">javafx.qualified.name</depends> into the plugin.xml would be enough for IntelliJ to check the qual. name automatically and load the plugin if available...

0
Comment actions Permalink

Both ApplicationManager.getInstance().invokeLater() and UIUtils.invokeLaterIfNeeded() give me "Not on FX application thread;". The code is invoked in AWT-EventQueue that is Swing UI thread - I need to run my code in JavaFX thread. Any ideas?

JavaFx thread is presnt but somehow don't execute runable I pass to it. I suspect classloaders problem.

0
Comment actions Permalink

Thanks a lot but I choose to implement my UI in swing (and with Intellij themes it looks really good ;) )

0

Please sign in to leave a comment.