web-dev-qa-db-fra.com

Comment créer un fichier JAR exécutable avec des dépendances à l'aide de Maven?

Je souhaite conditionner mon projet dans un fichier JAR exécutable unique pour la distribution.

Comment créer un package de projet Maven avec tous les fichiers JAR de dépendance dans mon fichier JAR de sortie?

2221
soemirno
<build>
  <plugins>
    <plugin>
      <artifactId>maven-Assembly-plugin</artifactId>
      <configuration>
        <archive>
          <manifest>
            <mainClass>fully.qualified.MainClass</mainClass>
          </manifest>
        </archive>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
      </configuration>
    </plugin>
  </plugins>
</build>

et vous le courez avec

mvn clean compile Assembly:single

L'objectif de compilation doit être ajouté avant Assembly: unique ou sinon, le code de votre propre projet n'est pas inclus.

Voir plus de détails dans les commentaires.


Généralement, cet objectif est lié à une phase de construction à exécuter automatiquement. Cela garantit que le fichier JAR est créé lors de l'exécution de mvn install ou du déploiement/de la publication.

<plugin>
  <artifactId>maven-Assembly-plugin</artifactId>
  <configuration>
    <archive>
      <manifest>
        <mainClass>fully.qualified.MainClass</mainClass>
      </manifest>
    </archive>
    <descriptorRefs>
      <descriptorRef>jar-with-dependencies</descriptorRef>
    </descriptorRefs>
  </configuration>
  <executions>
    <execution>
      <id>make-Assembly</id> <!-- this is used for inheritance merges -->
      <phase>package</phase> <!-- bind to the packaging phase -->
      <goals>
        <goal>single</goal>
      </goals>
    </execution>
  </executions>
</plugin>
2176
IAdapter

Vous pouvez utiliser le plugin dependency pour générer toutes les dépendances dans un répertoire distinct avant la phase de package, puis l'inclure dans le chemin d'accès aux classes du manifeste:

<plugin>
    <groupId>org.Apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/lib</outputDirectory>
                <overWriteReleases>false</overWriteReleases>
                <overWriteSnapshots>false</overWriteSnapshots>
                <overWriteIfNewer>true</overWriteIfNewer>
            </configuration>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.Apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <classpathPrefix>lib/</classpathPrefix>
                <mainClass>theMainClass</mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin>

Vous pouvez également utiliser ${project.build.directory}/classes/lib comme OutputDirectory pour intégrer tous les fichiers JAR dans le fichier JAR principal. Vous devrez ensuite ajouter un code de chargement de classe personnalisé pour charger les fichiers JAR.

326
André Aronsen

J'ai blogué à propos de différentes façons de le faire.

Voir Fichier exécutable avec Apache Maven (WordPress)

ou executable-jar-with-maven-example (GitHub)

Remarques

Ces avantages et inconvénients sont fournis par Stephan .


Pour un déploiement manuel

  • Avantages
  • Les inconvénients
    • Les dépendances sont hors du pot final.

Copier les dépendances dans un répertoire spécifique

<plugin>
  <groupId>org.Apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <executions>
    <execution>
      <id>copy-dependencies</id>
      <phase>prepare-package</phase>
      <goals>
        <goal>copy-dependencies</goal>
      </goals>
      <configuration>
        <outputDirectory>${project.build.directory}/${project.build.finalName}.lib</outputDirectory>
      </configuration>
    </execution>
  </executions>
</plugin>

Rendre le fichier exécutable et le classpath conscients

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

À ce stade, la jar est réellement exécutable avec des éléments externes de chemin de classe.

$ Java -jar target/${project.build.finalName}.jar

Faire des archives déployables

Le fichier jar est uniquement exécutable avec le répertoire frère ...lib/. Nous devons créer des archives à déployer avec le répertoire et son contenu.

