web-dev-qa-db-fra.com

Le package entre en conflit avec des modules automatiques dans Java 9

Avec Java 9 à l'horizon proche, je pensais que ce serait un bon exercice d'apprentissage de porter certains de mes projets sur Java 9. Dans l'un de mes projets) J'ai des dépendances pour rxjava et rxjavafx

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

Je veux créer ce projet en tant que module nommé. Pour ce faire, je dois créer un module-info.Java fichier et je dois spécifier les exigences pour rxjava et rxjavafx ici. Cependant, ces bibliothèques n'ont pas encore d'informations sur le module.

Afin de contourner cela, j'ai lu que j'ai besoin de créer des modules automatiques . D'après ce que je comprends, je dois renommer les bocaux rxjava et rxjavafx pour avoir un nom simple, puis répertorier les bocaux dans le --module-path paramètre. J'ajoute ensuite une directive requires dans mon module-info.Java avec les noms des pots.

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

J'ai écrit une tâche gradle pour modifier les noms des pots pour moi, et cela semble fonctionner dans la plupart des cas. Il prend tous les fichiers jar qui doivent être compilés et les renomme pour ne pas inclure les informations de version ou les barres obliques. Les fichiers sont ensuite concaténés dans un : chaîne séparée:

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(':')]
}

Naturellement, les bibliothèques rx partagent certains de leurs noms de packages ... cela provoque cependant le compilateur à cracher des erreurs telles que:

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

Il semble que la seule façon de contourner ce problème serait de reconditionner le contenu de rxjava et rxjavafx dans un seul pot et de l'ajouter en tant que module unique. Cela ne semble cependant pas être une bonne solution ...

Mes questions sont donc:

  • Suis-je en train d'utiliser correctement le nouveau système de modules?
  • Que puis-je faire à propos de cette erreur? et
  • Ces dépendances m'empêchent-elles de mettre à jour, ou dois-je simplement attendre que rx mette à jour leurs bibliothèques?

Remarque: J'ai essayé de l'exécuter avec le standard Java/javac et ils causent les mêmes problèmes. Voici également mon 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

Suis-je en train d'utiliser correctement le nouveau système de modules?

Oui. Ce que vous voyez, c'est le comportement voulu, et c'est parce que les modules JPMS n'autorisent pas les packages fractionnés.

Dans le cas où vous n'êtes pas familier avec le terme "packages séparés", cela signifie essentiellement deux membres du même package provenant de deux modules différents.

Par exemple:
com.foo.A (à partir du moduleA.jar)
com.foo.B (à partir du moduleB.jar)

Que puis-je faire à propos de cette erreur?

Vous avez deux options:

  1. (plus difficile) "dissocier" les dépendances du paquet. Cependant, cela pourrait être difficile ou impossible si vous n'êtes pas familier avec le fonctionnement interne de la bibliothèque
  2. (plus facile) combinez les deux pots en un seul pot (et donc un seul module automatique) comme vous l'avez mentionné ci-dessus. Je suis d'accord que ce n'est pas une "bonne" solution, mais avoir des packages fractionnés en premier lieu n'est généralement pas une bonne idée non plus.

Ces dépendances m'empêchent-elles de mettre à jour, ou dois-je simplement attendre que rx mette à jour leurs bibliothèques?

Avec un peu de chance, rx mettra éventuellement à jour ses bibliothèques pour ne pas avoir de packages séparés à un moment donné dans le futur. Jusque-là, ma recommandation serait de casser les deux pots ensemble dans un seul pot (option n ° 2).

20
Andy Guibert

J'ai eu un problème similaire:

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

Je pourrais me débarrasser du problème de compilation des packages fractionnés en vérifiant les dépendances transitives de mon projet ("dépendances gradle" ou "dépendance mvn: arbre" pourrait être utile) et en excluant par code simmiliar:

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

ou

<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>

Aucun reconditionnement de bocal n'était nécessaire dans mon problème. Ce problème ne s'est pas produit sur # JDK8. L'exclusion probable des dépendances n'aide pas dans tous les projets.

4
Radosław Osiński

j'ai été confronté au même problème avec le package de lecture Java.transaction.xa de javaee et Java.transaction.xa. Et je l'ai corrigé en ajoutant cette ligne à mon modul-info.Java

 opens javax.transaction.xa;

Cela a bien fonctionné mais un indice est apparu indiquant que le package javax.transaction.xa est vide ou n'existe pas. cependant, le code source se compile correctement.

1
kamel2005