À quoi sert le plugin maven-shade-plugin et pourquoi voudriez-vous déplacer les packages Java?

J’ai trouvé que le plugin maven-shade-plugin était utilisé dans le fichier pom.xml de quelqu’un. Je n’ai jamais utilisé maven-shade-plugin auparavant (et je suis un Maven n00b), alors j’ai essayé de comprendre la raison de cette utilisation et de ce qu’elle fait.

J’ai regardé les documents Maven , mais je ne peux pas comprendre cette déclaration:

“Ce plugin offre la possibilité d’emballer l’artefact dans un uber-jar, y compris ses dépendances et de mettre à l’ombre – c.-à-d. Renommer – les paquets de certaines des dépendances.” La documentation sur la page ne semble pas très conviviale pour les débutants.

Qu’est-ce qu’un “uber jar?” Pourquoi quelqu’un voudrait-il en fabriquer un? Quel est l’intérêt de renommer les packages des dépendances? J’ai essayé de passer en revue les exemples de la page Apache de maven-shade-plugin, telle que «Sélection du contenu pour Uber Jar», mais je n’arrive toujours pas à comprendre ce qui est accompli avec «shading».

Tout pointeur vers des exemples / cas d’utilisation illustratifs (avec une explication de la raison pour laquelle l’ombrage était requirejs dans ce cas – quel problème cela résout) serait apprécié. Enfin, quand dois-je utiliser le plugin maven-shade-plugin?

    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 trouver tous les artefacts (JARs, etc.) que le projet dépend du moment où le projet est construit.

    Un uber-jar est quelque chose qui prend toutes les dépendances, et extrait le contenu des dépendances et les place 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 n’aurez besoin que d’un gros JAR au lieu de tonnes de petits JAR pour exécuter votre application. Cela facilite également la dissortingbution dans certains cas.

    Juste une note latérale. Évitez d’utiliser uber-jar en tant que dépendance Maven, car cela gâche 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 dissortingbution manuelle, mais pas pour le repository 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 qui, espérons-le, aideront les personnes ayant des questions similaires.

    La création d’ub-jar pour faciliter le déploiement est un cas d’utilisation du plugin shad. Il existe également d’autres cas d’utilisation courants qui impliquent un changement de nom de package.

    Par exemple, je développe une bibliothèque Foo , qui dépend d’une version spécifique (par exemple 1.0) de la bibliothèque Bar . En supposant que je ne puisse pas utiliser d’autres versions de Bar lib (à cause de la modification de l’API ou d’autres problèmes techniques, etc.). Si je déclare simplement Bar:1.0 comme une dépendance de Foo dans Maven, il est possible de tomber dans un problème: un projet Qux dépend de Foo , et aussi Bar:2.0 (et il ne peut pas utiliser Bar:1.0 car Qux doit utiliser nouvelle fonctionnalité dans Bar:2.0 ). Voici le dilemme: Qux devrait- Qux utiliser Bar:1.0 (quel code Qux ne fonctionnera pas) ou Bar:2.0 (quel code Foo ne fonctionnera pas)?

    Afin de résoudre ce problème, le développeur de Foo peut choisir d’utiliser le plugin shadie pour renommer son utilisation de Bar , de sorte que toutes les classes de Bar:1.0 jar soient incorporées dans Foo jar et que le package des classes Bar incorporées soit modifié de com.bar à com.foo.bar . Ce faisant, Qux peut en toute sécurité dépendre de Bar:2.0 car maintenant, Foo ne dépend plus de la Bar , et il utilise sa propre copie de la Bar “modifiée” située dans un autre paquet.

    Je me demandais récemment pourquoi elasticsearch nuançait et déplaçait quelques dépendances (mais pas toutes). Voici une explication du responsable du projet, @kimchy :

    La partie ombrée est intentionnelle, les bibliothèques ombrées que nous utilisons dans elasticsearch font partie intégrante d’elasticsearch, la version utilisée est étroitement liée à ce que elasticsearch expose et à la manière dont elle utilise la bibliothèque en fonction du fonctionnement interne de la bibliothèque (et qui change entre les versions), netty et guava sont d’excellents exemples.

    Btw, je n’ai aucun problème à fournir plusieurs jarres de elasticsearch, une avec lucene non ombrée, et une avec Lucene shaded. Je ne sais pas comment le faire avec maven. Je ne veux pas fournir une version qui ne nuise pas à netty / jackson par exemple, en raison de l’intimidation intense que ces derniers ont avec eux (par exemple, utiliser l’amélioration du tampon avec toute version précédente de netty, à l’exception de la version actuelle). utiliser réellement plus de mémoire par rapport à l’utilisation considérablement moins).

    https://github.com/elasticsearch/elasticsearch/issues/2091#issuecomment-7156766

    Et un autre ici de drewr :

    L’ombrage est important pour garder nos dépendances (notamment netty, lucene, guava) proches de notre code afin que nous puissions résoudre un problème même si le fournisseur en amont est à la traîne. Il est possible que nous dissortingbuions des versions modulaires du code, ce qui aiderait avec votre problème particulier (par exemple, # 2091), mais nous ne pouvons pas simplement supprimer les dépendances ombrées pour le moment. Vous pouvez créer une version locale de ES pour vos besoins jusqu’à ce que la solution soit meilleure.

    https://github.com/elasticsearch/elasticsearch/pull/3244#issuecomment-20125452

    Donc, c’est un cas d’usage. Comme exemple illustratif, voici comment maven-shade-plugin est utilisé dans le fichier pom.xml d’elasticsearch (v0.90.5). Les lignes artifactSet::include lui indiquent les dépendances à tirer dans le JAR uber (en gros, elles sont décompressées et ré-empaquetées avec les propres classes d’elasticsearch lorsque le fichier JAR cible est produit. (Si vous ne le saviez pas déjà, un fichier JAR est juste un fichier ZIP contenant les classes du programme, les ressources, etc., et certaines métadonnées, vous pouvez en extraire un pour voir comment il est assemblé.)

    Les lignes relocations::relocation 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 mettant sous org.elasticsearch.common .

    Enfin, la section des filters exclut certains éléments du fichier JAR cible, tels que les métadonnées JAR, les fichiers de construction ant, les fichiers texte, etc. qui sont fournis avec certaines dépendances, mais qui n’appartiennent pas à un JAR uber. .

       org.apache.maven.plugins maven-shade-plugin 2.1   package  shade     true   com.google.guava:guava net.sf.trove4j:trove4j org.mvel:mvel2 com.fasterxml.jackson.core:jackson-core com.fasterxml.jackson.dataformat:jackson-dataformat-smile com.fasterxml.jackson.dataformat:jackson-dataformat-yaml joda-time:joda-time io.netty:netty com.ning:compress-lzf     com.google.common org.elasticsearch.common   gnu.trove org.elasticsearch.common.trove   jsr166y org.elasticsearch.common.util.concurrent.jsr166y   jsr166e org.elasticsearch.common.util.concurrent.jsr166e   org.mvel2 org.elasticsearch.common.mvel2   com.fasterxml.jackson org.elasticsearch.common.jackson   org.joda org.elasticsearch.common.joda   org.jboss.netty org.elasticsearch.common.netty   com.ning.compress org.elasticsearch.common.compress     *:*  META-INF/license/** META-INF/* META-INF/maven/** LICENSE NOTICE /*.txt build.properties       

    Petit avertissement

    Bien que cela ne décrive pas pourquoi on aimerait utiliser le plugin maven-shade-plugin (puisque la réponse sélectionnée le décrit assez bien), je voudrais noter que j’ai eu des problèmes avec cela. Il a changé le JAR (depuis que c’est ce qu’il fait) et il a provoqué une régression dans mon logiciel.

    Donc, au lieu d’utiliser ceci (ou le plugin maven-jarjar), j’ai utilisé le binary de JarJar qui semble fonctionner sans problème.

    Je poste ici ma solution car il m’a fallu du temps pour trouver une solution décente.


    Télécharger le fichier JAR de JarJar

    Vous pouvez télécharger le bocal ici: https://code.google.com/p/jarjar/ Dans le menu de gauche, vous avez un lien pour le télécharger.


    Comment utiliser JarJar afin de déplacer des classes d’un JAR d’un paquet à un autre

    Dans cet exemple, nous allons remplacer le package “com.fasterxml.jackson” par “io.kuku.dependencies.com.fasterxml.jackson”. – Le fichier JAR source s’appelle “jackson-databind-2.6.4.jar” et le nouveau fichier JAR modifié (cible) s’appelle “kuku-jackson-databind-2.6.4.jar”. – Le fichier JAR “jarjar” est en version 1.4

    1. Créez un fichier “rules.txt”. Le contenu du fichier devrait être (regardez la période précédant le caractère ‘@’): règle com.fasterxml.jackson. ** io.kuku.dependencies.com.fasterxml.jackson. @ 1

    2. Exécutez la commande suivante: java -jar processus jarjar-1.4.jar 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 \”.

    Installation de mvn: install-file -Dfile = C: \ mes-jars \ kuku-jackson-annotations-2.6.4.jar -DgroupId = io.kuku.dependencies Dpackaging = pot

    Installation de mvn: install-file -Dfile = C: \ mes-jars \ kuku-jackson-core-2.6.4.jar -DgroupId = io.kuku.dependencies -DartifactId = kuku-jackson-core -Dversion = 2.6.4 – Dpackaging = pot

    Installation de mvn: fichier-installation-fichier-de-données = C: \ mes-bocaux \ kuku-jackson-databind-2.6.4.jar -DgroupId = io.kuku.dependencies Dpackaging = pot


    Utiliser les JAR modifiés dans le pom du projet

    Dans cet exemple, il s’agit de l’élément “dependencies” des projets pom:

          io.kuku.dependencies kuku-jackson-annotations 2.6.4   io.kuku.dependencies kuku-jackson-core 2.6.4   io.kuku.dependencies kuku-jackson-databind 2.6.4