NoClassDefFoundError on a JavaFX class in compileGroovy task on Java 8

I’m running on a Java 8 release candidate (b129) & I have groovy code that references the built-in class javafx.scene.chart.Chart.

The compileGroovy task chokes on that reference & produces a NoClassDefFoundError (full stack trace is below).

Having found GRADLE-2232 & GRADLE-2317, I decided to try adding jfxrt.jar as a compile dependency:

compile files("${System.properties['java.home']}/lib/ext/jfxrt.jar")

This worked.

Perhaps this is due to jfxrt.jar having moved from lib in Java 7 to lib/ext in Java 8?

Is that the best workaround? I’d rather not have this redundant dependency in my build.

Thanks,

Neil

Gradle -v output is: ------------------------------------------------------------ Gradle 1.11 ------------------------------------------------------------

Build time:

2014-02-11 11:34:39 UTC Build number: none Revision:

a831fa866d46cbee94e61a09af15f9dd95987421

Groovy:

1.8.6 Ant:

Apache Ant™ version 1.9.2 compiled on July 8 2013 Ivy:

2.2.0 JVM:

1.8.0 (Oracle Corporation 25.0-b69) OS:

Windows 7 6.1 x86

Exception is: org.gradle.api.tasks.TaskExecutionException: Execution failed for task ‘:framework:compileGroovy’.

at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)

at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)

at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)

at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)

at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)

at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:42)

at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)

at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)

at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)

at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:289)

at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.executeTask(AbstractTaskPlanExecutor.java:79)

at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:63)

at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:51)

at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:23)

at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:86)

at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:29)

at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:61)

at org.gradle.execution.DefaultBuildExecuter.access$200(DefaultBuildExecuter.java:23)

at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:67)

at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)

at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:61)

at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:54)

at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:166)

at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:113)

at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:81)

at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:64)

at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:33)

at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:24)

at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:35)

at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)

at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:50)

at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:171)

at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:201)

at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:174)

at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:170)

at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:139)

at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)

at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)

at org.gradle.launcher.Main.doAction(Main.java:46)

at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)

at org.gradle.launcher.Main.main(Main.java:37)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:483)

at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:50)

at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:32)

at org.gradle.launcher.GradleMain.main(GradleMain.java:23) Caused by: java.lang.NoClassDefFoundError: javafx/scene/chart/Chart

at java.lang.ClassLoader.defineClass1(Native Method)

at java.lang.ClassLoader.defineClass(ClassLoader.java:760)

at java.lang.ClassLoader.defineClass(ClassLoader.java:642)

at org.gradle.internal.classloader.TransformingClassLoader.findClass(TransformingClassLoader.java:50)

at java.lang.ClassLoader.loadClass(ClassLoader.java:424)

at java.lang.ClassLoader.loadClass(ClassLoader.java:411)

at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:648)

at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:516)

at org.codehaus.groovy.control.ClassNodeResolver.tryAsLoaderClassOrScript(ClassNodeResolver.java:183)

at org.codehaus.groovy.control.ClassNodeResolver.findClassNode(ClassNodeResolver.java:168)

at org.codehaus.groovy.control.ClassNodeResolver.resolveName(ClassNodeResolver.java:124)

at org.codehaus.groovy.control.ResolveVisitor.resolveToOuter(ResolveVisitor.java:616)

at org.codehaus.groovy.control.ResolveVisitor.resolve(ResolveVisitor.java:268)

at org.codehaus.groovy.control.ResolveVisitor.visitClass(ResolveVisitor.java:1140)

at org.codehaus.groovy.control.ResolveVisitor.startResolving(ResolveVisitor.java:141)

at org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit$1.call(JavaAwareCompilationUnit.java:67)

at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1036)

at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:572)

at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:550)

at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:527)

at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:506)

at org.gradle.api.internal.tasks.compile.ApiGroovyCompiler.execute(ApiGroovyCompiler.java:119)

at org.gradle.api.internal.tasks.compile.ApiGroovyCompiler.execute(ApiGroovyCompiler.java:40)

at org.gradle.api.internal.tasks.compile.daemon.CompilerDaemonServer.execute(CompilerDaemonServer.java:53)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:483)

