Impossible de faire fonctionner les dépendances de test Maven avec les modules Java 9 (ni 10)

Edit: J’ai analysé les réponses données. En particulier, j’ai testé l’hypothèse de Till Brychcy, qui semble tenir, mais ouvre d’autres questions. J’ai ajouté cette parsing à la fin de la question, après le grand séparateur suivant: “———– Analyse de la réponse de Till Brychcy ———-”

D’une manière ou d’une autre, il comstack et s’exécute dans IJ, mais mvn clean install ne parvient pas à comstackr le test

Explication des 2 modules, et ce qui échoue

J’ai un projet java 9 maven avec 2 modules: apimod et clientmod . Le module clientmod dépend de apimod (ces modules sont à la fois des modules Maven et des modules Java 9).

En outre, je veux que le module clientmod puisse réutiliser non seulement le code de production d’ apimod , mais également le code de test. C’est un modèle courant, que j’ai utilisé maintes fois avec Java 8. Avec Java 9 (c’est pareil avec Java 10), cela fonctionne également très bien, tant que je ne déclare pas module-info.java (c’est-à-dire, comme je ne cours pas avec le système de module).

Mais dès que je le fais, l’activation de la dépendance de test semble désactiver la dépendance de production: api.Base (une classe src/main du module apimod ) n’est plus visible de client.test.DerivedTest (une classe src/test du module clientmod ). Le test ne comstack plus.

Est-ce un bogue dans Maven ou dans Java 9? C’est avec les versions les plus récentes: Java 9.0.4 (c’est la même chose avec Java 10), Maven 3.5.3, maven-comstackr-plugin 3.7.0

Mon parsing jusqu’à présent

Le code

Le code source est à:

 git clone https://github.com/vandekeiser/wires.git 

J’ai “dichotomisé” le problème avec un test qui a échoué dans une twig:

 git checkout MINIMIZE_ISSUE `mvn clean install` 

-> BUILD FAIL (erreur de compilation dans le test de clientmod )

Dépendance de test Maven

Je veux que le module clientmod puisse réutiliser non seulement le code de production d’ apimod mais également le code de test. Avec Maven, vous le faites comme ça ( clientmod/pom.xml ):

  fr.cla apimod ${project.version} tests test  

Modules Java 9

 module apimod { exports api; } module clientmod { requires apimod; } 

L’échec en essayant d’activer les deux systèmes de module

Avec Java 9, si je déclare à la fois la dépendance test-scoped et les modules Java 9, le test ne se comstack plus (sortie de mvn clean install ):

 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-comstackr-plugin:3.7.0:testComstack (default-testComstack) on project clientmod: Compilation failure [ERROR] /G:/projets/wires/wires/wires/clientmod/src/test/java/client/test/DerivedTest.java:[8,22] cannot access api.Base [ERROR] class file for api.Base not found 

Reproduire le problème avec javac: un bogue dans la correction de module?

C’est comme si l’activation de la dépendance de test ( src/test ) désactivait la dépendance de production ( src/main ). Je sais que dans ce scénario, Maven est censé utiliser l’ --patch-module javac --patch-module . Donc, j’ai reproduit le problème en utilisant simplement javac (en utilisant la sortie de débogage de mvn -X ):

Même compilation, en sautant Maven:

 javac "G:\projets\wires\wires\wires\clientmod\src\test\java\client\test\DerivedTest.java" \ -d "G:\projets\wires\wires\wires\clientmod\target\test-classes" \ -classpath "G:\projets\wires\wires\wires\clientmod\target\test-classes;" \ --module-path "G:\projets\wires\wires\wires\apimod\target\apimod-1.0-SNAPSHOT-tests.jar;G:\projets\wires\wires\wires\clientmod\target\classes;G:\projets\wires\wires\wires\apimod\target\apimod-1.0-SNAPSHOT.jar;" \ -sourcepath "G:\projets\wires\wires\wires\clientmod\src\test\java;" \ --release 9 \ -Xlint:all \ --patch-module clientmod="G:\projets\wires\wires\wires\clientmod\target\classes;G:\projets\wires\wires\wires\clientmod\src\test\java;" 

Même erreur de compilation:

 G:\projets\wires\wires\wires\clientmod\src\test\java\client test\DerivedTest.java:8: error: cannot access Base new Derived().equals(null); ^ class file for api.Base not found 1 error 

