Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Not able to use variables defined in classes within groovy annotations

I am trying to port some code from the Dropwizard examples from java to groovy.

I see that within java, I can use the following code without any issues:

package com.example.helloworld;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;

@Produces(MediaType.APPLICATION_JSON)
public class HelloWorldService{  

}

However, with the groovy compiler ( both 1.8 and 2.0.6 ), the class fails to compile with a noClassFoundException around MediaType.APPLICATION_JSON

If I change this code to use the actual string value

@Produces('application/json')
public class HelloWorldService{  

}

everything works perfectly.

Are there any differences between the way groovy resolves annotations and the way that java does?

For completeness, this is part of a gradle project and here is my build.gradle ( the file goes under src/groovy/com/example/helloworld )

apply plugin: 'groovy'

// Set our project variables
project.ext {
    dropwizardVersion = '0.6.1'
}

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'com.yammer.dropwizard', name: 'dropwizard-core', version: dropwizardVersion
    groovy group: 'org.codehaus.groovy', name: 'groovy-all', version: '1.8.7'
}

The compilation error is:

Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: com.sun.ws.rs.ext.RuntimeDelegateImpl ... 17 more Caused by: java.lang.ClassNotFoundException: com.sun.ws.rs.ext.RuntimeDelegateImpl at org.gradle.api.internal.tasks.compile.TransformingClassLoader.findClass(TransformingClassLoader.java:47)

like image 853
Tomas Lin Avatar asked Jan 21 '13 21:01

Tomas Lin


People also ask

How do I use a variable in Groovy?

Variables in Groovy can be defined in two ways − using the native syntax for the data type or the next is by using the def keyword. For variable definitions it is mandatory to either provide a type name explicitly or to use "def" in replacement. This is required by the Groovy parser.

What are annotations in Groovy?

Advertisements. Annotations are a form of metadata wherein they provide data about a program that is not part of the program itself. Annotations have no direct effect on the operation of the code they annotate.

How do you call a class in Groovy?

In Groovy we can add a method named call to a class and then invoke the method without using the name call . We would simply just type the parentheses and optional arguments on an object instance. Groovy calls this the call operator: () . This can be especially useful in for example a DSL written with Groovy.

What is constructor in Groovy?

Groovy adds the constructor automatically in the generated class. We can use named arguments to create an instance of a POGO, because of the Map argument constructor. This only works if we don't add our own constructor and the properties are not final. Since Groovy 2.5.


1 Answers

The problem is caused by an unfortunate limitation of the Groovy compiler, namely that it uses reflection to access classes on the compile class path. This may in turn trigger other classes to get loaded, which may not be available on the compile class path. Typically (but not always) these are runtime dependencies.

In the concrete case, the Groovy compiler loads javax.ws.rs.core.MediaType via reflection, which ultimately results in com.sun.ws.rs.ext.RuntimeDelegateImpl being loaded via Class.forName (triggered by a static initializer), which isn't on the compile class path. The solution is to put that class on the compile class path. (In the longer run, the solution is to fix the standalone Groovy compiler not to use reflection, and from what I know this is already in the queue.) If your module's transitive dependencies aren't an issue, the simplest way to achieve this is:

dependencies {
    compile "com.sun.jersey:jersey-client:1.15" 
}

I suspect that the Eclipse Groovy compiler doesn't have this problem because it doesn't use reflection to access the compile class path. I'd expect GMaven to blow up like Gradle, unless it is configured to use the Eclipse compiler (which isn't currently supported by Gradle).

like image 74
Peter Niederwieser Avatar answered Oct 22 '22 22:10

Peter Niederwieser