web-dev-qa-db-fra.com

Y compris les dépendances dans un pot avec Maven

Existe-t-il un moyen de forcer maven (2.0.9) à inclure toutes les dépendances dans un seul fichier jar?

J'ai un projet les construit dans un fichier JAR unique. Je veux que les classes des dépendances soient également copiées dans le bocal.

Mise à jour: Je sais que je ne peux pas inclure un fichier JAR dans un fichier JAR. Je cherche un moyen de décompresser les fichiers jars spécifiés comme dépendances et de conditionner les fichiers de classe dans mon fichier jar.

289
racer

Vous pouvez le faire en utilisant le plugin maven-Assembly avec le descripteur "jar-with-dependencies". Voici le morceau pertinent de l'un de nos pom.xml qui fait ceci:

  <build>
    <plugins>
      <!-- any other plugins -->
      <plugin>
        <artifactId>maven-Assembly-plugin</artifactId>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
  </build>
417
John Stauffer

Avec Maven 2, la bonne façon de faire consiste à utiliser le plug-in d'assemblage Maven2 qui possède un fichier { descripteur prédéfini } à cette fin et que vous pouvez simplement utiliser en ligne de commande. :

mvn Assembly:assembly -DdescriptorId=jar-with-dependencies

Si vous voulez rendre ce jar exécutable, ajoutez simplement la classe principale à exécuter à la configuration du plugin:

<plugin>
  <groupId>org.Apache.maven.plugins</groupId>
  <artifactId>maven-Assembly-plugin</artifactId>
  <configuration>
    <archive>
      <manifest>
        <mainClass>my.package.to.my.MainClass</mainClass>
      </manifest>
    </archive>
  </configuration>
</plugin>

Si vous souhaitez créer cet assembly dans le cadre du processus de construction normal, vous devez lier l'objectif single ou directory-single _ (l'objectif Assembly ne doit être exécuté qu'à partir de la ligne de commande). à une phase du cycle de vie (package est logique), quelque chose comme ceci:

<plugin>
  <groupId>org.Apache.maven.plugins</groupId>
  <artifactId>maven-Assembly-plugin</artifactId>
  <executions>
    <execution>
      <id>create-my-bundle</id>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
      <configuration>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        ...
      </configuration>
    </execution>
  </executions>
</plugin>

Adaptez l'élément configuration à vos besoins (par exemple, avec le contenu du manifeste tel qu'il est parlé).

123
Pascal Thivent

Si vous souhaitez créer un fichier jar exécutable, vous devez également définir la classe principale. Donc, la configuration complète devrait être.

    <plugins>
            <plugin>
                 <artifactId>maven-Assembly-plugin</artifactId>
                 <executions>
                     <execution>
                          <phase>package</phase>
                          <goals>
                              <goal>single</goal>
                          </goals>
                      </execution>
                  </executions>
                  <configuration>
                       <!-- ... -->
                       <archive>
                           <manifest>
                                 <mainClass>fully.qualified.MainClass</mainClass>
                           </manifest>
                       </archive>
                       <descriptorRefs>
                           <descriptorRef>jar-with-dependencies</descriptorRef>
                      </descriptorRefs>
                 </configuration>
         </plugin>
   </plugins>
27
abdiel

Vous pouvez utiliser le fichier jar nouvellement créé en utilisant une balise <classifier>.

<dependencies>
    <dependency>
        <groupId>your.group.id</groupId>
        <artifactId>your.artifact.id</artifactId>
        <version>1.0</version>
        <type>jar</type>
        <classifier>jar-with-dependencies</classifier>
    </dependency>
</dependencies>
14
lasantha

Il y a le plugin shade maven . Il peut être utilisé pour package et renommer dépendances (pour omettre les problèmes de dépendance sur le chemin de classe).

13
Thomas Jung

Si vous (comme moi) n’aimez pas particulièrement l’approche jar-with-dependencies décrite ci-dessus, La solution maven que je préfère est simplement de construire un projet WAR, Même si ce n’est qu’un application Java autonome que vous créez:

  1. Faites un projet-javard normal, qui construira votre fichier jar (sans les dépendances).

  2. En outre, configurez un projet de guerre maven (avec seulement un fichier src/main/webapp/WEB-INF/web.xml vide, ce qui évitera un avertissement/une erreur dans le maven-build), qui n'a jar-project comme dépendance et faites de votre jar-project un <module> sous votre projet war. (Ce projet de guerre n’est qu’une simple astuce pour envelopper toutes vos dépendances de fichiers jar dans un fichier Zip.)

  3. Construisez le projet de guerre pour produire le fichier de guerre.

  4. Dans l'étape de déploiement, renommez simplement votre fichier .war en * .Zip et décompressez-le.

