我正在尝试从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 at org.gradle.api.internal.tasks.compile.TransformingClassLoader.findClass(TransformingClassLoader.java:47)
答案 0 :(得分: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目前不支持)。