java - make - maven-assembly-plugin
¿Cómo coloco todos los archivos JAR requeridos en una carpeta de biblioteca dentro del archivo JAR final con Maven? (8)
Actualizado:
<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>
Estoy usando Maven en mi aplicación independiente, y quiero empaquetar todas las dependencias en mi archivo JAR dentro de una carpeta de biblioteca, como se menciona en una de las respuestas aquí:
¿Cómo puedo crear un JAR ejecutable con dependencias usando Maven?
Quiero que mi archivo JAR final tenga una carpeta de biblioteca que contenga las dependencias como archivos JAR, no como el maven-shade-plugin
que pone las dependencias en forma de carpetas como la jerarquía Maven en la carpeta .m2.
Bueno, en realidad la configuración actual hace lo que quiero, pero tengo un problema con la carga de los archivos JAR cuando se ejecuta la aplicación. No puedo cargar las clases.
Aquí está mi configuración:
<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>
El proyecto funciona bien desde Eclipse, y los archivos JAR se colocan en la carpeta de la biblioteca dentro de mi archivo JAR final como yo quiera, pero cuando ejecuto el archivo JAR final desde la carpeta de destino siempre obtengo 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.
¿Cómo puedo solucionar esta excepción?
Así es como lo hago:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.project.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
Y luego solo corro:
mvn assembly:assembly
El complemento Maven del empaquetador ejecutable se puede usar exactamente para ese propósito: crear aplicaciones java independientes que contengan todas las dependencias como archivos JAR en una carpeta específica.
Simplemente agregue lo siguiente a su pom.xml
dentro de la sección <build><plugins>
(asegúrese de reemplazar el valor de mainClass
consecuencia):
<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>
El archivo JAR target/<YourProjectAndVersion>-pkg.jar
se encuentra en target/<YourProjectAndVersion>-pkg.jar
después de ejecutar el mvn package
. Todas sus dependencias en tiempo de compilación y en tiempo de ejecución se incluirán en la carpeta lib/
dentro del archivo JAR.
Descargo de responsabilidad: soy el autor del complemento.
Encontré esta respuesta a la pregunta:
http://padcom13.blogspot.co.uk/2011/10/creating-standalone-applications-with.html
No solo obtiene los archivos lib dependientes en una carpeta lib, sino que también obtiene un director de bin con un ejecutable tanto de UNIX como de DOS.
El ejecutable finalmente llama a Java con un argumento -cp que también enumera todas sus bibliotecas dependientes.
Todo el lote se encuentra en una carpeta de instalación dentro de la carpeta de destino. Épico.
====================================================================================================================================================================================================
Este es claramente un problema de classpath. Tenga en cuenta que classpath debe cambiar un poco cuando ejecuta su programa fuera del IDE. Esto se debe a que el IDE carga los otros JAR relativos a la carpeta raíz de su proyecto, mientras que en el caso del JAR final esto generalmente no es cierto.
Lo que me gusta hacer en estas situaciones es construir el JAR manualmente. Me lleva como máximo 5 minutos y siempre resuelve el problema. No sugiero que hagas esto. Encuentra una manera de usar Maven, ese es su propósito.
La forma más simple y más eficiente es usar un plugin de uber como este:
<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-${artifactId}-${version}</finalName>
</configuration>
</plugin>
Habrá desnormalizado todo en un archivo JAR.
La siguiente es mi solución. Pruébalo si funciona para ti:
<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>
El primer complemento coloca todas las dependencias en la carpeta target / classes / lib, y el segundo incluye la carpeta de la biblioteca en el archivo JAR final y configura el archivo Manifest.mf
.
Pero luego deberá agregar un código personalizado de carga de clases para cargar los archivos JAR.
O bien, para evitar la carga de clases personalizada, puede usar "$ {project.build.directory} / lib, pero en este caso, no tiene dependencias dentro del archivo JAR final, lo cual infringe el propósito.
Han pasado dos años desde que se hizo la pregunta. El problema de los archivos JAR anidados persiste sin embargo. Espero que ayude a alguien.
siguiendo este enlace:
Cómo: Eclipse Maven instala el jar de construcción con dependencias
descubrí que esta solución no es viable porque el cargador de clases no carga los frascos desde dentro de los frascos, por lo que creo que desempaquetaré las dependencias dentro del frasco.