Construyendo un frasco ejecutable con Maven 2

82

Soy relativamente nuevo en el mantra de Maven, pero estoy tratando de construir un jar ejecutable en la línea de comandos con Maven. He configurado mis dependencias, pero cuando ejecuto mvn installe intento ejecutar el jar, suceden dos cosas. Primero, no se encuentra ninguna clase principal, que se pueda corregir. Cuando lo he corregido, obtengo errores al ejecutar que indican que no se pueden encontrar las clases.

Maven no está empaquetando mis bibliotecas de dependencia dentro del jar, por lo que no puedo ejecutar el jar como una aplicación independiente. ¿Cómo corrijo esto?

Stefan Kendall
fuente
Puede usar IDE para maven como Netbenas
Sajad Bahmani
7
@SjB: ¿y eso resuelve mágicamente el problema? No lo creo.
Joachim Sauer
1
¿Duplicado exacto de qué, exactamente?
Stefan Kendall
Tal vez este stackoverflow.com/questions/1832853/… , o este stackoverflow.com/questions/574594/… (pero la respuesta aceptada es incorrecta), o este stackoverflow.com/questions/1814526/… . En realidad, esta parece ser una de las preguntas más frecuentes en maven ...
Pascal Thivent
1
Las otras respuestas no son tan claras, y uber jar (ueber escrito incorrectamente), no menciona la ejecución. Además, los otros temas están llenos de material irrelevante, como el nivel de fuente, etc.
Stefan Kendall

Respuestas:

113

La forma más sencilla de hacer esto sería crear un ensamblado usando maven-assembly-pluginy el jar-with-dependenciesdescriptor predefinido . También necesitará generar un manifiesto con una entrada de clase principal para este uber jar. El siguiente fragmento muestra cómo configurar el complemento de ensamblaje para hacerlo:

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

Luego, para generar el ensamblado, simplemente ejecute:

mvn assembly:assembly

Si desea generar el ensamblaje como parte de su compilación, simplemente vincule el assembly:singlemojo a la fase del paquete:

<build>
  <plugins>
    <plugin>
      <artifactId>maven-assembly-plugin</artifactId>
      <configuration>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <archive>
          <manifest>
            <mainClass>fully.qualified.MainClass</mainClass>
          </manifest>
        </archive>
      </configuration>
      <executions>
        <execution>
          <phase>package</phase>
          <goals>
            <goal>single</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Y simplemente ejecuta:

mvn package
Pascal Thivent
fuente
1
El complemento maven-shadow-plugin también funciona de manera similar y está dedicado a este propósito.
Dominic Mitchell
4
Esto no funciona para Spring y otras bibliotecas que esperan múltiples recursos con el mismo nombre en la ruta de clases. En el caso de spring, META-INF \ spring.schemas se incluye en varios frascos (beans, jdbc, etc.) y se usa para configurar el soporte del espacio de nombres XML para el analizador XML. Si intenta 'jar-with-dependencies', pasar application-context.xml fallará en tiempo de ejecución con algo como "org.xml.sax.SAXParseException: cvc-elt.1: No se puede encontrar la declaración del elemento 'beans'".
David Roussel
@David Maven no resolverá una "limitación" de Java. Simplemente empaquete su aplicación limpiamente (es decir, no en un uberjar) en ese caso.
Pascal Thivent
Esto funciona con la configuración de Spring sin problemas. Mi clase principal carga todas las demás clases con el contexto de la aplicación Classpath y esta solución funciona perfectamente.
vsingh
2
El assembly:assemblyobjetivo está obsoleto
Jared Beck
25

Maven no empaqueta sus dependencias dentro de su archivo jar, porque normalmente no hace esto con programas Java.

En su lugar, entrega las dependencias junto con su archivo jar y las menciona en el Class-Pathencabezado del Manifiesto .

Para seguir esta ruta, deberá habilitar la addClasspathpropiedad (documentada aquí ) para maven-jar-plugin.

Si realmente desea incluir todas sus dependencias en su archivo jar, puede usar el complemento Maven Assembly para crear un jar-with-dependencies.

Joachim Sauer
fuente
4
+1 He tenido dificultades para encontrar información sobre cómo los programas java están diseñados para ser construidos y distribuidos, especialmente con Maven.
Ed Brannin
8

Esto es lo que haría yo para proyectos pequeños. La mayoría de las veces no querrás un frasco enorme.

para construir: mvn clean dependency: paquete copy-dependencies

para ejecutar ( en el directorio de destino ): java -cp myjar.jar: ./ dependency / * com.something.MyClass

usuario2409824
fuente
¡Excelente! Guardé esto en mi Makefile, en el mismo directorio con pom.xml. build: \ n mvn .... (lo que dijiste)
Roboprog
Gracias. Después de buscar en Internet durante más de 2 horas, encontré esta respuesta muy útil ...
Shekhar
6

Estoy de acuerdo con Joachim Sauer,

En lugar de usar jar-with-dependency, debe configurar el complemento jar así en su pom.xml:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.4</version>
    <configuration>
        <archive>
            <index>true</index>
            <manifest>
                <addClasspath>true</addClasspath>
                <mainClass>[mainClassFullName]</mainClass>
            </manifest>
            <manifestEntries>
                <mode>development</mode>
                <url>${project.url}</url>
                <key>value</key>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>

Y use esta configuración de ensamblaje para agregar las dependencias de jar a su ensamblaje:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
  <id>zip-with-jars</id>
  <formats>
    <format>zip</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <dependencySets>
    <dependencySets>
    <dependencySet>
    <outputDirectory>/</outputDirectory>
    <useProjectArtifact>true</useProjectArtifact>
    <unpack>false</unpack>
    <scope>runtime</scope>
    </dependencySet>
</dependencySets>
  </dependencySets>
</assembly>
formixiano
fuente
2

Simplemente agregue el siguiente código en pom.xml y ejecútelo como: maven: install. El jar se creará en la carpeta de destino de eclipse que se puede utilizar como "java -jar Hello.jar". pero asegúrese de que el nombre de la clase principal sea com.abc.HelloWorld.java

<build>
<plugins>
<plugin>
<groupid>org.apache.maven.plugins</groupid>
<artifactid>maven-shade-plugin</artifactid>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalname>HelloW</finalname>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestentries>
<main-class>com.abc.HelloWorld.java</main-class>
<build-number>1</build-number>
</manifestentries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>

</build>
Pan
fuente