A cosa serve il plugin maven-shade e perché vorresti spostare i pacchetti Java?


Ho trovato il plugin maven-shade utilizzato nel pom di qualcuno.XML. Non ho mai usato maven-shade-plugin prima (e sono un Maven n00b) quindi ho cercato di capire il motivo dell'utilizzo di questo e cosa fa.

Ho guardato il Maven docs, tuttavia non riesco a capire questa affermazione:

"Questo plugin fornisce la capacità di impacchettare l'artefatto in un uber-jar, incluse le sue dipendenze e di ombreggiare - cioè rinominare - i pacchetti di alcune delle dipendenze." Il la documentazione sulla pagina non sembra molto amichevole per i principianti.

Che cos'è un "barattolo uber?"Perché qualcuno dovrebbe volerne fare uno? Qual è il punto di rinominare i pacchetti delle dipendenze? Ho provato a passare attraverso gli esempi sulla pagina apache maven-shade-plugin come "Selezione dei contenuti per Uber Jar", ma non riesco ancora a capire cosa si sta realizzando con " shading."

Eventuali puntatori a esempi illustrativi / casi d'uso (con una spiegazione del perché l'ombreggiatura era richiesta in questo caso - quale problema sta risolvendo) sarebbe apprezzato. Infine, quando dovrei usare il plugin maven-shade?

Author: Lii, 2012-11-29

3 answers

Uber JAR, in breve, è un BARATTOLO contenente tutto.

Normalmente in Maven, ci affidiamo alla gestione delle dipendenze. Un artefatto contiene solo le classi / risorse di se stesso. Maven sarà responsabile di scoprire tutti gli artefatti (barattoli, ecc.) che il progetto dipende da quando il progetto è stato costruito.

Un uber-jar è qualcosa che prende tutte le dipendenze, ed estrae il contenuto delle dipendenze e le mette con le classi/risorse del progetto stesso, in un grande VASO. Avendo tale uber-jar, è facile per l'esecuzione, perché avrai bisogno solo di un grande BARATTOLO invece di tonnellate di piccoli barattoli per eseguire la tua app. Facilita anche la distribuzione in alcuni casi.

Solo una nota a margine. Evita di usare uber-jar come dipendenza Maven, poiché sta rovinando la funzione di risoluzione delle dipendenze di Maven. Normalmente creiamo uber-jar solo per l'artefatto finale per la distribuzione effettiva o per la distribuzione manuale, ma non per la messa in repository Maven.


Aggiornamento: ho ho appena scoperto che non ho risposto a una parte della domanda: "Qual è il punto di rinominare i pacchetti delle dipendenze?". Ecco alcuni brevi aggiornamenti e speriamo che aiuteranno le persone che hanno domande simili.

La creazione di uber-jar per facilità di distribuzione è un caso d'uso del plugin shade. Ci sono anche altri casi d'uso comuni che coinvolgono la ridenominazione dei pacchetti.

Ad esempio, sto sviluppando la libreria Foo, che dipende da una versione specifica (ad esempio 1.0) della libreria Bar. Supponendo che non possa utilizzare un'altra versione di Bar lib (perché modifica API, o altri problemi tecnici, ecc.). Se dichiaro semplicemente Bar:1.0 come dipendenza di Foo in Maven, è possibile cadere in un problema: un progetto Qux dipende da Foo e anche Bar:2.0 (e non può usare Bar:1.0 perché Qux deve usare una nuova funzionalità in Bar:2.0). Ecco il dilemma: dovrebbe Qux usare Bar:1.0 (che il codice di Qux non funzionerà) o Bar:2.0 (che il codice di Foo non funzionerà)?

Per risolvere questo problema, lo sviluppatore di Foo può scegliere di utilizzare il plugin shade per rinominare il suo utilizzo di Bar, in modo che tutte le classi in Bar:1.0 jar siano incorporate in Foo jar e il pacchetto delle classi Bar incorporate venga modificato da com.bar a com.foo.bar. In questo modo, Qux può tranquillamente dipendere da Bar:2.0 perché ora Foo non dipende più da Bar, e sta usando la propria copia di "altered" Bar situata in un altro pacchetto.

 269
Author: Adrian Shum, 2016-02-12 02:20:20

Mi stavo chiedendo di recente perché elasticsearch sfumasse e trasferisse alcune (ma non tutte) delle sue dipendenze. Ecco una spiegazione dal manutentore del progetto, @kimchy:

La parte di ombreggiatura è intenzionale, le librerie ombreggiate che usiamo in elasticsearch sono per tutte le finalità e le finalità di elasticsearch, la versione utilizzata è strettamente legata a ciò che elasticsearch espone e come utilizza la libreria in base agli interni di come funziona la libreria (e che cambia tra le versioni), netty e guava sono grandi esempi.

