Problems compiling in mixed Java/Groovy environment when Java files contain references to Groovy types

Hi. My apologies if this is one of those recurring questions that has already been answered. I’ve searched and searched and haven’t really found an answer to it though, so I’m hoping to get some help. I’m working in a source tree that has mixed Java/Groovy code. Putting the Java code in src/main/groovy is not an option. This is pretty much how the tree is structured:

top
   src/main/java
      Foo.java
   src/main/groovy
      Bar.groovy

Foo.java contains a field Bar, which is the Groovy type. When I run gradle build, I get a compilation error for the Java file:

.../src/main/java/Foo.java:2: error: cannot find symbol
  private Bar bar;
          ^
  symbol:
 class Bar
  location: class Foo
1 error
:compileJava FAILED

At first I tried a very minimalistic build.gradle file. Something like this:

apply plugin: 'groovy'
version = 1.0
  repositories {
    mavenCentral()
}
  dependencies {
    compile 'org.codehaus.groovy:groovy-all:2.2.0'
    testCompile 'junit:junit:4.11'
}

Then I tried adding the explicit sourceSet:

sourceSets {
    main {
        java {
            srcDirs = [ 'src/main/java' ]
        }
        groovy {
            srcDirs = ['src/main/groovy']
        }
    }
}

But that didn’t work either. The project is imported as a Gradle project in Spring Tool Suite, and it compiles fine there since I’m using the groovy-eclipse plugin for STS. But I can’t get it to compile on the command line for the life of me. Any help is much appreciated! Thanks.

Never mind, I just found this article and it solved my problem: http://forums.gradle.org/gradle/topics/how_to_compile_groovy_sources_mixed_with_java_sources

Hmm. The solution mentioned in the link above worked fine for my “hello world” test project, but when I added it to the larger multi-project build for the real project, I ran into a build error. I added the following to the build.gradle file for the project:

sourceSets.main.java.srcDirs = []
sourceSets.main.groovy.srcDirs = ["src/main/java", "src/main/groovy"]

But now when I compile the project where the mixed Java/Groovy code resides, Gradle fails with:

FAILURE: Build failed with an exception.

  • What went wrong: Execution failed for task ‘:admin:compileGroovy’. > java.lang.ExceptionInInitializerError (no error message)

Running with --debug yields a long stacktrace. It seems like the failure originates here:

21:20:46.995 [ERROR] [org.gradle.BuildExceptionReporter] Caused by: java.lang.ExceptionInInitializerError
21:20:46.995 [ERROR] [org.gradle.BuildExceptionReporter]
at org.gradle.api.internal.tasks.compile.ApiGroovyCompiler.execute(ApiGroovyCompiler.java:119)
21:20:46.995 [ERROR] [org.gradle.BuildExceptionReporter]
at org.gradle.api.internal.tasks.compile.ApiGroovyCompiler.execute(ApiGroovyCompiler.java:40)
21:20:46.995 [ERROR] [org.gradle.BuildExceptionReporter]
at org.gradle.api.internal.tasks.compile.daemon.CompilerDaemonServer.execute(CompilerDaemonServer.java:53)
21:20:46.995 [ERROR] [org.gradle.BuildExceptionReporter]
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
21:20:46.995 [ERROR] [org.gradle.BuildExceptionReporter]
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
21:20:46.995 [ERROR] [org.gradle.BuildExceptionReporter]
at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:355)
21:20:46.995 [ERROR] [org.gradle.BuildExceptionReporter]
at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:64)
21:20:46.996 [ERROR] [org.gradle.BuildExceptionReporter] Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: com.sun.ws.rs.ext.RuntimeDelegateImpl
21:20:46.996 [ERROR] [org.gradle.BuildExceptionReporter]
... 7 more
21:20:46.996 [ERROR] [org.gradle.BuildExceptionReporter] Caused by: java.lang.ClassNotFoundException: com.sun.ws.rs.ext.RuntimeDelegateImpl
21:20:46.996 [ERROR] [org.gradle.BuildExceptionReporter]
at org.gradle.internal.classloader.TransformingClassLoader.findClass(TransformingClassLoader.java:41)
21:20:46.996 [ERROR] [org.gradle.BuildExceptionReporter]
... 7 more

I’m using Gradle 1.12 on MacOS 10.9.2 in case that’s relevant. Worth mentioning is that Spring Tool Suite 3.5.1 using the exact same build.gradle files compiles everything just fine with the groovy-eclipse plugin. Any help with this is much appreciated! Thanks.

I forgot to mention that I’m using java version 1.7.0_51 and Groovy version 2.1.8.

Might be the known Groovy compiler limitation where runtime dependencies are sometimes required on the compile class path. The Groovy Eclipse compiler doesn’t have this limitation.

See http://stackoverflow.com/questions/14447650/not-able-to-use-variables-defined-in-classes-within-groovy-annotations/ for a detailed explanation.

Thanks much! That might very well be the case. I’ll try it out.

Is there an easy way of figuring out which class/annotation the compiler chokes on? I don’t see anything in the stack trace that alludes to it.

I think the best way to find out (if you need to know) is to gradually reduce the set of source files to be compiled.

Bummer. Has someone created a Jira ticket for that? I assume it’s in the Groovy compiler itself? Is there any way of using the groovy-eclipse plugin compiler since it doesn’t have the runtime dependency problem? Would there be any disadvantage to doing that? We took that approach in a previous project with our Maven configuration, and it seemed to work ok. But I haven’t been able to do it with Gradle. The downer is that I’ll have a hard time convincing my team mates of the greatness of Groovy unless I can resolve this. The only annotations my Groovy code has are @Component and @Service from the Spring Framework, and I added that jar to the compile dependencies, but it didn’t make a difference. Thanks.

It’s a long-standing Groovy limitation which was targeted to be fixed in 2.3, but I’m not sure if it happened. There’s definitely a ticket for it in the Groovy issue tracker. Groovy Eclipse compiler isn’t supported by Gradle, so you’d have to integrate it yourself (e.g. using a ‘JavaExec’ task). However, all it should take to solve this problem is to add a compile dependency on ‘jersey-client’, as explained in my Stack Overflow answer.

Ok. Thanks again for the quick replies!