web-dev-qa-db-fra.com

Comment fonctionne la résolution du préfixe du plugin Maven? Pourquoi résout-il les "findbugs" mais pas les "jetty"?

Je faisais des tests avec Maven et j'ai réalisé que je pouvais exécuter l'objectif findbugs du plugin Findbugs sans ajouter le plugin au fichier POM. D'un autre côté, lorsque j'ai dû exécuter l'objectif run du plugin Jetty, j'ai été obligé d'ajouter le plugin au fichier POM ou la construction a échoué.

  • Pourquoi Jetty avait besoin d'une configuration dans le POM alors que Findbugs n'en avait pas besoin?
  • Comment Maven sait-il quels Findbugs exécuter (supposons que nous ayons des plugins avec le même nom mais un identifiant de groupe différent)?

Lorsque j'exécute la première commande, la génération réussit sans aucune modification du fichier POM:

mvn findbugs:findbugs
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building module-mytest 1.0
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- findbugs-maven-plugin:3.0.4:findbugs (default-cli) @ module-mytest ---
[INFO] Fork Value is true
     [Java] Warnings generated: 6
[INFO] Done FindBugs Analysis....
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 24.165s
[INFO] Finished at: Sun Oct 23 18:40:26 WEST 2016
[INFO] Final Memory: 21M/111M
[INFO] -----------------------------------------------------------------------

Mais quand je lance la seconde, j'obtiens ceci:

