Quiero empaquetar mi proyecto en un único JAR ejecutable para su distribución.
¿Cómo puedo hacer un paquete de proyecto Maven con todos los JAR de dependencia en mi JAR de salida?
Puede usar el complemento-dependencia para generar todas las dependencias en un directorio separado antes de la fase del paquete y luego incluir eso en el classpath del manifiesto:
Alternativamente, use ${project.build.directory}/classes/lib como OutputDirectory para integrar todos los archivos jar en el jar principal, pero luego tendrá que agregar un código personalizado de carga de clases para cargar los jars.
Publiqué sobre algunas formas diferentes de hacer esto.
Consulte Frasco ejecutable con Apache Maven (WordPress)
o ejecutable-jar-con-maven-example (GitHub)
Notas
Esos pros y contras son proporcionados por Stephan .
A continuación, recomendaría hacer de esto una parte natural de su comstackción, en lugar de algo a lo que llamar explícitamente. Para hacer de esto una parte integral de su comstackción, agregue este complemento a su pom.xml y agréguelo al evento del ciclo de vida del package . Sin embargo, un problema es que debe llamar al assembly:single objective assembly:single si lo coloca en su pom.xml, mientras que si lo ejecuta manualmente desde la línea de comando, llamaría a ‘assembly: assembly’.
Utilice el maven-shade-plugin para empaquetar todas las dependencias en un solo uber-jar. También se puede usar para construir un jar ejecutable especificando la clase principal. Después de tratar de usar maven-assembly y maven-jar, encontré que este plugin se ajustaba mejor a mis necesidades.
Encontré este plugin particularmente útil ya que combina el contenido de archivos específicos en lugar de sobreescribirlos. Esto es necesario cuando hay archivos de recursos que tienen el mismo nombre en todas las jarras y el complemento intenta empaquetar todos los archivos de recursos.
Long usó el complemento de ensamblaje de maven , pero no pude encontrar una solución al problema con "already added, skipping" . Ahora, estoy usando otro complemento – onejar-maven-plugin . Ejemplo a continuación ( mvn package comstackción mvn package ):
Puede usar maven-dependency-plugin, pero la pregunta era cómo crear un JAR ejecutable. Hacer eso requiere la siguiente alteración a la respuesta de Matthew Franglen (por cierto, usar el complemento de dependencia tarda más en comstackrse cuando se comienza desde un objective limpio):
Otra opción si realmente desea volver a empaquetar los demás contenidos JAR dentro de su único JAR resultante es el complemento Maven Assembly . Desempaca y luego vuelve a empacar todo en un directorio a través de true . Entonces tendrías un segundo pase que lo construyó en un JAR masivo.
Otra opción es el complemento OneJar . Esto realiza las acciones de reempaquetado anteriores, todo en un solo paso.
Luego debe cambiar a través de la consola al directorio, donde se encuentra el pom.xml. Luego debe ejecutar mvn assembly: single y luego su archivo ejecutable JAR con dependencias se construirá con suerte. Puede verificarlo al cambiar al directorio de salida (destino) con cd ./target e iniciar su jar con un comando similar a java -jar mavenproject1-1.0-SNAPSHOT-jar-with-dependencies.jar .
Probé esto con Apache Maven 3.0.3 .
Puede combinar el maven-shade-plugin y maven-jar-plugin .
maven-shade-plugin incluye sus clases y todas las dependencias en un solo archivo jar.
Configure el maven-jar-plugin para especificar la clase principal de su jar ejecutable (vea Configurar el Classpath , capítulo “Make The Jar Executable”).
Ejemplo de configuración POM para maven-jar-plugin :
Revisé cada una de estas respuestas buscando hacer un gran contenedor ejecutable que contenga todas las dependencias y ninguna funcionó bien. La respuesta es el plugin de sombra, es muy fácil y directo.
Tenga en cuenta que sus dependencias deben tener un scope de comstackción o tiempo de ejecución para que esto funcione correctamente.
Este ejemplo vino de mkyong.com
Ken Liu lo tiene correcto en mi opinión. El complemento de dependencia maven le permite expandir todas las dependencias, que luego puede tratar como recursos. Esto le permite incluirlos en el artefacto principal . El uso del complemento de ensamblaje crea un artefacto secundario que puede ser difícil de modificar; en mi caso, quería agregar entradas de manifiesto personalizadas. Mi pom terminó como:
Aquí hay un complemento de jar ejecutable para Maven que usamos en Credit Karma. Crea un contenedor de jar con un cargador de clases capaz de cargar clases desde jarras anidadas. Esto le permite tener la misma ruta de clases en dev y prod y aún mantener todas las clases en un solo archivo jar firmado.
Utilice el complemento onejar para comstackrlo como un archivo jar ejecutable que empaqueta todos los jar de dependencias que contiene. Eso resolvió mi problema que era similar a esto. Cuando se utilizó el plugin de ensamblaje, desempaquetó todos los flasks de dependencias en la carpeta de origen y los volvió a empaquetar como un flask, ya había escrito todas las implementaciones similares que tenía dentro de mi código que tenían los mismos nombres de clase. Onejar es una solución fácil aquí.
¿Problema al ubicar el archivo de ensamblado compartido con maven-assembly-plugin-2.2.1?
Intente utilizar el parámetro de configuración descriptorId en lugar de los descriptores / descriptor o los parámetros descriptorRefs / descriptorRef.
Ninguno de ellos hace lo que necesita: busque el archivo en classpath. Por supuesto, necesita agregar el paquete donde reside el ensamblado compartido en el classpath de maven-assembly-plugin (ver a continuación). Si está utilizando Maven 2.x (no Maven 3.x), puede necesitar agregar esta dependencia en el pom.xml principal superior en la sección pluginManagement.
El desempaquetado debe estar en la fase de generación de recursos porque, si está en fase de paquete, no se incluirá como recursos. Prueba el paquete limpio y ya verás.
No responderé directamente a la pregunta, ya que otros ya lo han hecho antes, pero realmente me pregunto si es una buena idea incorporar todas las dependencias en el propio contenedor del proyecto.
Veo el punto (facilidad de implementación / uso) pero depende del caso de uso de su proyecto (y puede haber alternativas (ver a continuación)).
Si lo usa completamente independiente, ¿por qué no?
Pero si usa su proyecto en otros contextos (como en una aplicación web o en una carpeta donde están instalados otros archivos jar), puede tener duplicados jar en su classpath (los que están en la carpeta, uno en los archivos jar). Tal vez no sea un acuerdo de oferta, pero generalmente evito esto.
Una buena alternativa:
despliega tu aplicación como .zip / .war: el archivo contiene el jar de tu proyecto y todos los jars dependientes;
utilice un mecanismo dynamic de cargador de clases (vea Spring, o puede hacerlo fácilmente usted mismo) para tener un único punto de entrada de su proyecto (una sola clase para comenzar – vea el mecanismo Manifest en otra respuesta), que agregará (dinámicamente) al ruta de clases actual todos los demás jarrones necesarios.
Así, con al final solo un manifiesto y un “principal dynamic de carga de clases principal”, puedes comenzar tu proyecto con:
Tuve un caso extraordinario porque mi dependencia era el sistema uno:
.. system${project.basedir}/lib/myjar.jar
He cambiado el código provisto por @ user189057 con cambios: 1) maven-dependency-plugin se ejecuta en “prepare-package” fase 2) Estoy extrayendo clases desempaquetadas directamente a “target / classes”
Probé la respuesta más votada aquí, y pude hacer que el jar se pueda ejecutar. Pero el progtwig no se ejecutó correctamente. No sé cuál fue el motivo. Cuando trato de ejecutar desde Eclipse , obtengo un resultado diferente, pero cuando ejecuto el jar desde la línea de comandos obtengo un resultado diferente (se bloquea con un error de tiempo de ejecución específico del progtwig).
Tenía un requisito similar al OP, solo que tenía demasiadas (Maven) dependencias para mi proyecto. Afortunadamente, la única solución que funcionó para mí fue usar Eclipse . Muy simple y muy directo. Esta no es una solución para el OP, pero es una solución para alguien que tiene un requisito similar pero con muchas dependencias Maven,
1) Simplemente haga clic derecho en la carpeta de su proyecto (en Eclipse) y seleccione Export
2) Luego seleccione Java -> Runnable Jar
3) Se le pedirá que elija la ubicación del archivo jar
4) Finalmente, seleccione la clase que tiene el método principal que desea ejecutar y elija las Package dependencies with the Jar file y haga clic en Finish
Con esta configuración, todas las dependencias se ubicarán en /dependency-jars . Mi aplicación no tiene clase Main , solo contextuales, pero una de mis dependencias tiene una clase Main ( com.myDomain.etc.MainClassName ) que inicia el servidor JMX y recibe un parámetro de start o de stop . Así que con esto pude comenzar mi aplicación de esta manera:
java -jar ./lib/TestApp-1.0-SNAPSHOT.jar start
Espero que sea útil para todos ustedes.
Para resolver este problema, usaremos Maven Assembly Plugin que creará el JAR junto con sus JAR de dependencia en un solo archivo JAR ejecutable. Simplemente agregue la configuración de complemento a continuación en su archivo pom.xml.
El plugin maven-assembly-funcionó muy bien para mí. Pasé horas con el complemento maven-dependency-plugin y no pude hacerlo funcionar. La razón principal fue que tuve que definir explícitamente en la sección de configuración los elementos del artefacto que deberían incluirse tal como se describe en la documentación . Hay un ejemplo allí para los casos en que desea usarlo como: mvn dependency:copy , donde no se incluyen elementos de artefactos pero no funciona.
Esto también podría ser una opción. Podrás construir tu archivo jar
Comparé los plugins de árbol mencionados en esta publicación. Genere 2 jarras y un directorio con todos los flasks. Comparé los resultados y definitivamente el maven-shade-plugin es el mejor. Mi desafío fue que tengo varios recursos de spring que deben fusionarse, así como jax-rs y servicios JDBC. Todos fueron fusionados correctamente por el plugin de sombra en comparación con el plugin maven-assembly-plugin. En ese caso, el resorte fallará a menos que los copie en su propia carpeta de recursos y los fusione manualmente una vez. Ambos complementos muestran el árbol de dependencias correcto. Tenía varios ámbitos, como prueba, proporcionar, comstackr, etc., la prueba y la proporcionada fueron omitidas por ambos complementos. Ambos produjeron el mismo manifiesto, pero pude consolidar licencias con el plugin de sombra utilizando su transformador. Con el complemento maven-dependency, por supuesto, no tienes esos problemas porque no se extraen los flasks. Pero como ha señalado otro, necesita llevar uno o más archivos para funcionar correctamente. Aquí hay un recorte del pom.xml
Entonces, no es una configuración del plugin mvn-assembly, sino una propiedad de la dependencia.
Ya hay millones de respuestas, quería agregar que no necesita si no necesita agregar entryPoint a su aplicación. Por ejemplo, las API pueden no tener necesariamente el método main .