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 more原因:java.lang.ClassNotFoundException:com.sun.ws.rs.ext。 org.gradle.api.internal.tasks.compile.TransformingClassLoader.findClass(TransformingClassLoader.java:47)のRuntimeDelegateImpl

4

1 に答える 1

6

この問題は、Groovyコンパイラの不幸な制限、つまり、リフレクションを使用してコンパイルクラスパス上のクラスにアクセスすることが原因で発生します。これにより、他のクラスがロードされるようにトリガーされる可能性がありますが、コンパイルクラスパスでは使用できない場合があります。通常(常にではありませんが)、これらは実行時の依存関係です。

具体的なケースでは、Groovyコンパイラーはリフレクションを介してロードされjavax.ws.rs.core.MediaType、最終的にはコンパイルクラスパス上にない(静的初期化子によってトリガーされる)を介してロードされます。解決策は、そのクラスをコンパイルクラスパスに配置することです。(長期的には、解決策は、リフレクションを使用しないようにスタンドアロンのGroovyコンパイラーを修正することです。これは、すでにキューにあることがわかっています。)モジュールの一時的な依存関係が問題にならない場合は、これを実現する最も簡単な方法です。は:com.sun.ws.rs.ext.RuntimeDelegateImplClass.forName

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

Eclipse Groovyコンパイラーは、コンパイルクラスパスにアクセスするためにリフレクションを使用しないため、この問題は発生しないと思われます。Eclipseコンパイラー(現在Gradleでサポートされていない)を使用するように構成されていない限り、GMavenはGradleのように爆発すると思います。

于 2013-01-22T00:23:58.817 に答える