Construire un fichier exécutable avec maven?

122

J'essaie de générer un fichier jar exécutable pour un petit projet domestique appelé "logmanager" en utilisant maven, comme ceci:

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

J'ai ajouté l'extrait qui y est présenté au pom.xml et j'ai exécuté mvn assembly: assembly. Il génère deux fichiers jar dans logmanager / target: logmanager-0.1.0.jar et logmanager-0.1.0-jar-with-dependencies.jar. J'obtiens une erreur lorsque je double-clique sur le premier pot:

Could not find the main class: com.gorkwobble.logmanager.LogManager. Program will exit.

Une erreur légèrement différente lorsque je double-clique sur le fichier jar-with-dependencies.jar:

Failed to load Main-Class manifest attribute from: C:\EclipseProjects\logmanager\target\logmanager-0.1.0-jar-with-dependencies.jar

J'ai copié et collé le chemin et le nom de la classe, et vérifié l'orthographe dans le POM. Ma classe principale se lance bien à partir d'une configuration de lancement d'éclipse. Quelqu'un peut-il m'aider à comprendre pourquoi mon fichier jar ne s'exécute pas? Aussi, pourquoi y a-t-il deux pots pour commencer? Faites-moi savoir si vous avez besoin de plus d'informations.

Voici le plein pom.xml, pour référence:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.gorkwobble</groupId>
  <artifactId>logmanager</artifactId>
  <name>LogManager</name>
  <version>0.1.0</version>
  <description>Systematically renames specified log files on a scheduled basis. Designed to help manage MUSHClient logging and prevent long, continuous log files.</description>
  <build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.2</version>
            <!-- nothing here -->
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.2-beta-4</version>
            <configuration>
              <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
              </descriptorRefs>
              <archive>
                <manifest>
                  <mainClass>com.gorkwobble.logmanager.LogManager</mainClass>
                </manifest>
              </archive>
            </configuration>
            <executions>
              <execution>
                <phase>package</phase>
                <goals>
                  <goal>single</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
              <source>1.6</source>
              <target>1.6</target>
            </configuration>
          </plugin>
    </plugins>
  </build>
  <dependencies>
    <!-- commons-lang -->
    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.4</version>
    </dependency> 

    <!-- Quartz scheduler -->
    <dependency>
        <groupId>opensymphony</groupId>
        <artifactId>quartz</artifactId>
        <version>1.6.3</version>
    </dependency>
    <!-- Quartz 1.6.0 depends on commons collections -->
    <dependency>
      <groupId>commons-collections</groupId>
      <artifactId>commons-collections</artifactId>
      <version>3.1</version>
    </dependency>
    <!-- Quartz 1.6.0 depends on commons logging -->
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.1</version>
    </dependency>
    <!-- Quartz 1.6.0 requires JTA in non J2EE environments -->
    <dependency>
      <groupId>javax.transaction</groupId>
      <artifactId>jta</artifactId>
      <version>1.1</version>
      <scope>runtime</scope>
    </dependency>

    <!-- junitx test assertions -->
    <dependency>
        <groupId>junit-addons</groupId>
        <artifactId>junit-addons</artifactId>
        <version>1.4</version>
        <scope>test</scope>
    </dependency>

    <!-- junit dependency; FIXME: make this a separate POM -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.1</version>
    </dependency>

  </dependencies>
  <dependencyManagement>
  </dependencyManagement>
</project>
RMorrisey
la source

Réponses:

244

En fait, je pense que la réponse donnée dans la question que vous avez mentionnée est tout simplement fausse ( MISE À JOUR - 20101106: quelqu'un l'a corrigé, cette réponse fait référence à la version précédant l'édition ) et cela explique, au moins partiellement, pourquoi vous rencontrez des problèmes.


Il génère deux fichiers jar dans logmanager / target: logmanager-0.1.0.jar et logmanager-0.1.0-jar-with-dependencies.jar.

Le premier est le JAR du module logmanager généré lors de la packagephase by jar:jar(car le module a un packaging de type jar). Le second est l'assembly généré par assembly:assemblyet doit contenir les classes du module courant et ses dépendances (si vous avez utilisé le descripteur jar-with-dependencies).

J'obtiens une erreur lorsque je double-clique sur le premier pot:

Could not find the main class: com.gorkwobble.logmanager.LogManager. Program will exit.

Si vous avez appliqué la configuration suggérée du lien publié comme référence, vous avez configuré le plugin jar pour produire un artefact exécutable, quelque chose comme ceci:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
      <archive>
        <manifest>
          <addClasspath>true</addClasspath>
          <mainClass>com.gorkwobble.logmanager.LogManager</mainClass>
        </manifest>
      </archive>
    </configuration>
  </plugin>

Il logmanager-0.1.0.jarest donc effectivement exécutable mais 1. ce n'est pas ce que vous voulez (car il n'a pas toutes les dépendances) et 2. il ne contient pas com.gorkwobble.logmanager.LogManager(c'est ce que dit l'erreur, vérifiez le contenu du fichier jar).

Une erreur légèrement différente lorsque je double-clique sur le fichier jar-with-dependencies.jar:

Failed to load Main-Class manifest attribute from: C:\EclipseProjects\logmanager\target\logmanager-0.1.0-jar-with-dependencies.jar

Encore une fois, si vous avez configuré le plugin d'assemblage comme suggéré, vous avez quelque chose comme ceci:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
    </configuration>
  </plugin>