mvn jetty:run
[INFO] Scanning for projects...
Downloading: http://repo.maven.Apache.org/maven2/org/codehaus/mojo/maven-metadata.xml
Downloading: http://repo.maven.Apache.org/maven2/org/Apache/maven/plugins/maven-metadata.xml
Downloaded: http://repo.maven.Apache.org/maven2/org/Apache/maven/plugins/maven-metadata.xml (13 KB at 30.0 KB/sec)
Downloaded: http://repo.maven.Apache.org/maven2/org/codehaus/mojo/maven-metadata.xml (20 KB at 41.0 KB/sec)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.129s
[INFO] Finished at: Sun Oct 23 18:43:27 WEST 2016
[INFO] Final Memory: 12M/104M
[INFO] ------------------------------------------------------------------------
[ERROR] No plugin found for prefix 'jetty' in the current project and in the plugin groups [org.Apache.maven.plugins, org.codehaus.mojo] available from the repositories [local (/home/hp-pc/.m2/repository), central (http://repo.maven.Apache.org/maven2)] -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.Apache.org/confluence/display/MAVEN/NoPluginFoundForPrefixException

Donc, pour passer la build, j'avais besoin d'ajouter ce qui suit au fichier pom:

<plugin>
  <groupId>org.Eclipse.jetty</groupId>
  <artifactId>jetty-maven-plugin</artifactId>
  <version>9.2.11.v20150529</version>
</plugin>
13
Jachk E

Qu'est-ce qu'un préfixe et pourquoi en avons-nous besoin?

Vous venez de rencontrer la Plugin Prefix Resolution de Maven. Il s'agit d'une fonctionnalité qui permet à l'utilisateur d'appeler les objectifs d'un plugin Maven spécifique, en utilisant son préfixe. Lorsque vous invoquez directement un objectif sur la ligne de commande, vous pouvez utiliser la forme complète de:

mvn my.plugin.groupId:foo-maven-plugin:1.0.0:bar

Cela invoquerait l'objectif bar du plugin Foo Maven ayant les coordonnées my.plugin.groupId:foo-maven-plugin:1.0.0 (sous la forme de groupId:artifactId:version). Cela fonctionne bien, mais c'est un peu bavard. Ce serait bien d'invoquer cet objectif de manière plus simple, sans préciser toutes ces coordonnées. Maven rend cela possible en affectant des préfixes aux plugins, afin que vous puissiez vous référer à ce préfixe au lieu des coordonnées entières, avec:

mvn foo:bar
    ^^^ ^^^
     |    |
   prefix |
          |
         goal

Comment ce préfixe est-il déterminé?

Vous pouvez définir un préfixe pour chaque plugin Maven. Cela correspond à un nom simple utilisé pour l'identifier:

Les formats d'ID d'artefact conventionnels à utiliser sont:

  • maven-${prefix}-plugin - pour les plugins officiels maintenus par l'équipe Apache Maven elle-même (vous ne devez pas utiliser ce modèle de nommage pour votre plugin, voir cette note pour plus d'informations)
  • ${prefix}-maven-plugin - pour les plugins d'autres sources

Si l'artefactId de votre plugin correspond à ce modèle, Maven mappera automatiquement votre plugin au préfixe correct dans les métadonnées stockées dans le chemin groupId de votre plugin sur le référentiel.

Autrement dit, si l'ID d'artefact de votre plug-in est nommé foo-maven-plugin, Maven lui attribuera automatiquement un préfixe foo. Si vous ne souhaitez pas cette affectation par défaut, vous pouvez toujours configurer la vôtre à l'aide de maven-plugin-plugin et son paramètre goalPrefix .

Comment Maven mappe-t-il les préfixes aux plugins?

Dans la commande

mvn foo:bar

Maven doit avoir un moyen de déduire que foo signifie en fait my.plugin.groupId:foo-maven-plugin. Dans le settings.xml fichier, vous pouvez ajouter groupes de plugins , sous la forme de:

<pluginGroups>
  <pluginGroup>org.mortbay.jetty</pluginGroup>
</pluginGroups>

Ce que cela signifie, c'est de dire à Maven quel ID de groupe il est censé prendre en compte lorsque vous utilisez un préfixe dans une commande. Par défaut, et en plus des groupes spécifiés dans les paramètres, Maven recherche également les identifiants de groupe org.Apache.maven.plugins et org.codehaus.mojo . Il recherche ceux par défaut après ceux que vous avez configurés dans les paramètres. Par conséquent, avec la configuration ci-dessus et une commande de mvn foo:bar, Maven recherchera un plugin ayant un préfixe foo dans l'ID de groupe org.mortbay.jetty, org.Apache.maven.plugins et org.codehaus.mojo.

La deuxième étape est de savoir comment cette recherche est réellement effectuée. Maven télécharge les fichiers de métadonnées (ou les recherche dans votre référentiel local s'ils sont déjà téléchargés), appelé maven-metadata.xml, à partir de chaque référentiel distant sur ces identifiants de groupe. Si nous prenons l'exemple où le seul référentiel distant que nous avons est Maven Central, Maven téléchargera d'abord http://repo1.maven.org/maven2/org/mortbay/jetty/maven-metadata.xml , et regardez à l'intérieur de ce fichier si nous avons quelque chose de mappant foo. Remarquez comment l'ID de groupe a été transformé en une structure de répertoires dans le référentiel distant. La structure de ce fichier de métadonnées est la suivante:

<metadata>
  <plugins>
    <plugin>
      <name>Some Awesome Maven Plugin</name>
      <prefix>somePrefix</prefix>
      <artifactId>some-maven-plugin</artifactId>
    </plugin>
  </plugins>
</metadata>

Si aucun des <plugin> la section contient un <prefix> qui est égal à celui que nous avons spécifié (foo), Maven continuera avec l'ID de groupe suivant, en appuyant sur http://repo1.maven.org/maven2/org/codehaus/mojo/maven-metadata.xml . Encore une fois, si aucun n'est trouvé, Maven frappera finalement http://repo1.maven.org/maven2/org/Apache/maven/plugins/maven-metadata.xml (notez le Downloading: connecte votre mvn jetty:run, récupérant exactement ces deux derniers fichiers). Si aucun n'est encore trouvé, Maven ne peut plus rien faire pour vous, et cela entraînera une erreur:

[ERREUR] Aucun plugin trouvé pour le préfixe 'foo' dans le projet en cours et dans les groupes de plugins [org.mortbay.jetty, org.Apache.maven.plugins, org.codehaus.mojo] disponibles dans les référentiels [local (.. ./.m2/repository), central ( http://repo.maven.Apache.org/maven2)] -> [Aide 1]

C'est l'erreur que vous avez ici. Cependant, si une correspondance a été établie lors de cette recherche, Maven peut déduire le <artifactId> utiliser.

Cela signifie maintenant qu'il a l'ID de groupe et l'ID d'artefact. La dernière pièce du puzzle est la version

Quelle version va être utilisée?

Maven prendra la dernière version disponible, sauf si elle est explicitement configurée dans le POM (voir la section suivante). Toutes les versions possibles sont récupérées en récupérant un autre fichier de métadonnées, toujours appelé maven-metadata.xml, mais cette fois en vivant à côté du dossier id d'artefact dans le référentiel (contrairement à ceux ci-dessus, où il était à côté de l'ID de groupe). Prenons l'exemple du plugin Maven Clean (dont l'ID de groupe et l'ID d'artefact se trouveraient avec le mécanisme ci-dessus et une commande de mvn clean:clean), le maven-metadata.xml ressemble à:

<metadata>
  <groupId>org.Apache.maven.plugins</groupId>
  <artifactId>maven-clean-plugin</artifactId>
  <versioning>
    <latest>3.0.0</latest>
    <release>3.0.0</release>
    <versions>
      <version>2.0-beta-1</version>
      <version>2.0-rc1</version>
      <version>2.0</version>
      <version>2.1</version>
      <!-- more versions -->
      <version>3.0.0</version>
    </versions>
    <lastUpdated>20151022205339</lastUpdated>
  </versioning>
</metadata>

Maven sélectionnera comme version le <release> version, qui représente la dernière version du plugin. Si cette balise n'est pas là, elle sélectionnera <latest> qui représente la dernière version du plugin, de la version ou de l'instantané. Il peut arriver que les deux balises ne soient pas là, auquel cas, Maven sélectionnera la première version, ou le premier instantané faute de version , de la liste de <version> éléments.

Si cela échoue toujours, Maven ne peut plus rien faire pour vous, la version n'a pas pu être déduite et il y a des erreurs. Cependant, cela ne se produira probablement pas. Nous avons maintenant rassemblé l'ID de groupe, l'ID d'artefact et la version; il est enfin temps d'invoquer l'objectif bar de notre plugin.

Quel est le problème avec ma configuration?

Comme indiqué ci-dessus, Maven recherche dans certains identifiants de groupe prédéfinis à l'intérieur des référentiels distants actifs pour rechercher des correspondances avec un préfixe donné. Avec la commande

mvn findbugs:findbugs

Maven démarre la recherche avec le préfixe findbugs. Puisque notre configuration n'a pas de <pluginGroup> dans nos paramètres, Maven examine org.codehaus.mojo et org.Apache.maven.plugins id de groupe pour une correspondance de préfixe.

Et il en trouve un: Plugin Findbugs Maven est publié sous le org.codehaus.mojo id du groupe; en effet, vous pouvez le trouver dans le maven-metadata.xml :

<plugin>
  <name>FindBugs Maven Plugin</name>
  <prefix>findbugs</prefix>
  <artifactId>findbugs-maven-plugin</artifactId>
</plugin>

Et vous pouvez également trouver la version qui va être utilisée en jetant un œil dans le maven-metadata.xml fichier sous le findbugs-maven-plugin vient d'être déduit (3.0.4 au moment d'écrire ces lignes; et remarquez comment cela correspond exactement à la version dans le mvn findbugs:findbugs journaux de votre question). La résolution a donc réussi, puis Maven peut continuer à invoquer l'objectif findbugs de ce plugin.

Le deuxième exemple est la commande

mvn jetty:run

Comme précédemment, les mêmes étapes de résolution se produisent, mais, dans ce cas, vous découvrirez que le préfixe <jetty> n'apparaît dans aucun des maven-metadata.xml pour les identifiants de groupe org.codehaus.mojo et org.Apache.maven.plugins. La résolution échoue donc et Maven renvoie l'erreur que vous avez.

Mais nous avons vu comment le faire fonctionner! Nous pouvons ajouter un <pluginGroup> dans nos paramètres, afin que cet identifiant de groupe puisse également être recherché pendant la résolution. Jetty Maven Plugin est publié sous l'ID de groupe org.Eclipse.jetty, et si nous jetons un œil dans le correspondant maven-metadata.xml dans Maven Central , vous verrez que <prefix>jetty</prefix> y a-t-il. Le correctif est donc simple: il suffit de définir ce nouvel identifiant de groupe pour rechercher dans les paramètres:

<pluginGroups>
  <pluginGroup>org.Eclipse.jetty</pluginGroup>
</pluginGroups>

Maintenant, Maven examinera également cet identifiant de groupe et fera correspondre le préfixe jetty au org.Eclipse.jetty:jetty-maven-plugin avec succès.

Comment utiliser une version spécifique? Ou, je ne veux pas modifier mes paramètres!

Bien sûr, toute cette résolution peut être contournée si vous définissez le plugin explicitement dans votre POM, qui est l'autre solution que vous avez trouvée:

<plugin>
  <groupId>org.Eclipse.jetty</groupId>
  <artifactId>jetty-maven-plugin</artifactId>
  <version>9.2.11.v20150529</version>
</plugin>

et utilise

mvn jetty:run

Si vous configurez le plugin directement dans le POM, la résolution du préfixe se produit toujours, mais elle est un peu masquée: Maven téléchargera le plugin à partir des référentiels distants configurés, et téléchargera et installera tous les fichiers de métadonnées en cours de route, y compris le maven-metadata.xml contenant le mappage du préfixe jetty. Donc, comme il le télécharge automatiquement, la recherche réussit toujours.

Notez également que puisque le plugin a été défini dans le POM, vous n'aurez pas besoin de <pluginGroup> dans les paramètres: l'ID du groupe a été écrit dans le POM. De plus, il s'assure que la version 9.2.11.v20150529 va être utilisée, au lieu de la dernière.

39
Tunaki