Construire un pot de graisse avec Maven

118

J'ai une base de code que je souhaite distribuer sous forme de fichier jar. Il dépend également des fichiers jar externes, que je souhaite regrouper dans le jar final.

J'ai entendu dire que cela pouvait être fait en utilisant maven-assembly-plug-in, mais je ne comprends pas comment. Quelqu'un pourrait-il me montrer quelques exemples.

En ce moment, j'utilise du gros pot pour regrouper le dernier pot. Je veux réaliser la même chose en utilisant maven.

Bianca
la source

Réponses:

144

Remarque: si vous êtes une application à démarrage à ressort, lisez la fin de la réponse

Ajoutez le plugin suivant à votre pom.xml La dernière version peut être trouvée à

...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>CHOOSE LATEST VERSION HERE</version>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>assemble-all</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
...

Après avoir configuré ce plug-in, l'exécution mvn packageproduira deux fichiers JAR: un contenant uniquement les classes du projet, et un second gros fichier avec toutes les dépendances avec le suffixe "-jar-with-dependencies".

si vous voulez une classpathconfiguration correcte au moment de l'exécution, ajoutez également le plugin suivant

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <mainClass>fully.qualified.MainClass</mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin>

Pour l'application Spring Boot, utilisez juste le plugin suivant (choisissez la version appropriée)

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <fork>true</fork>
        <mainClass>${start-class}</mainClass>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>
Jigar Joshi
la source
1
La version actuelle de ce plugin est maintenant 2.4
guerda
13
Ceci est maintenant obsolète et le plugin maven-shade doit être utilisé à la place. Voir la réponse @phlogratos: stackoverflow.com/a/16222965/274350 .
Richard Neish
2
Maven-assembly-plugin peut-il minimiser la taille du pot de graisse?
12 mai
1
@Richard Où voyez-vous qu'il est obsolète? Je n'ai rien trouvé ici maven.apache.org/plugins/maven-assembly-plugin
user3833308
3
@ user3833308 "obsolète" n'est peut-être pas le bon mot, mais la documentation sur maven.apache.org/plugins/maven-assembly-plugin dit "Si votre projet veut empaqueter votre artefact dans un uber-jar, le plugin d'assembly ne fournit que Pour plus de contrôle, utilisez le plugin Maven Shade. "
Richard Neish
55

Vous pouvez utiliser le plugin maven-shadow .

Après avoir configuré le plugin Shade dans votre build, la commande mvn packagecréera un seul pot avec toutes les dépendances fusionnées.

phlogratos
la source
9
C'est maintenant la bonne façon de le faire. La documentation de maven-assembly-plugin déclare: "Si votre projet veut empaqueter votre artefact dans un uber-jar, le plugin d'assembly ne fournit qu'un support de base. Pour plus de contrôle, utilisez le plugin Maven Shade."
Richard Neish
Mais comment puis-je prendre ce .jar unique et l'utiliser pour la publication?
DanGordon
42

Peut-être souhaitez-vous maven-shade-pluginregrouper les dépendances, minimiser le code inutilisé et masquer les dépendances externes pour éviter les conflits.

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.1.1</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <minimizeJar>true</minimizeJar>
                        <createDependencyReducedPom>true</createDependencyReducedPom>
                        <dependencyReducedPomLocation>
                            ${java.io.tmpdir}/dependency-reduced-pom.xml
                        </dependencyReducedPomLocation>
                        <relocations>
                            <relocation>
                                <pattern>com.acme.coyote</pattern>
                                <shadedPattern>hidden.coyote</shadedPattern>
                            </relocation>
                        </relocations>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Références:

ggrandes
la source
Si on rencontre Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not found, supprimez simplement <minimizeJar>true</minimizeJar>.
koppor le
Si vous obtenez une exception «java.lang.SecurityException: Invalid signature file digest for Manifest main attributes», alors cet ajout à la section de configuration ci-dessus aide: stackoverflow.com/a/6743609/38368
Danny Varod
12

en fait, en ajoutant le

<archive>
   <manifest>
    <addClasspath>true</addClasspath>
    <packageName>com.some.pkg</packageName>                     
    <mainClass>com.MainClass</mainClass>
  </manifest>
</archive>

La déclaration à maven-jar-plugin n'ajoute pas l'entrée de classe principale au fichier manifeste pour moi. J'ai dû l'ajouter au maven-assembly-plugin afin de l'avoir dans le manifeste

Ameet Chaubal
la source
5

Vous pouvez utiliser le plugin onejar-maven pour l'empaquetage. Fondamentalement, il assemble votre projet et ses dépendances en un seul fichier jar, y compris non seulement le fichier jar de votre projet, mais également toutes les dépendances externes en tant que "jar of jars", par exemple

<build>
    <plugins>
        <plugin>
            <groupId>com.jolira</groupId>
            <artifactId>onejar-maven-plugin</artifactId>
                <version>1.4.4</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>one-jar</goal>
                        </goals>
                    </execution>
                </executions>
        </plugin>
    </plugins>
</build>

Remarque 1: les options de configuration sont disponibles sur la page d'accueil du projet .

Note 2: Pour une raison ou une autre, le projet onejar-maven-plugin n'est pas publié sur Maven Central. Cependant, jolira.com suit le projet d'origine et le publie avec le groupId com.jolira.

matsev
la source
Est-il possible de choisir les dépendances avec lesquelles vous souhaitez empaqueter? Par exemple, si a.jar et b.jar sont des fichiers JAR externes et que je souhaite empaqueter uniquement a.jar dans le jar final, est-ce quelque chose de possible / configurable?
bianca
Je vois aussi que des trucs à un pot ont été regroupés dans le pot final. Cela a beaucoup augmenté la taille du pot final. Est-il possible de choisir des pots externes que vous avez l'intention d'inclure dans le pot final? Voici les journaux à un pot: pastebin.com/UwniQJ2X
bianca
Je ne sais pas si vous pouvez configurer ce qui est inclus ou non. Fondamentalement, one-jar inclut toutes les dépendances spécifiées par votre projet, y compris les dépendances transitives, donc oui, le fichier jar final est susceptible de devenir gros si vous avez beaucoup de dépendances. Une surcharge sera ajoutée par one-jar, afin de faire fonctionner Java avec la structure "jar of jars".
matsev
2

Une alternative est d'utiliser le maven ombre plug - in pour construire un uber-jar.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version> Your Version Here </version>
    <configuration>
            <!-- put your configurations here -->
    </configuration>
    <executions>
            <execution>
                    <phase>package</phase>
                    <goals>
                            <goal>shade</goal>
                    </goals>
            </execution>
    </executions>
</plugin>
Stanislav
la source