groovyfx-project / groovyfx

A library for writing JavaFX 8 applications in the Groovy language.
http://groovyfx.org
Apache License 2.0
199 stars 48 forks source link

Grape examples appear to be incomplete #42

Closed kastork closed 7 years ago

kastork commented 8 years ago

When trying to run an example using the suggested @Grab approach. Receive an exception.

e.g. this is the accordion example copied from the demos directory. Then, as suggested in README, add the Grab annotation.

@Grab('org.groovyfx:groovyfx:8.0.0')

import static groovyx.javafx.GroovyFX.start

start {
    stage(title: "GroovyFX Accordion Demo", x: 100, y: 100, visible: true, style: "decorated", primary: true) {
        scene(fill: GROOVYBLUE, width: 400, height: 400) {
            accordion {
                titledPane(id: "t1", text: "Label 1") {
                    content {
                        label(text: "This is Label 1\n\nAnd there were a few empty lines just there!")
                    }
                }
                titledPane(id: "t2", text: "Label 2") {
                    content {
                        label(text: "This is Label 2\n\nAnd there were a few empty lines just there!")
                    }
                }
                titledPane(id: "t3", text: "Label 3") {
                    // this is content
                    label(text: "This is Label 3\n\nAnd there were a few empty lines just there!")
                }
            }
        }
    }
}

Then, using either groovy AccordionDemo.groovy or groovy -cp $JAVA_HOME/jre/lib/ext/jfxrt.jar AccordionDemo.groovy

results in

Caught: java.lang.ExceptionInInitializerError
java.lang.ExceptionInInitializerError
    at com.sun.proxy.$Proxy4.onClassInfo(Unknown Source)
Caused by: java.lang.IllegalStateException: Toolkit not initialized
    at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:273)
    at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:268)
    at com.sun.javafx.application.PlatformImpl.setPlatformUserAgentStylesheet(PlatformImpl.java:550)
    at com.sun.javafx.application.PlatformImpl.setDefaultPlatformUserAgentStylesheet(PlatformImpl.java:512)
    at javafx.scene.control.Control.<clinit>(Control.java:87)
    ... 1 more

The google machine suggests this error can be corrected by instantiating a JFXPanel by hand, but I'm not sure where you would do this. I tried it at the root script level:

   new JFXPanel()
   start {
      ...

and also at the top of the start block with no success.

Also, I've seen people suggest this

@GrabConfig(systemClassLoader=true, initContextClassLoader=true)

Also no change

So it seem like there must be a missing step in those places where you suggest a @Grape invocation to pull in groovyfx.

I'd try it with the 9.0 snapshot, but it doesn't seem to resolve.

grape resolve org.groovyfx groovyfx 8.0.0
/Users/kirk/.groovy/grapes/org.groovyfx/groovyfx/jars/groovyfx-8.0.0.jar
/Users/kirk/.groovy/grapes/org.codehaus.groovy/groovy-all/jars/groovy-all-2.4.6.jar

grape resolve org.groovyfx groovyfx 9.0.0-SNAPSHOT
Error in resolve:
    Error grabbing Grapes -- [unresolved dependency: org.groovyfx#groovyfx;9.0.0-SNAPSHOT: not found]
Perhaps the grape is not installed?
russel commented 8 years ago

I think we need to separate the JDK8 and JDK9 problems into two. Also we need to be sure which Groovy versions are being used. This script with JDK9 119 gives me the java.lang.ExceptionInInitializerError but the stack is totally different. Can I propose we close this issue and start two new ones?

bgoetzmann commented 7 years ago

Same thing for me, with a Groovy script using a same Grab annotation. I'm using Windows 7, and JDK 8 (1.8.0_102). My stacktrace is slightly different:

Caught: java.lang.ExceptionInInitializerError
java.lang.ExceptionInInitializerError
        at java_lang_Class$isAssignableFrom.call(Unknown Source)
        at com.sun.proxy.$Proxy4.onClassInfo(Unknown Source)
Caused by: java.lang.IllegalStateException: Toolkit not initialized
        at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:273)
        at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:268)
        at com.sun.javafx.application.PlatformImpl.setPlatformUserAgentStylesheet(PlatformImpl.java:550)
        at com.sun.javafx.application.PlatformImpl.setDefaultPlatformUserAgentStylesheet(PlatformImpl.java:512)
        at javafx.scene.control.Control.<clinit>(Control.java:87)
        ... 2 more

Bertrand

bgoetzmann commented 7 years ago

