5

我正在尝试将 Dropwizard 示例中的一些代码从 java 移植到 groovy。

我看到在 java 中,我可以毫无问题地使用以下代码:

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

@Produces(MediaType.APPLICATION_JSON)
public class HelloWorldService{  

}

但是,使用 groovy 编译器( 1.8 和 2.0.6 ),该类无法编译,并且在 MediaType.APPLICATION_JSON 周围出现 noClassFoundException

如果我更改此代码以使用实际的字符串值

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

}

一切正常。

groovy 解析注解的方式和 java 的方式有什么不同吗?

为了完整起见,这是 gradle 项目的一部分,这是我的 build.gradle (该文件位于 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'
}

编译错误是:

原因:java.lang.RuntimeException: java.lang.ClassNotFoundException: com.sun.ws.rs.ext.RuntimeDelegateImpl ... 17 更多原因:java.lang.ClassNotFoundException: com.sun.ws.rs.ext。 RuntimeDelegateImpl 在 org.gradle.api.internal.tasks.compile.TransformingClassLoader.findClass(TransformingClassLoader.java:47)

4

1 回答 1

6

该问题是由 Groovy 编译器的一个不幸限制引起的,即它使用反射来访问编译类路径上的类。这可能反过来触发其他类被加载,这在编译类路径上可能不可用。通常(但不总是)这些是运行时依赖项。

在具体情况下,Groovy 编译器javax.ws.rs.core.MediaType通过反射加载,最终导致com.sun.ws.rs.ext.RuntimeDelegateImpl通过Class.forName不在编译类路径上的(由静态初始化程序触发)加载。解决方案是将该类放在编译类路径上。(从长远来看,解决方案是修复独立的 Groovy 编译器不使用反射,据我所知,这已经在队列中。)如果你的模块的传递依赖不是问题,实现这一点的最简单方法是:

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

我怀疑 Eclipse Groovy 编译器没有这个问题,因为它不使用反射来访问编译类路径。我希望 GMaven 会像 Gradle 一样爆炸,除非它被配置为使用 Eclipse 编译器(Gradle 目前不支持)。

于 2013-01-22T00:23:58.817 回答