J'ai trouvé le plugin maven-shadow utilisé dans le fichier pom.xml de quelqu'un. Je n'ai jamais utilisé de plugin maven-shadow avant (et je suis un Maven n00b), j'ai donc essayé de comprendre la raison de son utilisation et ce qu'il fait.
J'ai regardé les documents Maven , mais je ne comprends pas cette déclaration:
"Ce plugin offre la possibilité de conditionner l'artefact dans un uber-jar, y compris ses dépendances et de masquer - c'est-à-dire renommer - les packages de certaines des dépendances."
La documentation sur la page ne semble pas très adaptée aux débutants.
Qu'est-ce qu'un "pot uber?" Pourquoi voudrait-on en faire un? Quel est l'intérêt de renommer les packages des dépendances? J'ai essayé de passer en revue les exemples sur la page apache de maven-shadow-plugin tels que "Sélection du contenu pour Uber Jar", mais je ne comprends toujours pas ce qui est accompli avec "ombrage".
Tout pointeur vers des exemples / cas d'utilisation illustratifs (avec une explication de la raison pour laquelle l'ombrage était nécessaire dans ce cas - quel problème résout-il) serait apprécié. Enfin, quand dois-je utiliser le plugin maven-shadow-plugin?
la source
s/reallocation/relocation/
dans le commentaire ci-dessus.Réponses:
Uber JAR, en bref, est un JAR contenant tout.
Normalement, à Maven, nous comptons sur la gestion des dépendances. Un artefact ne contient que les classes / ressources de lui-même. Maven sera responsable de découvrir tous les artefacts (JAR, etc.) du projet en fonction de la date de construction du projet.
Un uber-jar est quelque chose qui prend toutes les dépendances, extrait le contenu des dépendances et les met avec les classes / ressources du projet lui-même, dans un grand JAR. En ayant un tel uber-jar, il est facile à exécuter, car vous aurez besoin d'un seul grand JAR au lieu de tonnes de petits JAR pour exécuter votre application. Il facilite également la distribution dans certains cas.
Juste une petite note. Évitez d'utiliser uber-jar comme dépendance Maven, car cela ruine la fonctionnalité de résolution des dépendances de Maven. Normalement, nous créons uber-jar uniquement pour l'artefact final pour un déploiement réel ou pour une distribution manuelle, mais pas pour le placement dans le référentiel Maven.
Mise à jour: Je viens de découvrir que je n'ai pas répondu à une partie de la question: "Quel est l'intérêt de renommer les packages des dépendances?". Voici quelques brèves mises à jour et, espérons-le, aideront les personnes ayant une question similaire.
Créer un uber-jar pour faciliter le déploiement est un cas d'utilisation du plugin d'ombre. Il existe également d'autres cas d'utilisation courants qui impliquent un changement de nom de package.
Par exemple, je développe une
Foo
bibliothèque, qui dépend d'une version spécifique (par exemple 1.0) de laBar
bibliothèque. En supposant que je ne peux pas utiliser une autre version deBar
lib (en raison d'un changement d'API ou d'autres problèmes techniques, etc.). Si je déclare simplementBar:1.0
queFoo
la dépendance « dans Maven, il est possible de tomber dans un problème: unQux
projet dépend deFoo
, et aussiBar:2.0
(et il ne peut pas utiliserBar:1.0
parce que lesQux
besoins d'utiliser nouvelle fonctionnalitéBar:2.0
). Voici le dilemme: devraitQux
utiliserBar:1.0
(quelQux
code ne fonctionnera pas) ouBar:2.0
(quelFoo
code ne fonctionnera pas)?Afin de résoudre ce problème, le développeur de
Foo
peut choisir d'utiliser le plugin d'ombre pour renommer son utilisationBar
, de sorte que toutes les classes dansBar:1.0
jar soient incorporées dansFoo
jar et que le package desBar
classes incorporées soit changé decom.bar
encom.foo.bar
. Ce faisant,Qux
peut dépendre en toute sécuritéBar:2.0
car maintenantFoo
ne dépend plus deBar
, et il utilise sa propre copie de "altéré"Bar
situé dans un autre package.la source
jar-with-dependency
descripteur intégré . Pour le problème de la dépendance de la roslution avec uber-jar, j'ai déjà mentionné dans ma réponse: N'utilisez pas uber-jar comme dépendance, point final. Un peu plus en détail: avant de créer l'uber-jar, vous devez avoir un projet normal avec une dépendance normale. Cet artefact d'origine est celui que vous devez utiliser comme dépendance (au lieu du pot d'uber)Class.forName
fonctionne- t-il pas ?Je me demandais récemment pourquoi elasticsearch ombrage et délocalise quelques-unes (mais pas toutes) de ses dépendances. Voici une explication du responsable du projet, @kimchy :
- https://github.com/elasticsearch/elasticsearch/issues/2091#issuecomment-7156766
Et un autre ici de drewr :
- https://github.com/elasticsearch/elasticsearch/pull/3244#issuecomment-20125452
Voilà donc un cas d'utilisation. Comme pour un exemple illustratif, voici comment le plugin maven-shadow-plugin est utilisé dans le fichier pom.xml d'elasticsearch (v0.90.5). Les
artifactSet::include
lignes lui indiquent les dépendances à insérer dans le JAR uber (en gros, elles sont décompressées et reconditionnées aux côtés des propres classes d'Elasticsearch lorsque le pot Elasticsearch cible est produit. (Si vous ne le saviez pas déjà, un fichier JAR est juste un fichier ZIP qui contient les classes du programme, les ressources, etc., et quelques métadonnées. Vous pouvez en extraire un pour voir comment il est assemblé.)Les
relocations::relocation
lignes sont similaires, sauf que dans chaque cas, elles appliquent également les substitutions spécifiées aux classes de la dépendance - dans ce cas, en les regroupantorg.elasticsearch.common
.Enfin, la
filters
section exclut certaines choses du JAR cible qui ne devraient pas y être - telles que les métadonnées JAR, les fichiers de construction de fourmis, les fichiers texte, etc. qui sont emballés avec certaines dépendances, mais qui n'appartiennent pas à un JAR uber.la source
Petit avertissement
Bien que cela ne décrive pas pourquoi on aimerait utiliser le plugin maven-shadow-plugin (puisque la réponse sélectionnée le décrit assez bien), je voudrais noter que j'ai eu des problèmes avec lui. Cela a changé le JAR (puisque c'est ce qu'il fait) et cela a provoqué une régression dans mon logiciel.
Donc, au lieu d'utiliser ceci (ou le plugin maven-jarjar), j'ai utilisé le binaire de JarJar qui semble fonctionner sans problème.
Je poste ici ma solution car il m'a fallu un certain temps pour trouver une solution décente.
Télécharger le fichier JAR de JarJar
Vous pouvez télécharger le pot ici: https://code.google.com/p/jarjar/ Dans le menu de gauche, vous avez un lien pour le télécharger.
Comment utiliser JarJar pour déplacer des classes d'un JAR d'un package à un autre
Dans cet exemple, nous allons changer le package de "com.fasterxml.jackson" en "io.kuku.dependencies.com.fasterxml.jackson". - Le JAR source est appelé "jackson-databind-2.6.4.jar" et le nouveau JAR modifié (cible) est appelé "kuku-jackson-databind-2.6.4.jar". - Le fichier JAR "jarjar" est en version 1.4
Créez un fichier "rules.txt". Le contenu du fichier doit être (observez la période précédant le caractère '@'): règle com.fasterxml.jackson. ** io.kuku.dependencies.com.fasterxml.jackson. @ 1
Exécutez la commande suivante: java -jar jarjar-1.4.jar process rules.txt jackson-databind-2.6.4.jar kuku-jackson-databind-2.6.4.jar
Installation des fichiers JAR modifiés dans le référentiel local
Dans ce cas, j'installe 3 fichiers situés dans le dossier "c: \ my-jars \".
mvn install: install-file -Dfile = C: \ my-jars \ kuku-jackson-annotations-2.6.4.jar -DgroupId = io.kuku.dependencies -DartifactId = kuku-jackson-annotations -Dversion = 2.6.4 - Dpackaging = pot
mvn install: install-file -Dfile = C: \ my-jars \ kuku-jackson-core-2.6.4.jar -DgroupId = io.kuku.dependencies -DartifactId = kuku-jackson-core -Dversion = 2.6.4 - Dpackaging = pot
mvn install: install-file -Dfile = C: \ my-jars \ kuku-jackson-databind-2.6.4.jar -DgroupId = io.kuku.dependencies -DartifactId = kuku-jackson-annotations -Dversion = 2.6.4 - Dpackaging = pot
Utilisation des fichiers JAR modifiés dans le pom du projet
Dans cet exemple, il s'agit de l'élément "dépendances" dans le projet pom:
la source
Je pense qu'un exemple de la nécessité d'un pot "ombré" est une fonction AWS Lambda. Ils semblent vous permettre de télécharger seulement 1 pot, pas une collection entière de .jars comme vous le trouveriez dans un fichier .war typique. Ainsi, la création d'un seul .jar avec toutes les dépendances du projet vous permet de le faire.
la source