at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)

at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)

at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:355)

at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:64)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

at java.lang.Thread.run(Thread.java:744) Caused by: java.lang.ClassNotFoundException: javafx.scene.chart.Chart

at org.gradle.internal.classloader.TransformingClassLoader.findClass(TransformingClassLoader.java:41)

at java.lang.ClassLoader.loadClass(ClassLoader.java:424)

at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

… 35 more

The issues you link to are unrelated. Have you checked if plain javac puts JavaFX on the class path automatically? I wouldn’t think so.

Yes, in java 8, javafx is on the class path automatically.

In this forum topic: http://gsfn.us/t/43gq4, you said: “Could be the known Groovy compiler problem that the Groovy compiler sometimes needs runtime dependencies on the compile class path.”

That was what gave me the idea above (sorry about the unrelated issues).

Even if javac always has JavaFX on its compile class path, this may not be the case for groovyc. That’s likely the problem.

I renamed the .java test file to .groovy & it compiles & runs fine.

I added @CompileStatic onto the class & it still compiles & runs fine.

This is my declaration of my groovy dependency:

compile group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.2.2'

By the way, thank you for Spock, Peter, it is excellent!

Which Java test file are you suddenly speaking of? I thought that the problem is that Groovy production code that references JavaFX classes doesn’t compile. (After all, the task that failed is ‘:framework:compileGroovy’). You may have to describe the problem in more detail, but I doubt there is a better solution than the one you’ve already found.

When you asked if the java compiler puts jfxrt.jar on the class path, I used the HelloWorld program from http://docs.oracle.com/javafx/2/get_started/hello_world.htm as a simple example to verify that it does.

When you asked if the groovy compiler does the same, I used that same JavaFX program to verify that the current groovy compiler does the same.

When that HelloWorld.groovy program is compiled by compileGroovy with the following build.gradle:

apply plugin: 'groovy'
  repositories {
  mavenCentral()
}
  dependencies {
  compile 'org.codehaus.groovy:groovy:2.2.2'
}

It produces errors like: C:\tmp\src\main\groovy\HelloWorldFX.groovy: 5: unable to resolve class javafx.scene.control.Button

@ line 5, column 1.

import javafx.scene.control.Button;

^

C:\tmp\src\main\groovy\HelloWorldFX.groovy: 2: unable to resolve class javafx.event.ActionEvent

@ line 2, column 1.

import javafx.event.ActionEvent;

^

I hope this bug in the compileGroovy task when run under Java 8 can be fixed at some point.

Until then, we can use our current workaround.

I’ve raised GRADLE-3046 to investigate this further.

Thanks Peter.

Hi all,

This problem affects me as well and therefore I decided to investigate a bit more. This is what I have found:

  1. I have converted the JavaFX HelloWorld example to Groovy (see http://git.io/_D3FQA). 2. Compiling ‘HelloWorldFx.groovy’ “by hand” using ‘groovyc’ works just fine. 3. The resulting class runs with the java interpreter from the command line without problems. The Groovy jar is the only one needed on the classpath. 4. I then copied the same ‘HelloWorldFx.groovy’ class to the simplest Gradle Groovy project I could build. 5. When I run ‘gradle classes’ I get errors in the ‘compileGroovystartup’ task because the JavaFx classes could not be found. The complete build log is available in the Gist.

This is the ‘build.gradle’ file:

apply plugin: ‘groovy’

repositories { mavenCentral() }

dependencies { compile ‘org.codehaus.groovy:groovy:2.3.6’ }

Apparently the issue is with Gradle and not with the Groovy compiler that, by itself, works just fine.

jfxrt.jar is probably not added to the compile classpath when driven by Gradle.

The curious thing is that I cannot find any hint of jfxrt.jar being explicitly added to the compile classpath by Groovy. Therefore it must come from the regular JDK environment.

But if this is true, why Gradle does not see and use it?

Environment:

  • OS: Windows 7 * Gradle: 2.0 & 2.1-rc-2 * Groovy: 2.3.6 * Java: 1.8.0_20

Thanks.