<plugin>
  <groupId>org.Apache.maven.plugins</groupId>
  <artifactId>maven-antrun-plugin</artifactId>
  <executions>
    <execution>
      <id>antrun-archive</id>
      <phase>package</phase>
      <goals>
        <goal>run</goal>
      </goals>
      <configuration>
        <target>
          <property name="final.name" value="${project.build.directory}/${project.build.finalName}"/>
          <property name="archive.includes" value="${project.build.finalName}.${project.packaging} ${project.build.finalName}.lib/*"/>
          <property name="tar.destfile" value="${final.name}.tar"/>
          <Zip basedir="${project.build.directory}" destfile="${final.name}.Zip" includes="${archive.includes}" />
          <tar basedir="${project.build.directory}" destfile="${tar.destfile}" includes="${archive.includes}" />
          <gzip src="${tar.destfile}" destfile="${tar.destfile}.gz" />
          <bzip2 src="${tar.destfile}" destfile="${tar.destfile}.bz2" />
        </target>
      </configuration>
    </execution>
  </executions>
</plugin>

Maintenant vous avez target/${project.build.finalName}.(Zip|tar|tar.bz2|tar.gz) qui contient chacun les jar et lib/*.


Apache Maven Assembly Plugin

  • Avantages
  • Les inconvénients
    • Pas de support de transfert de classe (utilisez maven-shade-plugin si le transfert de classe est nécessaire).
<plugin>
  <groupId>org.Apache.maven.plugins</groupId>
  <artifactId>maven-Assembly-plugin</artifactId>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
      <configuration>
        <archive>
          <manifest>
            <mainClass>${fully.qualified.main.class}</mainClass>
          </manifest>
        </archive>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
      </configuration>
    </execution>
  </executions>
</plugin>

Vous avez target/${project.bulid.finalName}-jar-with-dependencies.jar.


Apache Maven Shade Plugin

  • Avantages
  • Les inconvénients
<plugin>
  <groupId>org.Apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <executions>
    <execution>
      <goals>
        <goal>shade</goal>
      </goals>
      <configuration>
        <shadedArtifactAttached>true</shadedArtifactAttached>
        <transformers>
          <transformer implementation="org.Apache.maven.plugins.shade.resource.ManifestResourceTransformer">
            <mainClass>${fully.qualified.main.class}</mainClass>
          </transformer>
        </transformers>
      </configuration>
    </execution>
  </executions>
</plugin>

Vous avez target/${project.build.finalName}-shaded.jar.


onejar-maven-plugin

  • Avantages
  • Les inconvénients
    • Pas activement soutenu depuis 2012.
<plugin>
  <!--groupId>org.dstovall</groupId--> <!-- not available on the central -->
  <groupId>com.jolira</groupId>
  <artifactId>onejar-maven-plugin</artifactId>
  <executions>
    <execution>
      <configuration>
        <mainClass>${fully.qualified.main.class}</mainClass>
        <attachToBuild>true</attachToBuild>
        <!-- https://code.google.com/p/onejar-maven-plugin/issues/detail?id=8 -->
        <!--classifier>onejar</classifier-->
        <filename>${project.build.finalName}-onejar.${project.packaging}</filename>
      </configuration>
      <goals>
        <goal>one-jar</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Spring Boot Maven Plugin

  • Avantages
  • Les inconvénients
    • Ajoutez les classes potentiellement inutiles liées à Spring et Spring Boot.
<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <executions>
    <execution>
      <goals>
        <goal>repackage</goal>
      </goals>
      <configuration>
        <classifier>spring-boot</classifier>
        <mainClass>${fully.qualified.main.class}</mainClass>
      </configuration>
    </execution>
  </executions>
</plugin>

Vous avez target/${project.bulid.finalName}-spring-boot.jar.

191
Jin Kwon

En prenant la réponse de Unanswered et en la reformatant, nous avons:

<build>
    <plugins>
        <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>
        <plugin>
            <artifactId>maven-Assembly-plugin</artifactId>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
        </plugin>
    </plugins>
</build>

Ensuite, je recommanderais de faire de cela une partie naturelle de votre construction, plutôt que d’appeler explicitement. Pour en faire une partie intégrante de votre construction, ajoutez ce plugin à votre pom.xml et associez-le à l'événement package cycle de vie. Cependant, vous devez appeler l'objectif Assembly:single si vous le placez dans votre pom.xml, tandis que vous appelez 'Assembly: assembly' si vous l'exécutez manuellement à partir de la ligne de commande.

<project>
  [...]
  <build>
      <plugins>
          <plugin>
              <artifactId>maven-Assembly-plugin</artifactId>
              <configuration>
                  <archive>
                      <manifest>
                          <addClasspath>true</addClasspath>
                          <mainClass>fully.qualified.MainClass</mainClass>
                      </manifest>
                  </archive>
                  <descriptorRefs>
                      <descriptorRef>jar-with-dependencies</descriptorRef>
                  </descriptorRefs>
              </configuration>
              <executions>
                  <execution>
                      <id>make-my-jar-with-dependencies</id>
                      <phase>package</phase>
                      <goals>
                          <goal>single</goal>
                      </goals>
                  </execution>
              </executions>
          </plugin>
      [...]
      </plugins>
    [...]
  </build>
</project>
133
Matthew McCullough

Utilisez le plugin maven-shade-package pour regrouper toutes les dépendances dans un seul uber-jar. Il peut également être utilisé pour créer un fichier jar exécutable en spécifiant la classe principale. Après avoir essayé d’utiliser maven-Assembly et maven-jar, j’ai trouvé que ce plug-in répondait le mieux à mes besoins.

J'ai trouvé ce plugin particulièrement utile car il fusionne le contenu de fichiers spécifiques au lieu de les écraser. Cela est nécessaire lorsque des fichiers de ressources portent le même nom dans les fichiers JAR et que le plug-in tente de conditionner tous les fichiers de ressources.

Voir exemple ci-dessous

      <plugins>
    <!-- This plugin provides the capability to package the artifact in an uber-jar, including its dependencies and to shade - i.e. rename - the packages of some of the dependencies. -->
        <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>1.4</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <artifactSet>
                        <!-- signed jars-->
                            <excludes>
                                <exclude>bouncycastle:bcprov-jdk15</exclude>
                            </excludes>
                        </artifactSet>

                         <transformers>
                            <transformer
                                implementation="org.Apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <!-- Main class -->
                                <mainClass>com.main.MyMainClass</mainClass>
                            </transformer>
                            <!-- Use resource transformers to prevent file overwrites -->
                            <transformer 
                                 implementation="org.Apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>properties.properties</resource>
                            </transformer>
                            <transformer
                                implementation="org.Apache.maven.plugins.shade.resource.XmlAppendingTransformer">
                                <resource>applicationContext.xml</resource>
                            </transformer>
                            <transformer
                                implementation="org.Apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>META-INF/cxf/cxf.extension</resource>
                            </transformer>
                            <transformer
                                implementation="org.Apache.maven.plugins.shade.resource.XmlAppendingTransformer">
                                <resource>META-INF/cxf/bus-extensions.xml</resource>
                            </transformer>
                     </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>

    </plugins>
96
Vijay Katam

Longtemps utilisé le maven Assembly plugin , mais je n’ai pas trouvé de solution au problème avec "already added, skipping" . Maintenant, j'utilise un autre plugin - ( onejar-maven-plugin . Exemple ci-dessous (_mvn package_ build jar):

_<plugin>
    <groupId>org.dstovall</groupId>
    <artifactId>onejar-maven-plugin</artifactId>
    <version>1.3.0</version>
    <executions>
        <execution>
            <configuration>
                <mainClass>com.company.MainClass</mainClass>
            </configuration>
            <goals>
                <goal>one-jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>
_

Vous devez ajouter un référentiel pour ce plugin:

_<pluginRepositories>
    <pluginRepository>
        <id>onejar-maven-plugin.googlecode.com</id>
        <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
    </pluginRepository>
</pluginRepositories>
_
19
marioosh

Vous pouvez utiliser le plugin maven-dependency, mais la question était de savoir comment créer un fichier JAR exécutable. Cela nécessite la modification suivante de la réponse de Matthew Franglen (au fait, l'utilisation du plug-in de dépendance prend plus de temps à compiler quand on part d'une cible propre):

<build>
    <plugins>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>fully.qualified.MainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>unpack-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>unpack-dependencies</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
    <resources>
        <resource>
            <directory>${basedir}/target/dependency</directory>
        </resource>
    </resources>
</build>
17
user189057

Une autre option si vous souhaitez vraiment reconditionner le contenu des autres fichiers JAR dans votre fichier JAR résultant est le plug-in Maven Assembly . Il décompresse puis remballe le tout dans un répertoire via <unpack>true</unpack>. Ensuite, vous auriez un deuxième passage qui le construirait dans un JAR massif.

ne autre option est le plugin OneJar . Ceci effectue les actions de reconditionnement ci-dessus en une seule étape.

15
Matthew McCullough

Vous pouvez ajouter ce qui suit à votre pom.xml:

<build>
<defaultGoal>install</defaultGoal>
<plugins>
  <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
      <source>1.6</source>
      <target>1.6</target>
    </configuration>
  </plugin>
  <plugin>
    <groupId>org.Apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.3.1</version>
    <configuration>
      <archive>
        <manifest>
          <addClasspath>true</addClasspath>
          <mainClass>com.mycompany.package.MainClass</mainClass>
        </manifest>
      </archive>
    </configuration>
  </plugin>
  <plugin>
    <artifactId>maven-Assembly-plugin</artifactId>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
      <archive>
        <manifest>
          <mainClass>com.mycompany.package.MainClass</mainClass>
        </manifest>
      </archive>
    </configuration>
    <executions>
      <execution>
        <id>make-my-jar-with-dependencies</id>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
      </execution>
    </executions>
  </plugin>
</plugins>
</build>

Ensuite, vous devez passer par la console au répertoire où se trouve le fichier pom.xml. Ensuite, vous devez exécuter mvn Assembly: single et ensuite votre fichier JAR exécutable avec dépendances sera construit, espérons-le. Vous pouvez le vérifier lorsque vous passez au répertoire de sortie (cible) avec cd ./target et démarrez votre jar avec une commande similaire à Java -jar mavenproject1-1.0-SNAPSHOT-jar-with -dependencies.jar.

J'ai testé cela avec Apache Maven 3.0..

13
Benny Neugebauer

J'ai parcouru chacune de ces réponses en cherchant à créer un gros fichier jar exécutable contenant toutes les dépendances et aucune d'entre elles ne fonctionnait correctement. La réponse est le plugin nuance, il est très facile et simple.

    <plugin>
      <groupId>org.Apache.maven.plugins</groupId>
      <artifactId>maven-shade-plugin</artifactId>
      <version>2.3</version>
      <executions>
         <!-- Run shade goal on package phase -->
        <execution>
        <phase>package</phase>
        <goals>
            <goal>shade</goal>
        </goals>
        <configuration>
          <transformers>
             <transformer implementation="org.Apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                <mainClass>path.to.MainClass</mainClass>
             </transformer>
          </transformers>
        </configuration>
          </execution>
      </executions>
    </plugin>

Sachez que vos dépendances doivent avoir une portée de compilation ou d’exécution pour que cela fonctionne correctement.

Cet exemple provient de mkyong.com

11
dsutherland

Vous pouvez combiner les maven-shade-plugin et maven-jar-plugin.

  • Le maven-shade-plugin regroupe vos classes et toutes les dépendances dans un seul fichier jar.
  • Configurez le maven-jar-plugin pour spécifier la classe principale de votre fichier jar exécutable (voir Configuration du chemin de classe , chapitre "Créer le fichier jar exécutable").

Exemple de configuration POM pour maven-jar-plugin:

        <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>com.example.MyMainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>

Enfin, créez le fichier jar exécutable en appelant:

mvn clean package shade:shade
11
Oliver

Vous pouvez utiliser le plugin maven-shade pour construire un pot comme ci-dessous

<plugin>
    <groupId>org.Apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
        </execution>
    </executions>
</plugin>
10
Minisha

Voici un plugin jar exécutable pour Maven que nous utilisons chez Credit Karma. Il crée un fichier jar contenant un classloader capable de charger des classes à partir de fichiers jar imbriqués. Cela vous permet d'avoir le même chemin d'accès aux classes dans dev et prod et de conserver toutes les classes dans un seul fichier jar signé.

https://github.com/creditkarma/maven-exec-jar-plugin

Et voici un article de blog avec des détails sur le plugin et pourquoi nous l'avons créé: https://engineering.creditkarma.com/general-engineering/new-executable-jar-plugin-available-Apache-maven/ =

9
jchavannes

Ken Liu a raison à mon avis. Le plugin maven dependency vous permet de développer toutes les dépendances, que vous pouvez ensuite traiter en tant que ressources. Cela vous permet de les inclure dans l'artefact main. L'utilisation du plug-in Assembly crée un artefact secondaire qui peut être difficile à modifier - dans mon cas, je voulais ajouter des entrées de manifeste personnalisées. Mon pom a fini comme:

<project>
 ...
 <build>
  <plugins>
   <plugin>
    <groupId>org.Apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
     <execution>
      <id>unpack-dependencies</id>
      <phase>package</phase>
      <goals>
       <goal>unpack-dependencies</goal>
      </goals>
     </execution>
    </executions>
   </plugin>
  </plugins>
  ...
  <resources>
   <resource>
    <directory>${basedir}/target/dependency</directory>
    <targetPath>/</targetPath>
   </resource>
  </resources>
 </build>
 ...
</project>
9
Matthew Franglen

Ça devrait être comme ça:

<plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>unpack-dependencies</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>unpack-dependencies</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Le décompactage doit être en phase de génération de ressources car, s'il est en phase de package, il ne sera pas inclus en tant que ressources. Essayez le paquet propre et vous verrez.

9
kac-ani

Utilisez plug-in onejar pour le construire en tant que fichier jar exécutable contenant tous les fichiers jar de dépendance qu'il contient. Cela a résolu mon problème qui était semblable à celui-ci. Lorsque le plug-in Assembly était utilisé, il décompressait tous les fichiers jar de dépendance dans un dossier source et les reconditionnait comme un fichier jar. Toutes les implémentations similaires que j'avais dans mon code étaient écrasées et portaient les mêmes noms de classes. onejar est une solution facile ici.

7
AmilaR

Problème de localisation du fichier Assembly partagé avec maven-Assembly-plugin-2.2.1?

Essayez d'utiliser le paramètre de configuration descriptorId au lieu des paramètres descriptors/descriptor ou descriptorRefs/descriptorRef.

Aucun d'entre eux ne fait ce dont vous avez besoin: recherchez le fichier sur classpath. Bien sûr, vous devez ajouter le paquet contenant l'assembly partagé sur le chemin d'accès aux classes de maven-Assembly-plugin (voir ci-dessous). Si vous utilisez Maven 2.x (et non Maven 3.x), vous devrez peut-être ajouter cette dépendance dans pom.xml, le parent le plus élevé, dans la section pluginManagement.

Voir this pour plus de détails.

Classe: org.Apache.maven.plugin.Assembly.io.DefaultAssemblyReader

Exemple:

        <!-- Use the Assembly plugin to create a Zip file of all our dependencies. -->
        <plugin>
            <artifactId>maven-Assembly-plugin</artifactId>
            <version>2.2.1</version>
            <executions>
                <execution>
                    <id>make-Assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                    <configuration>
                        <descriptorId>Assembly-Zip-for-wid</descriptorId>
                    </configuration>
                </execution>
            </executions>
            <dependencies>
                <dependency>
                    <groupId>cz.ness.ct.ip.assemblies</groupId>
                    <artifactId>TEST_SharedAssemblyDescriptor</artifactId>
                    <version>1.0.0-SNAPSHOT</version>
                </dependency>
            </dependencies>
        </plugin>
7

Je ne répondrai pas directement à la question, car d'autres l'ont déjà fait auparavant, mais je me demande vraiment si c'est une bonne idée d'intégrer toutes les dépendances dans le pot du projet lui-même.

Je vois le point (facilité de déploiement/utilisation) mais cela dépend du cas d'utilisation de votre projet (et il peut y avoir des alternatives (voir ci-dessous)).

Si vous l'utilisez entièrement, pourquoi pas.

Toutefois, si vous utilisez votre projet dans d'autres contextes (comme dans une application Web ou dans un dossier contenant d'autres fichiers jar), vous pouvez avoir des doublons dans votre classpath (ceux du dossier, ceux du fichier). Peut-être pas une offre mais je l’évite généralement.

Une bonne alternative:

  • déployez votre application en tant que .Zip/.war: l'archive contient le jar de votre projet et tous les jar dépendants;
  • utilisez un mécanisme de chargeur de classe dynamique (voir Spring, ou vous pouvez le faire vous-même) pour avoir un seul point d’entrée dans votre projet (une seule classe à démarrer - voir le mécanisme Manifest sur une autre réponse), ce qui ajoutera (dynamiquement) au classpath actuel tous les autres bocaux nécessaires.

Comme ceci, avec à la fin juste un manifeste et un "classloader dynamique spécial", vous pouvez commencer votre projet avec:

Java -jar ProjectMainJar.jar com.stackoverflow.projectName.MainDynamicClassLoaderClass
5
SRG

Pour résoudre ce problème, nous allons utiliser le plug-in Maven Assembly, qui créera le fichier JAR avec ses fichiers JAR de dépendance dans un fichier JAR exécutable unique. Ajoutez simplement la configuration du plugin ci-dessous dans votre fichier pom.xml.

<build>
   <pluginManagement>
      <plugins>
         <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-Assembly-plugin</artifactId>
            <configuration>
               <archive>
                  <manifest>
                     <addClasspath>true</addClasspath>
                     <mainClass>com.your.package.MainClass</mainClass>
                  </manifest>
               </archive>
               <descriptorRefs>
                  <descriptorRef>jar-with-dependencies</descriptorRef>
               </descriptorRefs>
            </configuration>
            <executions>
               <execution>
                  <id>make-my-jar-with-dependencies</id>
                  <phase>package</phase>
                  <goals>
                     <goal>single</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </pluginManagement>
</build>

Ceci fait, n’oubliez pas d’exécuter l’outil MAVEN avec cette commande, mvn clean compile Assembly: single

http://jkoder.com/maven-creating-a-jar-together-with-its-dependency-jars-into-a-single-executable-jar-file/

4
Anoop Rai

Pour créer un fichier JAR exécutable à partir de la ligne de commande, exécutez la commande ci-dessous à partir du chemin du projet:

mvn Assembly:assembly
3
Mayank

J'ai comparé les plugins d'arbre mentionnés dans ce post. J'ai généré 2 pots et un répertoire avec tous les pots. J'ai comparé les résultats et le maven-shade-plugin est sans aucun doute le meilleur. Mon défi était que je devais fusionner plusieurs ressources printanières, ainsi que des services jax-rs et JDBC. Ils ont tous été fusionnés correctement par le plugin shade en comparaison avec le plugin maven-Assembly-plugin. Dans ce cas, le ressort échouera à moins que vous ne les copiez dans votre propre dossier de ressources et que vous les fusionniez manuellement une fois. Les deux plugins génèrent le bon arbre de dépendance. J'ai eu plusieurs portées comme test, fournir, compiler, etc. le test et fourni ont été ignorés par les deux plugins. Ils ont tous deux produit le même manifeste, mais j'ai pu consolider les licences avec le plug-in shaden à l'aide de leur transformateur. Bien sûr, avec le plugin maven-dependency-plugin, vous n'avez pas ces problèmes, car les fichiers jar ne sont pas extraits. Mais comme certains l’ont souligné, vous devez emporter un fichier supplémentaire pour fonctionner correctement. Voici un extrait du pom.xml

            <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${project.build.directory}/lib</outputDirectory>
                        <includeScope>compile</includeScope>
                        <excludeTransitive>true</excludeTransitive>
                        <overWriteReleases>false</overWriteReleases>
                        <overWriteSnapshots>false</overWriteSnapshots>
                        <overWriteIfNewer>true</overWriteIfNewer>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-Assembly-plugin</artifactId>
            <version>2.6</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>com.rbccm.itf.cdd.poller.landingzone.LandingZonePoller</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>make-my-jar-with-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.4.3</version>
            <configuration>
                <shadedArtifactAttached>false</shadedArtifactAttached>
                <keepDependenciesWithProvidedScope>false</keepDependenciesWithProvidedScope>
                <transformers>
                    <transformer implementation="org.Apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/services/javax.ws.rs.ext.Providers</resource>
                    </transformer>
                    <transformer implementation="org.Apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.factories</resource>
                    </transformer>
                    <transformer implementation="org.Apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.handlers</resource>
                    </transformer>
                    <transformer implementation="org.Apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.schemas</resource>
                    </transformer>
                    <transformer implementation="org.Apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.tooling</resource>
                    </transformer>
                    <transformer implementation="org.Apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                    <transformer implementation="org.Apache.maven.plugins.shade.resource.ManifestResourceTransformer"/>
                    <transformer implementation="org.Apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer">
                    </transformer>
                </transformers>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
3
Fabio

C'est le meilleur moyen que j'ai trouvé:

  <plugin>
    <groupId>org.Apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.4</version>
    <configuration>
      <archive>
        <manifest>
        <addClasspath>true</addClasspath>
        <mainClass>com.myDomain.etc.MainClassName</mainClass>
        <classpathPrefix>dependency-jars/</classpathPrefix>
        </manifest>
      </archive>
    </configuration>
  </plugin>
  <plugin>
    <groupId>org.Apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.5.1</version>
    <executions>
      <execution>
        <id>copy-dependencies</id>
        <phase>package</phase>
        <goals>
            <goal>copy-dependencies</goal>
        </goals>
        <configuration>
            <outputDirectory>
               ${project.build.directory}/dependency-jars/
            </outputDirectory>
        </configuration>
      </execution>
    </executions>
  </plugin>

Avec cette configuration, toutes les dépendances seront situées dans /dependency-jars. Mon application n'a pas de classe Main, mais seulement de celles du contexte, mais l'une de mes dépendances possède une classe Main (com.myDomain.etc.MainClassName) qui démarre le serveur JMX et reçoit un start ou un paramètre stop. Donc, avec cela, j'ai pu démarrer mon application comme ceci:

Java -jar ./lib/TestApp-1.0-SNAPSHOT.jar start

J'attends que ce soit utile pour vous tous.

2
EliuX

Quelque chose qui a fonctionné pour moi était:

  <plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
      <execution>
        <id>unpack-dependencies</id>
        <phase>prepare-package</phase>
        <goals>
          <goal>unpack-dependencies</goal>
        </goals>
        <configuration>
          <outputDirectory>${project.build.directory}/classes</outputDirectory>
        </configuration>
      </execution>

    </executions>
  </plugin>


  <plugin>
    <groupId>org.Apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <executions>
      <execution>
        <id>unpack-dependencies</id>
        <phase>package</phase>
      </execution>
    </executions>
    <configuration>
      <archive>
        <manifest>
          <addClasspath>true</addClasspath>
          <classpathPrefix>lib/</classpathPrefix>
          <mainClass>SimpleKeyLogger</mainClass>
        </manifest>
      </archive>
    </configuration>
  </plugin>

J'ai eu un cas extraordinaire parce que ma dépendance était le premier système:

<dependency>
  ..
  <scope>system</scope>
  <systemPath>${project.basedir}/lib/myjar.jar</systemPath>
</dependency>

J'ai changé le code fourni par @ user189057 avec les modifications suivantes: 1) le plugin maven-dependency est exécuté dans la phase 2 de préparation du paquet, je suis en train d'extraire directement les classes non empaquetées en objectifs et classes

2
fascynacja

Vous pouvez également utiliser ce plug-in, il est très bon et je l’utilise pour emballer mes bocaux http://sonatype.github.io/jarjar-maven-plugin/

2
Adelin

Ajouter à pom.xml:

  <dependency>
            <groupId>com.jolira</groupId>
            <artifactId>onejar-maven-plugin</artifactId>
            <version>1.4.4</version>
  </dependency>

et

<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>

C'est ça. Le prochain paquet mvn créera également un gros fichier jar, y compris tous les fichiers jar de dépendance.

2
Aydin K.

Il existe déjà des millions de réponses, je voulais ajouter que vous n'avez pas besoin de <mainClass> si vous n'avez pas besoin d'ajouter entryPoint à votre application. Par exemple, les API ne doivent pas nécessairement avoir la méthode main.

maven plugin config

  <build>
    <finalName>log-enrichment</finalName>
    <plugins>
      <plugin>
        <artifactId>maven-Assembly-plugin</artifactId>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
  </build>

construire

mvn clean compile Assembly:single

vérifier

ll target/
total 35100
drwxrwx--- 1 root vboxsf     4096 Sep 29 16:25 ./
drwxrwx--- 1 root vboxsf     4096 Sep 29 16:25 ../
drwxrwx--- 1 root vboxsf        0 Sep 29 16:08 archive-tmp/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 classes/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 generated-sources/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 generated-test-sources/
-rwxrwx--- 1 root vboxsf 35929841 Sep 29 16:10 log-enrichment-jar-with-dependencies.jar*
drwxrwx--- 1 root vboxsf        0 Sep 29 16:08 maven-status/
2
prayagupd

J'ai essayé la réponse la plus votée ici, et j'ai réussi à faire fonctionner le bocal. Mais le programme n'a pas fonctionné correctement. Je ne sais pas quelle était la raison. Lorsque j'essaie d'exécuter à partir de Eclipse, j'obtiens un résultat différent, mais lorsque j'exécute le fichier jar à partir de la ligne de commande, j'obtiens un résultat différent (il se bloque avec une erreur d'exécution spécifique au programme).

J'avais une exigence similaire à celle de l'OP, simplement que j'avais trop de dépendances (Maven) pour mon projet. Heureusement, la seule solution qui a fonctionné pour moi était d'utiliser Eclipse. Très simple et très simple. Ce n'est pas une solution au PO mais une solution pour quelqu'un qui a une exigence similaire mais qui possède de nombreuses dépendances Maven,

1) Faites un clic droit sur le dossier de votre projet (dans Eclipse) et sélectionnez Export

2) Puis sélectionnez Java -> Runnable Jar

3) Il vous sera demandé de choisir l'emplacement du fichier jar

4) Enfin, sélectionnez la classe contenant la méthode Main que vous voulez exécuter, choisissez Package dependencies with the Jar file et cliquez _ Finish.

2
Rocky Inde

Pour ceux qui recherchent des options pour exclure des dépendances spécifiques de uber-jar, voici une solution qui a fonctionné pour moi:

<project...>
<dependencies>
        <dependency>
            <groupId>org.Apache.spark</groupId>
            <artifactId>spark-core_2.11</artifactId>
            <version>1.6.1</version>
            <scope>provided</scope> <=============
        </dependency>
</dependencies>
<build>
        <plugins>
            <plugin>
                <artifactId>maven-Assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>...</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-Assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Donc, ce n'est pas une configuration du plugin mvn-Assembly mais une propriété de la dépendance.

2
Paul Bormans

Cela pourrait aussi être une option, vous pourrez construire votre fichier jar

<build>
    <plugins>
        <plugin>
            <!-- Build an executable JAR -->
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                        <mainClass>WordListDriver</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>
2
salmanbw

Le plugin maven-Assembly a très bien fonctionné pour moi. J'ai passé des heures avec le plugin maven-dependency et je ne pouvais pas le faire fonctionner. La raison principale était que je devais définir explicitement dans la section de configuration les éléments d'artefact à inclure, comme décrit dans la documentation . Il y a un exemple ici pour les cas où vous voulez l'utiliser comme: mvn dependency:copy, où aucun artefactItems n'est inclus mais cela ne fonctionne pas.

1
Chris

Cet article de blog montre une autre approche en combinant les plugins maven-jar et maven-Assembly. Avec la configuration d'assembly xml de l'article de blog, il est également possible de contrôler si les dépendances seront développées ou simplement rassemblées dans un dossier et référencées par une entrée de chemin de classe dans le manifeste:

La solution idéale consiste à inclure les fichiers JAR dans un dossier lib et que le fichier manifest.mf du fichier JAR principal inclue tous les fichiers JAR du classpath.

Et exactement celui-ci est décrit ici: https://caffebig.wordpress.com/2013/04/05/executable-jar-file-with-dependent-jars-using-maven/

1
Jan Ziegler
<build>
    <plugins>
        <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-Assembly-plugin</artifactId>
            <version>2.4.1</version>
            <configuration>
                <!-- get all project dependencies -->
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>make-Assembly</id>
                    <!-- bind to the packaging phase -->
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
0
Shang Gao