¿Construyendo jar ejecutable con maven?

122

Estoy tratando de generar un jar ejecutable para un pequeño proyecto casero llamado "logmanager" usando maven, así:

¿Cómo puedo crear un JAR ejecutable con dependencias usando Maven?

Agregué el fragmento que se muestra allí al pom.xml, y ejecuté mvn assembly: assembly. Genera dos archivos jar en logmanager / target: logmanager-0.1.0.jar y logmanager-0.1.0-jar-with-dependencies.jar. Recibo un error cuando hago doble clic en el primer jar:

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

Un error ligeramente diferente cuando hago doble clic en jar-with-dependencies.jar:

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

Copié y pegué la ruta y el nombre de clase, y verifiqué la ortografía en el POM. Mi clase principal se inicia bien desde una configuración de inicio de eclipse. ¿Alguien puede ayudarme a descubrir por qué mi archivo jar no se ejecutará? Además, ¿por qué hay dos frascos para empezar? Déjeme saber si usted necesita más información.

Aquí está el completo pom.xml, para referencia:

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

Respuestas:

244

En realidad, creo que la respuesta dada en la pregunta que mencionó es simplemente incorrecta ( ACTUALIZACIÓN - 20101106: alguien la arregló, esta respuesta se refiere a la versión que precede a la edición ) y esto explica, al menos parcialmente, por qué tiene problemas.


Genera dos archivos jar en logmanager / target: logmanager-0.1.0.jar y logmanager-0.1.0-jar-with-dependencies.jar.

El primero es el JAR del módulo logmanager generado durante la packagefase por jar:jar(porque el módulo tiene un tipo de empaquetado jar). El segundo es el ensamblado generado por assembly:assemblyy debe contener las clases del módulo actual y sus dependencias (si utilizó el descriptor jar-with-dependencies).

Recibo un error cuando hago doble clic en el primer jar:

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

Si aplicó la configuración sugerida del enlace publicado como referencia, configuró el complemento jar para producir un artefacto ejecutable, algo como esto:

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

Por logmanager-0.1.0.jarlo tanto, es ejecutable, pero 1. esto no es lo que desea (porque no tiene todas las dependencias) y 2. no contiene com.gorkwobble.logmanager.LogManager(esto es lo que dice el error, verifique el contenido del jar).

Un error ligeramente diferente cuando hago doble clic en jar-with-dependencies.jar:

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

Nuevamente, si configuró el complemento de ensamblaje como se sugiere, tiene algo como esto:

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

Con esta configuración, logmanager-0.1.0-jar-with-dependencies.jarcontiene las clases del módulo actual y sus dependencias, pero, de acuerdo con el error, META-INF/MANIFEST.MF no contiene una Main-Classentrada (es probable que no sea el mismo MANIFEST.MF que en logmanager-0.1.0.jar). El jar no es ejecutable, lo que tampoco es lo que quieres.


Por lo tanto, mi sugerencia sería eliminar el configurationelemento del complemento maven-jar y configurar el complemento maven-assembly de esta manera:

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

Por supuesto, reemplace org.sample.Appcon la clase que desea ejecutar. Pequeño bono, me he unido assembly:singlea la packagefase para que no tengas que correr assembly:assemblymás. Simplemente ejecute mvn instally el ensamblaje se producirá durante la compilación estándar.

Por lo tanto, actualice su pom.xml con la configuración dada anteriormente y ejecútelo mvn clean install. Luego, cd en el targetdirectorio e intente nuevamente:

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

Si recibe un error, actualice su pregunta con él y publique el contenido del META-INF/MANIFEST.MFarchivo y la parte relevante de su pom.xml(las partes de configuración de complementos). También publique el resultado de:

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

para demostrar que funciona bien en la línea de comando (independientemente de lo que diga eclipse).

EDITAR: Para Java 6, debe configurar el complemento compilador maven. Agregue esto a su 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
fuente
44
¡Gracias por tus comentarios! Cambié mi pom.xml como lo especificó. Cuando ejecuto mvn clean install, recibo un montón de errores de compilación de mi código, diciendo que las anotaciones, etc., no son compatibles con -source 1.3. Estoy usando jdk1.6 y se compila en eclipse; No estoy seguro de cómo se introdujo el 1.3. ¿Quizás una de las versiones de la biblioteca en el fragmento de pom es una anterior?
RMorrisey
¡Gracias! Pasé el problema 1.3. También tuve que agregar la dependencia junit4 a mi POM. Estoy trabajando para solucionar otros problemas; si me atasco, volveré a publicar! Si pongo el frasco en marcha marcaré esto como respuesta. Mi POM actual se actualiza en la pregunta anterior.
RMorrisey
¿Hay alguna forma de excluir los recursos del archivo jar generado?
2
¿Es posible que el jar resultante tenga un nombre "normal"?
Daniil Shevelev
1
También encontré útil esta publicación de blog de Sonatype
15

La respuesta de Pascal Thivent también me ayudó. Pero si administra sus complementos dentro del <pluginManagement>elemento, debe definir el ensamblaje nuevamente fuera de la administración de complementos, de lo contrario, las dependencias no se empaquetarán en el jar si ejecuta 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>
Miguel
fuente
1
Gracias Mike, me ayudó. Inicialmente, mi paquete se estaba generando sin usar <pluginManagement>. Pero Eclipse estaba dando algún error en pom.xml "maven - Ejecución del complemento no cubierto por el ciclo de vida". Lo que me distrae. Entonces, para resolver esto, agregué <pluginManagement>, ahora el error de eclipse desapareció pero mi paquete dejó de compilarse. Tu fragmento de pom de arriba me ha funcionado. :)
shashaDenovo 01 de
2
Esto fue útil ... al usar <pluginManagement>, la respuesta principal no funcionará.
ininprsr
5

Si no desea ejecutar el objetivo de ensamblaje en el paquete, puede usar el siguiente comando:

mvn package assembly:single

Aquí el paquete es la palabra clave.

leonidv
fuente
-1

Haga clic con el botón derecho en el proyecto y proporcione compilación de maven, limpieza de maven, generación de recursos de maven e instalación de maven. El archivo jar se generará automáticamente.

muñeca dolly
fuente