java - with - maven-jar-plugin




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

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?


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


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 Mainclasse, mais seulement des contextes, mais l'une de mes dépendances a une Mainclasse ( com.myDomain.etc.MainClassName) qui démarre le serveur JMX et reçoit un startou un stopparamètre. 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.


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

Voir Jar 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, le fichier jar est réellement exécutable avec des éléments de chemin de classe externes.

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

Créer 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>

Vous avez maintenant la target/${project.build.finalName}.(zip|tar|tar.bz2|tar.gz) contenant chacune le 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 .


J'ai essayé la réponse la plus votée ici, et j'ai pu obtenir le pot qui fonctionne. Mais le programme n'a pas fonctionné correctement. Je ne sais pas quelle était la raison. Lorsque j'essaie d'exécuter à partir d' 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 l’utilisation d’ 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) Ensuite, sélectionnez Java -> Runnable Jar

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

4) Enfin, sélectionnez la classe Package dependencies with the Jar file méthode Main que vous souhaitez exécuter, choisissez Package dependencies with the Jar file puis cliquez sur Finish


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 complètement, pourquoi pas.

Mais 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..projectName.MainDynamicClassLoaderClass

Ken Liu a raison à mon avis. Le plugin maven dependency vous permet d’étendre toutes les dépendances, que vous pouvez ensuite traiter en tant que ressources. Cela vous permet de les inclure dans l'artefact principal . L'utilisation du plugin d'assemblage 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>

Longtemps utilisé le plugin d'assemblage maven , 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>

Problème de localisation du fichier d'assemblage 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.

Ni l'un ni l'autre 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>

Si vous voulez si de la ligne de commande elle-même. Il suffit d’exécuter la commande ci-dessous à partir du chemin du projet

assemblage MVN: assemblage


Utilisez le plugin 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 d'assembly était utilisé, il décompressait tous les fichiers jar de dépendance dans le 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.


Voici un plugin jar exécutable pour Maven que nous utilisons chez Credit Karma. Il crée un fichier jar de fichiers jar avec un chargeur de classe capable de charger des classes à partir de fichiers jar imbriqués. Cela vous permet d’avoir le même chemin de classe 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/



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

  • Le maven-shade-plugin contient 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 classpath , chapitre "Créer un 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

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 jar principal, mais vous devrez ensuite ajouter du code de chargement de classe personnalisé pour charger les jar.


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>

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 tout. Le prochain paquet mvn créera également un gros fichier jar, y compris tous les fichiers jar de dépendance.


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>

Il ne s’agit donc pas d’une configuration du plug-in mvn-assembly-plugin mais d’une propriété de la dépendance.


Il existe déjà des millions de réponses. Je voulais ajouter que <mainClass>vous n’avez pas besoin d’ajouter entryPoint à votre application. Par exemple, les API peuvent ne pas avoir nécessairement de mainméthode.

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/

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 de l'artefact à inclure, comme il est décrit dans la documentation . Il y a un exemple ici pour les cas où vous voulez l'utiliser comme:, mvn dependency:copyoù aucun artefactItems n'est inclus mais cela ne fonctionne pas.


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 de lancer 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/





executable-jar