If I change @Grab('org.groovyfx:groovyfx:8.0.0') by @Grab('org.codehaus.groovyfx:groovyfx:0.4.0') (strange idea isn't it?), the JavaFX application starts without exception.

Note: I test it with the example code of the GroovyFX project home page. If the app starts well, I have a white background (instead of black), and the window width seems not correct.

russel commented 7 years ago

@bgoetzmann If I change to 0.4.0 I just get a:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
General error during conversion: Error grabbing Grapes -- [unresolved dependency: org.groovyfx#groovyfx;0.4.0: not found]

Sorry the above was an error on my part – phasing error between editor and shell. The actual error I get with JDK8 is:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
General error during semantic analysis: java.lang.NoClassDefFoundError: javafx.stage.Stage

or with JDK9

java.lang.RuntimeException: Could not init groovyx.javafx.SceneGraphBuilder because of an exception in groovyx.javafx.SceneGraphBuilder.registerControls
    at groovy.util.FactoryBuilderSupport.callAutoRegisterMethods(FactoryBuilderSupport.java:214)
    at groovy.util.FactoryBuilderSupport.autoRegisterNodes(FactoryBuilderSupport.java:188)
    at groovy.util.FactoryBuilderSupport.<init>(FactoryBuilderSupport.java:162)
    at groovyx.javafx.SceneGraphBuilder.<init>(SceneGraphBuilder.groovy:91)
    at groovyx.javafx.SceneGraphBuilder.<init>(SceneGraphBuilder.groovy)
    at groovyx.javafx.GroovyFX.start(GroovyFX.java:34)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(javafx.graphics@9-ea/LauncherImpl.java:843)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$11(javafx.graphics@9-ea/PlatformImpl.java:449)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$9(javafx.graphics@9-ea/PlatformImpl.java:418)
    at java.security.AccessController.doPrivileged(java.base@9-ea/Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(javafx.graphics@9-ea/PlatformImpl.java:417)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(javafx.graphics@9-ea/InvokeLaterDispatcher.java:96)
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(javafx.graphics@9-ea/Native Method)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$8(javafx.graphics@9-ea/GtkApplication.java:195)
    at java.lang.Thread.run(java.base@9-ea/Thread.java:843)
Caused by: java.lang.reflect.InvocationTargetException
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@9-ea/Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base@9-ea/NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@9-ea/DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(java.base@9-ea/Method.java:535)
    at groovy.util.FactoryBuilderSupport.callAutoRegisterMethods(FactoryBuilderSupport.java:209)
    ... 14 more
Caused by: java.lang.ExceptionInInitializerError
    at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(java.base@9-ea/Native Method)
    at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(java.base@9-ea/NativeConstructorAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(java.base@9-ea/DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(java.base@9-ea/Constructor.java:455)
    at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
    at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:60)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:235)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:247)
    at groovyx.javafx.SceneGraphBuilder.registerControls(SceneGraphBuilder.groovy:569)
    ... 19 more
Caused by: java.lang.NumberFormatException: For input string: "9-e"
    at jdk.internal.math.FloatingDecimal.readJavaFormatString(java.base@9-ea/FloatingDecimal.java:2054)
    at jdk.internal.math.FloatingDecimal.parseFloat(java.base@9-ea/FloatingDecimal.java:122)
    at java.lang.Float.parseFloat(java.base@9-ea/Float.java:451)
    at java.lang.Float.valueOf(java.base@9-ea/Float.java:415)
    at org.codehaus.groovy.runtime.StringGroovyMethods.toFloat(StringGroovyMethods.java:3450)
    at org.codehaus.groovy.runtime.dgm$1185.invoke(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:274)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
    at groovyx.javafx.JdkUtil.jdkIsBefore8(JdkUtil.groovy:5)
    at groovyx.javafx.JdkUtil$jdkIsBefore8.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
    at groovyx.javafx.factory.TreeItemFactory.<clinit>(TreeItemFactory.groovy:41)
    ... 29 more
russel commented 7 years ago

With 8.0.0 on JDK9 I get:

Caught: java.lang.ExceptionInInitializerError
java.lang.ExceptionInInitializerError
    at java_lang_Class$isAssignableFrom$0.call(Unknown Source)
    at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@9-ea/DelegatingMethodAccessorImpl.java:43)
    at com.sun.proxy.$Proxy6.onClassInfo(Unknown Source)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@9-ea/Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base@9-ea/NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@9-ea/DelegatingMethodAccessorImpl.java:43)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@9-ea/Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base@9-ea/NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@9-ea/DelegatingMethodAccessorImpl.java:43)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@9-ea/Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base@9-ea/NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@9-ea/DelegatingMethodAccessorImpl.java:43)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@9-ea/Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base@9-ea/NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@9-ea/DelegatingMethodAccessorImpl.java:43)
