web-dev-qa-db-ja.com

Java 9のパッケージが自動モジュールと競合する

Java 9が間近に迫っています。私のプロジェクトの一部をJava 9.に移植するのは良い学習課題だと思いました。 rxjava および rxjavafx の依存関係があります

dependencies {
    compile 'io.reactivex:rxjava:1.2.6'
    compile 'io.reactivex:rxjavafx:1.0.0'
    ...
}

このプロジェクトを名前付きモジュールとして作成したいと思います。これを行うには、module-info.Javaファイルを作成し、rxjavaおよびrxjavafxの要件をここで指定する必要があります。ただし、これらのライブラリにはまだモジュール情報がありません。

これを回避するために、私はそれを読みました 自動モジュールを作成する必要があります 。理解したことから、rxjavaおよびrxjavafx jarの名前を単純な名前に変更し、--module-pathパラメーターにjarをリストする必要があります。次に、module-info.Javarequiresディレクティブをjar名とともに追加します。

module com.foo.bar {
    requires rxjavafx;
    requires rxjava;
}

私はjar名を編集するためにgradleタスクを作成しましたが、ほとんどの場合は機能しているようです。コンパイルする必要のあるすべてのjarを取得し、バージョン情報やスラッシュを含まないように名前を変更します。次に、ファイルは:で区切られた文字列に連結されます。

tasks.withType(JavaCompile) {
    delete { delete '/tmp/gradle' }
    copy {
        from configurations.compile + configurations.testCompile
        into '/tmp/gradle'
        rename '(.*)-[0-9]+\\..*.jar', '$1.jar'
        rename { String fileName -> fileName.replace("-", "") }
    }
    options.compilerArgs += ['--module-path', fileTree(dir: '/tmp/gradle', include: '*.jar').getFiles().join(':')]
}

当然、rxライブラリはパッケージ名の一部を共有します...しかし、これによりコンパイラは次のようなエラーを吐き出します:

error: module  reads package rx.subscriptions from both rxjava and rxjavafx
error: module  reads package rx.schedulers from both rxjava and rxjavafx
error: module  reads package rx.observables from both rxjava and rxjavafx
error: module rxjava reads package rx.subscriptions from both rxjavafx and rxjava
error: module rxjava reads package rx.schedulers from both rxjavafx and rxjava
error: module rxjava reads package rx.observables from both rxjavafx and rxjava
error: module rxjavafx reads package rx.subscriptions from both rxjava and rxjavafx
error: module rxjavafx reads package rx.schedulers from both rxjava and rxjavafx
error: module rxjavafx reads package rx.observables from both rxjava and rxjavafx

この問題を回避する唯一の方法は、rxjavarxjavafxの内容を単一のjarに再パッケージし、それを単一のモジュールとして追加することだと思われます。しかし、これは良い解決策ではないようです...

だから私の質問は:

  • 新しいモジュールシステムを正しく使用していますか?
  • このエラーについて何ができますか?そして
  • これらの依存関係によって更新が妨げられますか、それともrxがライブラリを更新するのを待つ必要がありますか?

注:標準のJava/javacでこれを実行しようとしましたが、同じ問題が発生します。また、ここに私のJava version:

Java version "9-ea"
Java(TM) SE Runtime Environment (build 9-ea+140)
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+140, mixed mode)
27
flakes

新しいモジュールシステムを正しく使用していますか?

はい。表示されているのは意図した動作です。これは、JPMSモジュールでは分割パッケージが許可されていないためです。

「分割パッケージ」という用語に慣れていない場合、本質的には、2つの異なるモジュールからの同じパッケージの2つのメンバーを意味します。

例えば:
com.foo.A(moduleA.jarから)
com.foo.B(moduleB.jarから)

このエラーについて何ができますか?

次の2つのオプションがあります。

  1. (難しい)パッケージの依存関係を「分割しない」。ただし、ライブラリの内部動作に精通していない場合、これは困難または不可能になる可能性があります
  2. (簡単)上記のように2つのjarを単一のjar(したがって単一の自動モジュール)に結合します。私はそれが「良い」解決策ではないことに同意しますが、そもそもパッケージを分割することは一般に良い考えでもありません。

これらの依存関係によって更新が妨げられますか、それともrxがライブラリを更新するのを待つ必要がありますか?

Rxが最終的にlibを更新して、将来のある時点で分割パッケージを持たないことを願っています。それまでは、2つのjarを1つのjarに粉砕することをお勧めします(オプション#2)。

20
Andy Guibert

私は簡単な問題がありました:

error: module flyway.core reads package javax.transaction.xa from both jboss.transaction.api.1.2.spec and Java.sql
error: module slf4j.api reads package javax.transaction.xa from both jboss.transaction.api.1.2.spec and Java.sql
error: module hibernate.core reads package javax.transaction.xa from both jboss.transaction.api.1.2.spec and Java.sql
.../src/main/Java/module-info.Java:1: error: module eu.com.x reads package javax.transaction.xa from both Java.sql and jboss.transaction.api.1.2.spec

プロジェクトの推移的な依存関係(「gradleの依存関係」または「mvnの依存関係:ツリー」が役立つ場合があります)を確認し、次のようなコードで除外することで、分割パッケージのコンパイルの問題を取り除くことができます。

configurations.all {
    exclude group: 'org.jboss.spec.javax.transaction', module: 'jboss-transaction-api_1.2_spec'
}

または

<dependencies>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>5.2.10.Final</version>
      <exclusions>
        <exclusion>
          <groupId>org.jboss.spec.javax.transaction</groupId>
          <artifactId>jboss-transaction-api_1.2_spec</artifactId>
        </exclusion>
      </exclusions> 
    </dependency>
  </dependencies>

私の問題では、jarの再パッケージ化は必要ありませんでした。この問題は、#JDK8では発生していません。おそらく依存関係を除外しても、すべてのプロジェクトで役立つとは限りません。

4

私は、java.transaction.xaがjavaeeとJava.transaction.xaの両方からパッケージを読み込むという同じ問題に直面しています。そして、この行をmodul-info.Javaに追加して修正しました

 opens javax.transaction.xa;

正常に動作しましたが、パッケージjavax.transaction.xaが空であるか存在しないというヒントが表示されました。ただし、ソースコードは正しくコンパイルされます。

1
kamel2005