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

j'ai trouvé le maven-shade-plugin utilisé dans la pom de quelqu'un.XML. Je n'ai jamais utilisé maven-shade-plugin avant (et je suis un Maven n00b) donc j'ai essayé de comprendre la raison de l'utilisation de CE et ce qu'il fait.

j'ai regardé le Maven docs , cependant je ne peux pas comprendre cette déclaration:

" ce plugin fournit la possibilité d'empaqueter l'artefact dans un Uber-jar, y compris ses dépendances et d'ombrer - i.e. renommer-les paquets de certaines dépendances."La documentation sur la page ne semble pas très conviviale pour les débutants.

qu'est Ce qu'un "uber pot?"Pourquoi quelqu'un voudrait-il le faire? Quel est l'intérêt de renommer les paquets des dépendances? J'ai essayé de passer en revue les exemples sur la page apache maven-shade-plugin tels que "Selecting contents for Uber Jar," mais je ne peux toujours pas comprendre ce qui est accompli avec "shading."

toute indication d'exemples/cas d'utilisation (avec une explication de la raison pour laquelle l'ombrage est requis dans ce cas - ci-quel problème est-il résolu) serait appréciée. Enfin, quand dois-je utiliser le maven-ombre-plugin?

228
demandé sur Lii 2012-11-29 10:46:36

3 réponses

Uber POT, en bref, est un récipient contenant de tout.

normalement dans Maven, nous comptons sur la gestion de la dépendance. Un artefact ne contient que les classes/ressources de lui-même. Maven sera responsable de trouver tous les artéfacts (jarres, etc.) que le projet selon le 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 met avec les classes/ressources de le projet lui-même, dans un grand BOCAL. En ayant un tel Uber-jar, il est facile pour l'exécution, parce que vous aurez besoin d'un seul grand pot au lieu de tonnes de petits pots 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 fonction de résolution de dépendance de Maven. Normalement nous créons Uber-jar seulement pour l'artéfact final pour le déploiement réel ou pour la distribution manuelle, mais pas pour mettre à Maven repository.


mise à jour: je viens de découvrir que je n'ai pas répondu à une partie de la question:" à quoi bon renommer les paquets des dépendances?". Voici quelques brèves mises à jour et, espérons-le, aideront les personnes qui ont une question semblable.

créer Uber-jar pour la facilité de déploiement est un cas d'utilisation de plugin d'ombre. Il existe également d'autres cas d'utilisation courante qui impliquent un changement de nom du paquet.

par exemple, je développe Foo bibliothèque, qui dépend d'une version spécifique (par exemple 1.0) de Bar bibliothèque. En supposant que je ne puisse pas utiliser une autre version de Bar lib (parce que L'API change, ou d'autres problèmes techniques, etc). Si je déclare simplement Bar:1.0 comme la 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 parce que Qux doit utiliser la nouvelle caractéristique dans Bar:2.0 ). Voici le dilemme: Qux utiliser Bar:1.0 (quel code de Qux ne fonctionnera pas) ou Bar:2.0 (quel code de Foo ne fonctionnera pas)?

afin de résoudre ce problème, le développeur de Foo peut choisir d'utiliser le plugin shade pour renommer son utilisation de Bar , de sorte que toutes les classes dans Bar:1.0 pot sont intégrés dans Foo pot, et le paquet de la La classe Bar est remplacée par la classe com.foo.bar . Ce faisant, Qux peut en toute sécurité dépendre de Bar:2.0 parce que maintenant Foo ne dépend plus de Bar , et il utilise sa propre copie de "modifié" Bar situé dans un autre paquet.

269
répondu Adrian Shum 2016-02-12 02:20:20

je me demandais récemment pourquoi elasticsearch abat et déplace quelques-unes (mais pas toutes) de ses dépendances. Voici une explication du responsable du projet, @kimchy :

la partie ombragée est intentionnelle, les bibliothèques ombragées que nous utilisons dans elasticsearch sont pour tout but et partie d'elasticsearch, la version utilisée est étroitement liée à ce qu'elasticsearch expose et comment il utilise la bibliothèque basé sur les internes de la façon dont la bibliothèque fonctionne (et que les changements entre les versions), netty et guava sont de grands exemples.

Btw, Je n'ai aucun problème à réellement fournir plusieurs pots de elasticsearch, un avec lucene pas ombragé, et un avec Lucene ombragé. Mais je ne sais pas comment faire avec maven. Je ne veux pas fournir une version qui ne nuance pas netty / jackson par exemple, en raison de l'utilisation intimiate profonde elasticsearch A avec eux (par exemple, en utilisant l'amélioration de bufferring à venir avec n'importe quelle version précédente de netty à l'exception de la version actuelle utilisera en fait 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 il est important de garder nos dépendances (notamment netty, lucene, guava) près de notre code afin que nous puissions résoudre un problème même si le fournisseur amont est en retard. Il est possible que nous distribuions des versions modularisées du code, ce qui aiderait pour votre problème particulier (#2091 par exemple), mais nous ne pouvons pas simplement supprimer les dépendances ombragées pour le moment. Vous pouvez construire une version locale de ES pour vos besoins jusqu'à ce qu'il y ait une meilleure solution.

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

Donc, c'est un cas d'utilisation. Comme pour un exemple illustratif, voici comment maven-shade-plugin est utilisé dans les pom d'elasticsearch.xml (v0.90.5). Les lignes artifactSet::include lui indiquent les dépendances à tirer dans le bocal uber (en gros, ils sont décompressés et emballés avec les propres classes d'elasticsearch lorsque le bocal cible d'elasticsearch est produire. (Dans le cas où 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 certaines métadonnées. Vous pouvez en extraire un pour voir comment il est assemblé.)

les lignes relocations::relocation sont semblables, sauf que dans chaque cas, elles appliquent aussi les substitutions spécifiées aux catégories de personnes à charge - dans ce cas, elles sont regroupées sous org.elasticsearch.common .

enfin la section filters exclut certaines choses de la jarre cible qui ne devrait pas être là - bas-tels que les métadonnées de la jarre, ant construisent des fichiers, des fichiers texte, etc. qui sont empaquetés avec certaines dépendances, mais qui n'ont pas leur place dans un Uber JAR.

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>2.1</version>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>shade</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <minimizeJar>true</minimizeJar>
            <artifactSet>
                <includes>
                    <include>com.google.guava:guava</include>
                    <include>net.sf.trove4j:trove4j</include>
                    <include>org.mvel:mvel2</include>
                    <include>com.fasterxml.jackson.core:jackson-core</include>
                    <include>com.fasterxml.jackson.dataformat:jackson-dataformat-smile</include>
                    <include>com.fasterxml.jackson.dataformat:jackson-dataformat-yaml</include>
                    <include>joda-time:joda-time</include>
                    <include>io.netty:netty</include>
                    <include>com.ning:compress-lzf</include>
                </includes>
            </artifactSet>
            <relocations>
                <relocation>
                    <pattern>com.google.common</pattern>
                    <shadedPattern>org.elasticsearch.common</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>gnu.trove</pattern>
                    <shadedPattern>org.elasticsearch.common.trove</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>jsr166y</pattern>
                    <shadedPattern>org.elasticsearch.common.util.concurrent.jsr166y</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>jsr166e</pattern>
                    <shadedPattern>org.elasticsearch.common.util.concurrent.jsr166e</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>org.mvel2</pattern>
                    <shadedPattern>org.elasticsearch.common.mvel2</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>com.fasterxml.jackson</pattern>
                    <shadedPattern>org.elasticsearch.common.jackson</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>org.joda</pattern>
                    <shadedPattern>org.elasticsearch.common.joda</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>org.jboss.netty</pattern>
                    <shadedPattern>org.elasticsearch.common.netty</shadedPattern>
                </relocation>
                <relocation>
                    <pattern>com.ning.compress</pattern>
                    <shadedPattern>org.elasticsearch.common.compress</shadedPattern>
                </relocation>
            </relocations>
            <filters>
                <filter>
                    <artifact>*:*</artifact>
                    <excludes>
                        <exclude>META-INF/license/**</exclude>
                        <exclude>META-INF/*</exclude>
                        <exclude>META-INF/maven/**</exclude>
                        <exclude>LICENSE</exclude>
                        <exclude>NOTICE</exclude>
                        <exclude>/*.txt</exclude>
                        <exclude>build.properties</exclude>
                    </excludes>
                </filter>
            </filters>
        </configuration>
    </plugin>
</plugins>
55
répondu Tom 2017-05-23 11:55:07

petit avertissement

bien que ce ne soit pas décrire pourquoi on voudrait utiliser le 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 elle. Il a changé le pot (depuis que ce qu'il fait) et il a causé la régression dans mon logiciel.

donc, au lieu d'utiliser ceci (ou le maven-jarjar-plugin), 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 convenable.


Télécharger JarJar du fichier JAR

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


un autre

dans cet exemple, nous changerons le paquet de" com.fasterxml.jackson " to " io.kuku.les dépendances.com.fasterxml.jackson". - Le pot source s'appelle "jackson-databind-2.6.4.jar " et le nouveau JAR modifié (cible) s'appelle "kuku-jackson-databind-2.6.4.pot." - Le fichier" jarjar " est dans la version 1.4

  1. Créer les règles".txt" un fichier. Le contenu du fichier doit être (regarder la période avant le'@' caractère): règle de com.fasterxml.Jackson.** io.kuku.dependencies.com.fasterxml.jackson.@1

  2. exécutez la commande suivante: java-jar jarjar-1.4.les règles du jar process.txt jackson-databind-2.6.4.jar kuku-jackson-databind-2.6.4.jar


installation des pots modifiés dans le dépôt local

dans ce cas, j'installe 3 fichiers situés sur" c:\my-jars\" dossier.

mvn install:install-fichier -Dfile=C:\mon-pots\kuku-jackson-annotations-2.6.4.jar-DgroupId=io.kuku.dépendances-DartifactId=kuku-jackson-annotations -Dversion=2.6.4-Dpackaging =jar

mvn install:install-fichier -Dfile=C:\mon-pots\kuku-jackson-core-2.6.4.jar-DgroupId=io.kuku.dependencies-DartifactId=kuku-jackson-core-Dversion=2.6.4-Dpackaging =jar

mvn install: install-file -Dfile=C:\mon-pots\kuku-jackson-databind-2.6.4.jar-DgroupId=io.kuku.dépendances-DartifactId=kuku-jackson-annotations -Dversion=2.6.4-Dpackaging =jar


utilisant les bocaux modifiés dans les pom du projet

dans cet exemple, c'est l'élément" dépendances "dans les projets pom:

<dependencies>
    <!-- ================================================== -->
    <!-- kuku JARs -->
    <!-- ================================================== -->
    <dependency>
        <groupId>io.kuku.dependencies</groupId>
        <artifactId>kuku-jackson-annotations</artifactId>
        <version>2.6.4</version>
    </dependency>
    <dependency>
        <groupId>io.kuku.dependencies</groupId>
        <artifactId>kuku-jackson-core</artifactId>
        <version>2.6.4</version>
    </dependency>
    <dependency>
        <groupId>io.kuku.dependencies</groupId>
        <artifactId>kuku-jackson-databind</artifactId>
        <version>2.6.4</version>
    </dependency>
</dependencies>
1
répondu nadavy 2016-01-13 13:55:56