A proposito, non ho problemi a fornire effettivamente diversi barattoli di elasticsearch, uno con lucene non ombreggiato e uno con Lucene ombreggiato. Non sono sicuro di come farlo con maven però. Non voglio fornire una versione che non ombreggi netty / jackson, ad esempio, a causa dell'uso intimo profondo che elasticsearch ha con loro (ad esempio, utilizzando il miglioramento del bufferring imminente con qualsiasi versione precedente di netty ad eccezione di quello attuale utilizzerà effettivamente più memoria rispetto all'utilizzo di molto meno).

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

E un altro qui da drewr :

L'ombreggiatura è importante per mantenere le nostre dipendenze (in particolare netty, lucene, guava) vicine al nostro codice in modo da poter risolvere un problema anche se il provider upstream è in ritardo. È possibile che lo faremo versioni modularizzate distribuite del codice, che potrebbero aiutare con il tuo particolare problema (#2091 per esempio), ma non possiamo semplicemente rimuovere le dipendenze ombreggiate in questo momento. È possibile creare una versione locale di ES per i propri scopi fino a quando non esiste una soluzione migliore.

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

Quindi, questo è un caso d'uso. Per quanto riguarda un esempio illustrativo, di seguito è riportato come maven-shade-plugin viene utilizzato in pom di elasticsearch.xml (v0.90.5). Le righe artifactSet::include indicano quali dipendenze inserire nel JAR uber (in pratica, vengono decompresse e ri-impacchettate insieme alle classi di elasticsearch quando viene prodotto il jar elasticsearch di destinazione. (Nel caso in cui non lo sapessi già, un file JAR è solo un file ZIP che contiene le classi, le risorse, ecc., e alcuni metadati. È possibile estrarre uno per vedere come è messo insieme.)

Le righe relocations::relocation sono simili, tranne che in ciascuna caso in cui applicano anche le sostituzioni specificate alle classi della dipendenza - in questo caso, portandole sotto org.elasticsearch.common.

Infine la sezione filters esclude alcune cose dal JAR di destinazione che non dovrebbero essere lì - come metadati JAR, file di compilazione ant, file di testo, ecc. che sono confezionati con alcune dipendenze, ma che non appartengono a un barattolo uber.

<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
Author: Tom, 2017-05-23 11:55:07

Piccolo avvertimento

Anche se questo non descrive il motivo per cui si vorrebbe usare il plugin maven-shade (poiché la risposta selezionata lo descrive abbastanza bene), vorrei notare che ho avuto problemi con esso. Ha cambiato il JAR (dal momento che quello che sta facendo) e ha causato la regressione nel mio software.

Quindi, invece di usare questo (o il plugin maven-jarjar), ho usato il binario di JarJar che sembra funzionare senza problemi.

Sto postando qui la mia soluzione poiché mi ha portato un po ' di tempo per trovare una soluzione decente.


Scarica il file JAR di JarJar

Puoi scaricare il barattolo da qui: https://code.google.com/p/jarjar / Nel menu a sinistra hai un link per scaricarlo.


Come usare JarJar per spostare le classi di un JAR da un pacchetto all'altro

In questo esempio cambieremo il pacchetto da " com.più velocexml.il nostro sito utilizza cookie tecnici e di terze parti. - Il VASO sorgente si chiama "jackson-databind-2.6.4.jar " e il nuovo JAR modificato (target) si chiama "kuku-jackson-databind-2.6.4.vaso". - Il file JAR" jarjar " è nella versione 1.4

  1. Creare un " regole.file "txt". Il contenuto del file dovrebbe essere (guarda il periodo prima del carattere'@'): regola com.più velocexml.Jackson.** io.kuku.dependencies.com.fasterxml.jackson.@1

  2. Eseguire il seguente comando: java-jar jarjar-1.4.regole di processo jar.txt jackson-databind-2.6.4.vaso kuku-jackson-databind-2.6.4.vaso


Installazione dei JAR modificati nel repository locale

In questo caso sto installando 3 file situati su "c:\my-jars \" cartella.

Per maggiori informazioni, consulta la nostra informativa sulla privacy.jar-DgroupId=io.kuku.dipendenze-DartifactId=kuku-jackson-annotazioni-Dversion=2.6.4-Dpackaging=jar Per maggiori informazioni clicca qui.jar-DgroupId=io.kuku.dipendenza -DartifactId=kuku-jackson-core-Dversion=2.6.4-Dpackaging=jar Il nostro sito utilizza cookie tecnici e di terze parti per migliorare la tua esperienza di navigazione.jar-DgroupId=io.kuku.dipendenze-DartifactId=kuku-jackson-annotazioni-Dversion=2.6.4-Dpackaging=jar

Utilizzo dei JAR modificati nel pom del progetto

In questo esempio, questo è l'elemento "dipendenze" nei progetti 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
Author: nadavy, 2016-01-13 13:55:56