Vous devriez maintenant avoir un répertoire lib (que vous pouvez déplacer où vous le souhaitez) avec votre jar et toutes les dépendances dont vous avez besoin pour exécuter votre application:

Java -cp 'path/lib/*' MainClass

(Le caractère générique dans classpath fonctionne en Java-6 ou supérieur)

Je pense que ceci est à la fois plus simple à installer dans maven (pas besoin de perdre son temps avec le plugin Assembly) et vous donne également une vue plus claire de la structure de l'application (vous verrez les numéros de version de tous les fichiers jar dépendants en clair, et éviter de tout encombrer dans un seul fichier jar).

12
Rop

http://fiji.sc/Uber-JAR fournit une excellente explication des alternatives: 

Il existe trois méthodes courantes pour construire un uber-JAR:

  1. Sans ombre. Décompressez tous les fichiers JAR, puis remballez-les dans un seul fichier JAR .
    • Pro: Fonctionne avec le chargeur de classes par défaut de Java.
    • Con: les fichiers présents dans plusieurs fichiers JAR avec le même chemin (par exemple, META-INF/services/javax.script.ScriptEngineFactory) en écraseront un un autre, entraînant un comportement fautif.
    • Outils: Assemblage Maven Plugin, Classworlds Uberjar
  2. Ombragé. Identique à non ombré, mais renommer (c'est-à-dire "ombrer") tous les paquets de toutes les dépendances .
    • Pro: Fonctionne avec le chargeur de classes par défaut de Java . Evite certains (pas tous) conflits de versions de dépendance.
    • Con: Fichiers présents dans plusieurs fichiers JAR avec le même chemin (par exemple, META-INF/services/javax.script.ScriptEngineFactory) en écraseront un un autre, entraînant un comportement fautif.
    • Outils: Plugin Maven Shade
  3. JAR de JAR. Le fichier JAR final contient les autres fichiers JAR incorporés dans .
    • Pro: évite les conflits de versions de dépendance. Tout les fichiers de ressources sont préservés.
    • Con: Doit regrouper un spécial Chargeur de classe "bootstrap" pour permettre à Java de charger des classes à partir du fichier fichiers JAR enveloppés. Le débogage des problèmes liés au chargeur de classe devient plus complexe.
    • Outils: Exportateur de fichiers JAR Eclipse, One-JAR.
9
André Valenti

Ma solution définitive sur Eclipse Luna et m2Eclipse: Chargeur de classes personnalisé (à télécharger et ajouter à votre projet, 5 classes uniquement) : http://git.Eclipse.org/c/jdt/Eclipse.jdt. ui.git/plain/org.Eclipse.jdt.ui/jar% 20in% 20jar% 20loader/org/Eclipse/jdt/internal/jarinjarloader/ ; Ce chargeur de classe est le meilleur parmi vite;

<project.mainClass>org.Eclipse.jdt.internal.jarinjarloader.JarRsrcLoader</project.mainClass> <project.realMainClass>my.Class</project.realMainClass>

Modifier dans JIJConstants "Rsrc-Class-Path" en "Class-Path"
mvn clean dependency: paquetage des dépendances de copie 
est créé un jar avec des dépendances dans le dossier lib avec un chargeur de classe thin 

<build>
    <resources>
        <resource>
            <directory>src/main/Java</directory>
            <includes>
                <include>**/*.Java</include>
                <include>**/*.properties</include>
            </includes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
            <includes>
                <include>**/*</include>
            </includes>
            <targetPath>META-INF/</targetPath>
        </resource>
        <resource>
            <directory>${project.build.directory}/dependency/</directory>
            <includes>
                <include>*.jar</include>
            </includes>
            <targetPath>lib/</targetPath>
        </resource>
    </resources>
<pluginManagement>
        <plugins>

            <plugin>
                <groupId>org.Apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>${project.mainClass}</mainClass>
                            <classpathPrefix>lib/</classpathPrefix>
                        </manifest>

                        <manifestEntries>
                            <Rsrc-Main-Class>${project.realMainClass}  </Rsrc-Main-Class>
                            <Class-Path>./</Class-Path>
                        </manifestEntries>

                    </archive>
                </configuration>
            </plugin>
<plugin>
                <groupId>org.Apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </pluginManagement>
</build>
4
Glaucio Southier
        <!-- Method 1 -->
        <!-- Copy dependency libraries jar files to a separated LIB folder -->
        <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <configuration>
                <outputDirectory>${project.build.directory}/lib</outputDirectory>
                <excludeTransitive>false</excludeTransitive> 
                <stripVersion>false</stripVersion>
            </configuration>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <!-- Add LIB folder to classPath -->
        <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                    </manifest>
                </archive>
            </configuration>
        </plugin>


        <!-- Method 2 -->
        <!-- Package all libraries classes into one runnable jar -->
        <plugin>
            <artifactId>maven-Assembly-plugin</artifactId>
            <executions>
              <execution>
                <phase>package</phase>
                <goals>
                  <goal>single</goal>
                </goals>
              </execution>
            </executions>
            <configuration>
              <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
              </descriptorRefs>
            </configuration>
        </plugin>            
3
Leslie Li

En mettant Maven de côté, vous pouvez placer des bibliothèques JAR dans le pot principal, mais vous devrez utiliser votre propre chargeur de classe.

Vérifiez ce projet: One-JAR link text

1
medopal

Ce message est peut-être un peu vieux, mais j'ai récemment eu le même problème récemment. La première solution proposée par John Stauffer est bonne, mais j'ai eu quelques problèmes en travaillant ce printemps. Les dépendances-jars du printemps que j'utilise ont des fichiers de propriétés et une déclaration xml-schemas qui partagent les mêmes chemins et noms. Bien que ces fichiers jar proviennent des mêmes versions, jar-with-dependencies maven-goal écrasait ce fichier avec le dernier fichier trouvé. 

En fin de compte, l’application n’a pas pu démarrer car les fichiers jar de printemps ne trouvaient pas les fichiers de propriétés corrects. Dans ce cas, la solution proposée par Rop a résolu mon problème.

Depuis lors, le projet Spring-Boot existe maintenant. C'est un moyen très pratique de gérer ce problème en fournissant un objectif maven qui surcharge l'objectif du paquet et fournit son propre chargeur de classe. See spring-boots Guide de référence

0
Francois Gergaud

Merci J'ai ajouté l'extrait ci-dessous dans le fichier POM.xml et le problème Mp résolu et le fichier Create Fat qui inclut tous les fichiers JAR dépendants.

<plugin>
    <artifactId>maven-Assembly-plugin</artifactId>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>single</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <descriptorRefs>
                <descriptorRef>dependencies</descriptorRef>
            </descriptorRefs>
        </configuration>
    </plugin>
</plugins>
0
Rajeev Rathor

Regardez cette réponse:

Je crée un programme d'installation qui s'exécute en tant que fichier JAR Java et doit décompresser les fichiers WAR et JAR aux emplacements appropriés dans le répertoire d'installation. Le plugin de dépendance peut être utilisé dans la phase de package avec l'objectif de copie. Il télécharge tous les fichiers du référentiel Maven (y compris les fichiers WAR) et les écrit où vous en avez besoin. J'ai changé le répertoire de sortie en $ {project.build.directory}/classes, puis le résultat final est que la tâche JAR normale inclut parfaitement mes fichiers. Je peux ensuite les extraire et les écrire dans le répertoire d'installation.

<plugin>
<groupId>org.Apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
    <execution>
        <id>getWar</id>
        <phase>package</phase>
        <goals>
            <goal>copy</goal>
        </goals>
        <configuration>
            <artifactItems>
                <artifactItem>
                    <groupId>the.group.I.use</groupId>
                    <artifactId>MyServerServer</artifactId>
                    <version>${env.Java_SERVER_REL_VER}</version>
                    <type>war</type>
                    <destFileName>myWar.war</destFileName>
                </artifactItem>
            </artifactItems>
            <outputDirectory>${project.build.directory}/classes</outputDirectory>
        </configuration>
    </execution>
</executions>

0
millebi