J’ai essayé d’utiliser les indicateurs javac censés désactiver le système de modules, mais ils ne semblent pas exister dans ma JVM Windows Oracle 64 bits? (Ordinateur virtuel Java HotSpot (TM) 64 bits (version 9.0.4 + 11, mode mixte):

 javac --illegal-access=warn javac: invalid flag: --permit-illegal-access javac --permit-illegal-access javac: invalid flag: --illegal-access=warn 

L’ajout d’exportations ou de lectures (logiquement inutiles, faites en désespoir de cause) ne change rien non plus:

 --add-reads apimod=ALL-UNNAMED \ --add-reads clientmod=ALL-UNNAMED \ --add-exports apimod/api=ALL-UNNAMED \ --add-exports clientmod/client=ALL-UNNAMED \ 

Sortie de mvn -version:

 Apache Maven 3.5.3 (3383c37e1f9e9b3bc3df5050c29c8aff9f295297; 2018-02-24T20:49:05+01:00) Maven home: G:\software\apache-maven-3.5.3 Java version: 9.0.4, vendor: Oracle Corporation Java home: C:\Program Files\Java\jdk-9.0.4 Default locale: fr_FR, platform encoding: Cp1252 OS name: "windows 7", version: "6.1", arch: "amd64", family: "windows" 

Analyse de la réponse de Till Brychcy

Merci pour votre réponse détaillée, qui consiste essentiellement à dire “Il semble que Maven ne supporte pas encore ce cas d’utilisation” -> Essayons donc de reproduire le problème sans Maven. J’ai créé la twig TRY_ADAPT_khmarbaise-MINIMIZE_ISSUE pour ces essais (désolé pour le nom déroutant de la twig).

  1. Adapter mon ancienne ligne de commande enregistrée par maven, c’est-à-dire:

     javac "G:\projets\wires\wires\wires\clientmod\src\test\java\client\test\DerivedTest.java" -d "G:\projets\wires\wires\wires\clientmod\target\test-classes" -classpath "G:\projets\wires\wires\wires\clientmod\target\test-classes;" --module-path "G:\projets\wires\wires\wires\apimod\target\apimod-1.0-SNAPSHOT-tests.jar;G:\projets\wires\wires\wires\clientmod\target\classes;G:\projets\wires\wires\wires\apimod\target\apimod-1.0-SNAPSHOT.jar;" -sourcepath "G:\projets\wires\wires\wires\clientmod\src\test\java;" --release 9 -Xlint:all --patch-module clientmod="G:\projets\wires\wires\wires\clientmod\target\classes;G:\projets\wires\wires\wires\clientmod\src\test\java;" --add-reads apimod=ALL-UNNAMED --add-reads clientmod=ALL-UNNAMED --add-exports apimod/api=ALL-UNNAMED --add-exports clientmod/client=ALL-UNNAMED --add-modules apimod 
  2. Je supprime G:\projets\wires\wires\wires\apimod\target\apimod-1.0-SNAPSHOT-tests.jar; de --module-path

  3. J’ajoute la même chose à --patch-module clientmod , en me donnant:

     javac "G:\projets\wires\wires\wires\clientmod\src\test\java\client\test\DerivedTest.java" \ -d "G:\projets\wires\wires\wires\clientmod\target\test-classes" \ -classpath "G:\projets\wires\wires\wires\clientmod\target\test-classes;" \ --module-path "G:\projets\wires\wires\wires\clientmod\target\classes;G:\projets\wires\wires\wires\apimod\target\apimod-1.0-SNAPSHOT.jar;" \ -sourcepath "G:\projets\wires\wires\wires\clientmod\src\test\java;" \ --release 9 \ -Xlint:all \ --patch-module clientmod="G:\projets\wires\wires\wires\clientmod\target\classes;G:\projets\wires\wires\wires\clientmod\src\test\java;G:\projets\wires\wires\wires\apimod\target\apimod-1.0-SNAPSHOT-tests.jar;" \ --add-reads apimod=ALL-UNNAMED \ --add-reads clientmod=ALL-UNNAMED \ --add-exports apimod/api=ALL-UNNAMED \ --add-exports clientmod/client=ALL-UNNAMED \ --add-modules apimod 

-> OK, ça se comstack maintenant! Donc, votre hypothèse selon laquelle maven-comstackr-plugin, ou maven, ne supporte pas encore cela semble validée. Mais je pense qu’il est censé être pris en charge dans la version que j’utilise, qui est la dernière. Je me demande par où commencer pour vérifier cela ..

Quoi qu’il en soit, en attendant, j’ai essayé de configurer explicitement le plug-in maven-comstackr-en vain. La structure générale est que j’ai essayé est (maven-comstackr-plugin.version = 3.7.0):

  org.apache.maven.plugins maven-comstackr-plugin ${maven-comstackr-plugin.version}  ${java.version} ${java.version} ${java.version}  [...]    

J’ai essayé le comstackrArgs suivant (les erreurs d’installation propre de mvn dans les commentaires xml):

1:

        --class-path=/G/projets/wires/wires/wires/clientmod/target/test-classes;  --module-path=/G/projets/wires/wires/wires/clientmod/target/classes;/G/projets/wires/wires/wires/apimod/target/apimod-1.0-SNAPSHOT.jar;  --source-path=/G/projets/wires/wires/wires/clientmod/src/test/java; -Xlint:all  --patch-module=clientmod=/G/projets/wires/wires/wires/clientmod/target/classes;/G/projets/wires/wires/wires/clientmod/src/test/java;/G/projets/wires/wires/wires/apimod/target/apimod-1.0-SNAPSHOT-tests.jar;  --add-reads=apimod=ALL-UNNAMED --add-reads=clientmod=ALL-UNNAMED --add-exports=apimod/api=ALL-UNNAMED --add-exports=clientmod/client=ALL-UNNAMED --add-modules=apimod  

2:

         --module-source-path=./*/src/main/java;./*/src/test/java/;  --source-path=/G/projets/wires/wires/wires/apimod/src/main/java;/G/projets/wires/wires/wires/apimod/src/test/java;/G/projets/wires/wires/wires/clientmod/src/test/java;/G/projets/wires/wires/wires/clientmod/src/main/java;  -Xlint:all  --patch-module=clientmod=/G/projets/wires/wires/wires/clientmod/target/classes;/G/projets/wires/wires/wires/clientmod/src/test/java;/G/projets/wires/wires/wires/apimod/target/apimod-1.0-SNAPSHOT.jar;/G/projets/wires/wires/wires/apimod/target/apimod-1.0-SNAPSHOT-tests.jar;  --add-reads=apimod=ALL-UNNAMED --add-reads=clientmod=ALL-UNNAMED --add-exports=apimod/api=ALL-UNNAMED --add-exports=clientmod/client=ALL-UNNAMED --add-modules=apimod  

Il semble que maven ne supporte pas encore ce cas d’utilisation.

Le problème est que apimod-1.0-SNAPSHOT-tests.jar est traité comme un module automatique et que son nom de module automatique (dérivé du nom de fichier) est ” apimod “. Le module actuel apimod dans apimod-1.0-SNAPSHOT.jar (qui cames plus tard sur le modulepath) est ignoré.

Maven devrait détecter que apimod-1.0-SNAPSHOT-tests.jar appartient à apimod et utiliser --patch-module apimod=G:\projets\wires\wires\wires\apimod\target\apimod-1.0-SNAPSHOT-tests.jar place de faire partie de --module-path

Ça fonctionne maintenant! Tout est expliqué ici: https://issues.apache.org/jira/browse/MCOMPILER-348

Le problème était un conflit de noms: changer le nom des modules maven en un nom différent de celui des modules java corrigés, dans la twig de réduction du problème et dans la twig de dev principale.

J’ai toujours un avertissement cependant (voir lien), pour le moment je l’ignore mais il faut y aller.

———– Copie du contenu du lien en cas de disparition de la JIRA ———–

Robert Scholte : À mon avis, apimod-1.0-SNAPSHOT-tests.jar aurait dû figurer sur le chemin de classe et non sur le modulepath. La seule raison pour laquelle je peux penser à son ajout au modulepath est que son nom de module automatique est également apimod. Changer le nom pour quelque chose qui n’entre pas en conflit avec le nom de module automatique corrige le problème (par exemple, info.example.apimod) En général, choisissez un nom de module plus unique, il doit être globalement unique (tout comme les classes du chemin de classe). Ajoutez reverseDNS ou le package partagé. Permalien Editer Supprimer

Moi : Oui, c’est ça, merci beaucoup! Je pensais que c’était un bogue (mais, il y a peut-être encore un bogue plus petit? Je n’ai pas encore jeté un œil dessus, mais il ya toujours un avertissement javac – voir le fin de ce commentaire).

Il a corrigé la twig de dichotomie et la twig principale: -Dans la twig de dichotomie, j’ai ajouté un préfixe aux modules java -Quand je suis revenu à la twig principale, j’ai renommé les modules Maven. sur, et les modules java au package racine partagé, en évitant également la collision de noms

Pour le dire en termes de «casse-tête Java», la leçon à retenir ici est double: -Pour les utilisateurs de l’API (Maven): suivez les conventions de dénomination: je n’aurais pas dû nommer les modules Maven avec un ‘. séparateur. J’aurais évité le conflit de noms sans y penser .. -Pour les concepteurs de l’API: peut-être enregistrer un message significatif si vous pouvez détecter ce conflit, car il est difficile de voir quand il se produit

Enfin, je reçois toujours un avertissement javac. Donc, pour le moment, je dois ignorer un avertissement concernant les exportations.

Je n’ai pas encore enquêté, mais voici:

 [WARNING] COMPILATION WARNING : [INFO] ------------------------------------------------------------- [WARNING] /G:/projets/wires/wires/wires/wires-core/src/test/java/fr/cla/wires/core/MavenVsJavaModulesReproduceTest.java:[9,54] class fr.cla.wires.support.oo.ddd.AbstractValueObjectTest in module is not exported [INFO] 1 warning [INFO] ------------------------------------------------------------- [INFO] ------------------------------------------------------------- [ERROR] COMPILATION ERROR : [INFO] ------------------------------------------------------------- [ERROR] /G:/projets/wires/wires/wires/wires-core/src/test/java/fr/cla/wires/core/MavenVsJavaModulesReproduceTest.java: warnings found and -Werror specified [INFO] 1 error 

Pour la reproduire, utilisez la balise WARN_IF_UNCOMMENT dans la twig principale ( https://github.com/vandekeiser/wires.git ) et supprimez l’exception d’exportation dans: -Xlint: all, -serial, -exports

Je ne peux pas (et ne devrais pas être obligé) d’append des exportations fr.cla.wires.support.oo.ddd; dans module-info.java car cela fait référence à un paquet qui est dans src / test

C’est là pour l’instant