web-dev-qa-db-ja.com

Java 9で実行時にjavax.annotation.Resourceにアクセスする方法

私にはテストがあります:

public class ResourceTest {
    @Test
    public void test() throws ClassNotFoundException {
        Class.forName("javax.annotation.Resource");
    }
}

javax.annotation.Resourceにアクセスしようとします。 Java 8では機能しましたが、Java 9(Oracle JDK 9を使用しています)ではClassNotFoundExceptionで失敗します。ここで説明したように 春:@ResourceインジェクションはJDK9で動作を停止しました 、JDKからのjavax.annotation.Resourceは、Java 9。

私はモジュール記述子を使用してそれにアクセスしようとしています:

module test {
    requires Java.xml.ws.annotation;
    requires junit;
}

ここでは、Java.xml.ws.annotationモジュール(javax.annotation.Resourceを含む)へのアクセスを具体的に要求します。しかし、テストはまだ失敗します。

そのrequires句を削除し、javax.annotations.Resourceを含む依存関係を(ライブラリとして)追加すると、動作します:

    <dependency>
        <groupId>javax.annotation</groupId>
        <artifactId>javax.annotation-api</artifactId>
        <version>1.3.1</version>
    </dependency>

両方を追加すると(pom.xmlrequires Java.xml.ws.annotationのMaven依存関係)、IDEAでのコンパイルが失敗し、次のメッセージが表示されます。

the unnamed module reads package javax.annotation from both Java.xml.ws.annotation and Java.annotation

しかし、Mavenビルドは引き続き成功します!

コマンドラインでJava.xml.ws.annotationモジュールを追加すると、機能します(Mavenの依存関係とwithrequires句なし):

mvn clean test -DargLine="--add-modules Java.xml.ws.annotation"

モジュールの説明に何か問題がありますか?コマンドラインスイッチなしでJDK提供のjavax.annotation.Resourceにアクセスするにはどうすればよいですか?

テストプロジェクトは https://github.com/rpuch/test-resource-jdk9 で入手できます。

20

ここで混乱を解消するために。あなたが質問で述べた作業方法は代替手段であり、すでに見たように組み合わせるべきではありません。

名前のないモジュールは、Java.xml.ws.annotationとJava.annotationの両方からパッケージjavax.annotationを読み取ります


したがって、動作する方法は次のいずれかです。

コンパイラー引数を使用してモジュールを追加できます

<plugin>
    <groupId>org.Apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.7.0</version>
    <configuration>
        <release>9</release>
        <compilerArgs>
            <arg>--add-modules</arg>
            <arg>Java.xml.ws.annotation</arg>
        </compilerArgs>
    </configuration>
</plugin>

[〜#〜] or [〜#〜]

javax.xml.ws.annotationアップグレード可能なモジュール であるため、これを使用して依存関係を利用できます

<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.1</version>
</dependency>

前者はforRemovalとマークされた @ Deprecated モジュールを使用するための単なる代替物であるため、理想的にはこれに固執する好ましいオプションになります。


したがって、必須句だけではモジュールにアクセスするのに十分ではありません...これはすべてのJDK提供モジュール(Java.baseを除く)に当てはまりますか、または非推奨モジュールにのみ当てはまりますか?

いいえ、requiresは宣言の一部にすぎません。 [ライブラリで追加されなかったクラスでimport some.foo.bar;ステートメントを使用した場合、JDK 9より前にこれについて考えてください。必要とマークされたモジュールは、アクセスするためにモジュールパス上になければなりません。


Update-最初のオプションは、JDK/11または上記のJEP Remove the Java EE and CORBA Modules がターゲットになっています。

29
Naman

Gradleビルドの場合、build.gradleに次を追加すると機能します。

compile 'javax.annotation:jsr250-api:1.0'

tasks.withType(AbstractCompile) {
    options.compilerArgs += ["--add-modules", "Java.xml.bind"]
}

tasks.withType(Test) {
    jvmArgs += ["--add-modules", "Java.xml.bind"]
}
2
Pratik Patil