Avec cette configuration, logmanager-0.1.0-jar-with-dependencies.jarcontient les classes du module actuel et ses dépendances mais, selon l'erreur, META-INF/MANIFEST.MF il ne contient pas d' Main-Classentrée (ce n'est probablement pas le même MANIFEST.MF que dans logmanager-0.1.0.jar). Le fichier jar n'est en fait pas exécutable, ce qui n'est pas non plus ce que vous voulez.


Donc, ma suggestion serait de supprimer l' configurationélément du maven-jar-plugin et de configurer le maven-assembly-plugin comme ceci:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.2</version>
    <!-- nothing here -->
  </plugin>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.2-beta-4</version>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
      <archive>
        <manifest>
          <mainClass>org.sample.App</mainClass>
        </manifest>
      </archive>
    </configuration>
    <executions>
      <execution>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

Bien sûr, remplacez-le org.sample.Apppar la classe que vous souhaitez exécuter. Petit bonus, je suis lié assembly:singleà la packagephase pour que vous n'ayez plus à courir assembly:assembly. Exécutez simplement mvn installet l'assemblage sera produit lors de la construction standard.

Donc, veuillez mettre à jour votre pom.xml avec la configuration donnée ci-dessus et exécuter mvn clean install. Ensuite, cd dans le targetrépertoire et réessayez:

java -jar logmanager-0.1.0-jar-with-dependencies.jar

Si vous obtenez une erreur, veuillez mettre à jour votre question avec elle et publier le contenu du META-INF/MANIFEST.MFfichier et la partie pertinente de votre pom.xml(les parties de configuration des plugins). Veuillez également publier le résultat de:

java -cp logmanager-0.1.0-jar-with-dependencies.jar com.gorkwobble.logmanager.LogManager

pour démontrer que cela fonctionne bien sur la ligne de commande (indépendamment de ce que dit eclipse).

EDIT: Pour Java 6, vous devez configurer le plugin maven-compiler-plugin. Ajoutez ceci à votre pom.xml:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
      <source>1.6</source>
      <target>1.6</target>
    </configuration>
  </plugin>
Pascal Thivent
la source
4
Merci pour vos commentaires! J'ai changé mon pom.xml comme vous l'avez spécifié. Lorsque j'exécute mvn clean install, j'obtiens un tas d'erreurs de compilation de mon code, disant que les annotations et ainsi de suite ne sont pas prises en charge dans -source 1.3. J'utilise jdk1.6 et il compile en eclipse; Je ne sais pas comment le 1.3 a été introduit. Peut-être que l'une des versions de la bibliothèque dans l'extrait de code pom est une version plus ancienne?
RMorrisey
Merci! J'ai dépassé le problème 1.3. J'ai également dû ajouter la dépendance junit4 à mon POM. Je travaille sur le dépannage d'autres choses; si je suis bloqué, je posterai à nouveau! Si je fais fonctionner le pot, je marquerai ceci comme réponse. Mon POM actuel est mis à jour dans la question ci-dessus.
RMorrisey
Existe-t-il un moyen d'exclure les ressources du fichier jar généré?
2
Est-il possible que le jar résultant ait un nom "normal"?
Daniil Shevelev le
1
J'ai également trouvé ce billet de blog Sonatype utile
15

La réponse de Pascal Thivent m'a aidé aussi. Mais si vous gérez vos plugins dans l' <pluginManagement>élément, vous devez redéfinir l'assemblage en dehors de la gestion des plugins, sinon les dépendances ne sont pas emballées dans le jar si vous exécutez mvn install.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>


    <build>
        <pluginManagement>
            <plugins>

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

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-assembly-plugin</artifactId>
                    <version>2.4</version>
                    <configuration>
                        <archive>
                            <manifest>
                                <mainClass>main.App</mainClass>
                            </manifest>
                        </archive>
                        <descriptorRefs>
                            <descriptorRef>jar-with-dependencies</descriptorRef>
                        </descriptorRefs>
                    </configuration>
                    <executions>
                        <execution>
                            <id>make-assembly</id>
                            <phase>package</phase>
                            <goals>
                                <goal>single</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

            </plugins>

        </pluginManagement>

        <plugins> <!-- did NOT work without this  -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
            </plugin>
        </plugins>

    </build>


    <dependencies>
       <!--  dependencies commented out to shorten example -->
    </dependencies>

</project>
Mike
la source
1
Merci Mike, cela m'a aidé. Au départ, mon package était généré sans utiliser <pluginManagement>. Mais Eclipse donnait une erreur dans pom.xml "maven - L'exécution du plugin n'est pas couverte par le cycle de vie". Ce qui me distrait. Donc, pour résoudre ce problème, j'ai ajouté <pluginManagement>, maintenant l'erreur d'éclipse a disparu mais mon package a cessé d'être construit. Votre extrait de pom ci-dessus a fonctionné pour moi. :)
shashaDenovo
2
Cela a été utile ... lors de l'utilisation de <pluginManagement>, la première réponse ne fonctionnera pas.
ininprsr
5

Si vous ne voulez pas exécuter l'objectif d'assemblage sur le package, vous pouvez utiliser la commande suivante:

mvn package assembly:single

Ici, le package est le mot-clé.

leonidv
la source
-1

Faites un clic droit sur le projet et donnez maven build, maven clean, maven generate resource et maven install.Le fichier jar sera automatiquement généré.

poupée de chariot
la source