Caused by: java.lang.IllegalStateException: Toolkit not initialized
    at com.sun.javafx.application.PlatformImpl.runLater(javafx.graphics@9-ea/PlatformImpl.java:396)
    at com.sun.javafx.application.PlatformImpl.runLater(javafx.graphics@9-ea/PlatformImpl.java:391)
    at com.sun.javafx.application.PlatformImpl.setPlatformUserAgentStylesheet(javafx.graphics@9-ea/PlatformImpl.java:673)
    at com.sun.javafx.application.PlatformImpl.setDefaultPlatformUserAgentStylesheet(javafx.graphics@9-ea/PlatformImpl.java:635)
    at javafx.scene.control.Control.<clinit>(javafx.controls@9-ea/Control.java:99)
    ... 16 more

and with JDK8 I get:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
General error during semantic analysis: java.lang.NoClassDefFoundError: javafx.stage.Stage
aalmiray commented 7 years ago

Ah lovely. Looks like the specific version of Groovy can't parse the new JDK9 version number. That's the problem @russel encounters when running with JDK9. Now on JDK8 we get a toolkit initialization exception (I can confirm the exception). This may be caused by an early access to a JavaFX class in SGB before the toolkit has been properly initialized.

I can have a loom at this issue tonight at the Luzern Hackergarten,

russel commented 7 years ago

@aalmiray Do you think the parsing is a Groovy or GroovyFX thing?

aalmiray commented 7 years ago

I was too quick to judge on Groovy directly, the problem is in GroovyFX given the stacktrace

at groovyx.javafx.JdkUtil.jdkIsBefore8(JdkUtil.groovy:5)

This means we can fix the problem from our side ;-)

bgoetzmann commented 7 years ago

@russel For the 0.4.0 version test, be careful, the groupId is different! I replaced @Grab('org.groovyfx:groovyfx:8.0.0') by @Grab('org.codehaus.groovyfx:groovyfx:0.4.0').

russel commented 7 years ago

We should publicise the way people can use this artefact prior to it being published formally.

jagedn commented 7 years ago

Hi @kastork

I had the same problem (jdk8, grape and Toolkit not initialized) and I was able to solve it using grape API instead of annotation. I think grape load services from MANIFEST before JafaFX to be ready

https://gist.github.com/jagedn/3ebc5a11f16743c7362b836827ffe3ce

mfreeman-xtivia commented 6 years ago

Related to the comment from @russel --can someone describe how we can make use of this fix today since it does not appear 8.1 has been published yet?

bitsnaps commented 6 years ago

@mfreeman-xtivia based on the example of @jagedn, I believe this has something to do with Grape and they it loads dependencies, the best way for now is to use Gradle, this is what works for me:

apply plugin: 'groovy'
// you shouldn't need to declare javafxHome variable if the java[c] path is ok
//project.ext.set('javafxHome', System.env['JAVAFX_HOME'])
repositories {
    jcenter()
}
dependencies {
    compile 'org.groovyfx:groovyfx:8.0.0'
    //compile files("${javafxHome}/rt/lib/jfxrt.jar")
}
task run(type: JavaExec) {
    main = 'HelloGroovyFX'
    classpath sourceSets.main.runtimeClasspath
}

Using: Gradle 3.5.1 Groovy: 2.4.4 JVM: 1.8.0_101 Win7.

jagedn commented 6 years ago

I "solved" the issue using a launcher who initialized javafx before to run the real script

LaunchFXScript.groovy

import javafx.embed.swing.JFXPanel
new JFXPanel()
File f = new File(args[0])
run(f,args.drop(1)) 

MyFXScript.groovy

@Grab(group='org.groovyfx',module='groovyfx',version='8.0.0',transitive=true, noExceptions=true)
import static groovyx.javafx.GroovyFX.start
start {
    stage(title: 'VisualSheet', height: 600, visible: true) {
        scene(fill: BLACK, width: 800, height: 250) {
            hbox(padding: 60) {
                button( text:'Load')
            }
   }
}

so you can run groovy LaunchFXScript.groovy MyFXScript.groovy

but I know it's a trick