126 votes

Comment mettre tous les fichiers JAR requis dans un dossier de bibliothèque à l'intérieur du fichier JAR final avec Maven ?

J'utilise Maven dans mon application autonome, et je veux empaqueter toutes les dépendances dans mon fichier JAR à l'intérieur d'un dossier de bibliothèque, comme mentionné dans l'une des réponses ici :

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

Je veux que mon fichier JAR final ait un dossier de bibliothèque contenant les dépendances sous forme de fichiers JAR, et non pas comme ce que le fichier maven-shade-plugin qui place les dépendances sous forme de dossiers, comme la hiérarchie Maven dans le dossier .m2.

En fait, la configuration actuelle fait ce que je veux, mais j'ai un problème avec le chargement des fichiers JAR lorsque je lance l'application. Je n'arrive pas à charger les classes.

Voici ma configuration :

<plugins>

    <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}/classes/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>com.myapp.MainClass</mainClass>
                </manifest>
            </archive>
        </configuration>
    </plugin>

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
            <source>1.6</source>
            <target>1.6</target>
        </configuration>
    </plugin>

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
            <execution>
                <id>install</id>
                <phase>install</phase>
                <goals>
                    <goal>sources</goal>
                </goals>
            </execution>
        </executions>
    </plugin>

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>2.5</version>
        <configuration>
            <encoding>UTF-8</encoding>
        </configuration>
    </plugin>

</plugins>

Le projet s'exécute correctement à partir d'Eclipse, et les fichiers JAR sont placés dans le dossier de la bibliothèque à l'intérieur de mon fichier JAR final comme je le souhaite, mais lorsque je lance le fichier JAR final à partir du dossier cible, j'obtiens toujours les résultats suivants ClassNotFoundException :

Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/context/ApplicationContext
Caused by: java.lang.ClassNotFoundException: org.springframework.context.ApplicationContext
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: com.myapp.MainClass. Program will exit.

Comment puis-je corriger cette exception ?

94voto

Rya Points 60

Voici ma solution. Testez-la si elle fonctionne pour vous :

<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}/classes/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>test.org.Cliente</mainClass> -->
            </manifest>
            <manifestEntries>
                <Class-Path>lib/</Class-Path>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>

Le premier plugin place toutes les dépendances dans le dossier target/classes/lib, et le second inclut le dossier de la bibliothèque dans le fichier JAR final, et configure la fonction Manifest.mf fichier.

Mais vous devrez alors ajouter un code de chargement de classe personnalisé pour charger les fichiers JAR.

Ou, pour éviter le classloading personnalisé, vous pouvez utiliser "${project.build.directory}/lib, mais dans ce cas, vous n'avez pas de dépendances dans le fichier JAR final, ce qui va à l'encontre du but recherché.

Cela fait deux ans que la question a été posée. Le problème des fichiers JAR imbriqués persiste néanmoins. J'espère que cela aidera quelqu'un.

36voto

mmc18 Points 1563

Mis à jour :

<build> 
  <plugins> 
    <plugin> 
    <artifactId>maven-dependency-plugin</artifactId> 
    <executions> 
      <execution> 
        <phase>install</phase> 
          <goals> 
            <goal>copy-dependencies</goal> 
          </goals> 
          <configuration> 
             <outputDirectory>${project.build.directory}/lib</outputDirectory> 
          </configuration> 
        </execution> 
      </executions> 
    </plugin> 
  </plugins> 
</build>

24voto

Andrey Borisov Points 1753

Le moyen le plus simple et le plus efficace est d'utiliser un plugin uber comme celui-ci :

          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <finalName>uber-${project.artifactId}-${project.version}</finalName>
            </configuration>
        </plugin>

Vous aurez dé-normalisé tout dans un seul fichier JAR.

14voto

Cybran Points 1082

El exécutable packer maven plugin peut être utilisé exactement dans ce but : créer des applications Java autonomes contenant toutes les dépendances sous forme de fichiers JAR dans un dossier spécifique.

Il suffit d'ajouter les éléments suivants à votre pom.xml à l'intérieur de la <build><plugins> (veillez à remplacer la valeur de mainClass en conséquence) :

<plugin>
    <groupId>de.ntcomputer</groupId>
    <artifactId>executable-packer-maven-plugin</artifactId>
    <version>1.0.1</version>
    <configuration>
        <mainClass>com.example.MyMainClass</mainClass>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>pack-executable-jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Le fichier JAR construit est situé à target/<YourProjectAndVersion>-pkg.jar après avoir exécuté mvn package . Toutes ses dépendances de compilation et d'exécution seront incluses dans le fichier lib/ dans le fichier JAR.

Disclaimer : Je suis l'auteur du plugin.

5voto

MahmoudS Points 6654

En suivant ce lien :

Comment faire : Eclipse Maven install build jar avec des dépendances

J'ai découvert que ce n'est pas une solution viable car le chargeur de classe ne charge pas les jars à partir d'un autre jar, donc je pense que je vais décompresser les dépendances à l'intérieur du jar.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X