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

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:

  org.apache.maven.plugins maven-dependency-plugin   copy-dependencies prepare-package  copy-dependencies   ${project.build.directory}/lib false false true      org.apache.maven.plugins maven-jar-plugin    true lib/ theMainClass     

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 .


Para el despliegue manual

  • Pros
  • Contras
    • Las dependencias están fuera de la jarra final.

Copie dependencias en un directorio específico

  org.apache.maven.plugins maven-dependency-plugin   copy-dependencies prepare-package  copy-dependencies   ${project.build.directory}/${project.build.finalName}.lib     

Haga que Jar ejecutable y Classpath estén al tanto

  org.apache.maven.plugins maven-jar-plugin    true ${project.build.finalName}.lib/ ${fully.qualified.main.class}     

En este punto, el jar es realmente ejecutable con elementos externos de classpath.

 $ java -jar target/${project.build.finalName}.jar 

Hacer archivos desplegables

El archivo jar solo es ejecutable con el hermano ...lib/ directory. Necesitamos hacer archivos para implementar con el directorio y su contenido.

  org.apache.maven.plugins maven-antrun-plugin   antrun-archive package  run                

Ahora tiene target/${project.build.finalName}.(zip|tar|tar.bz2|tar.gz) que contiene el jar y lib/* .


Complemento ensamblador Apache Maven

  • Pros
  • Contras
    • No hay soporte de reubicación de clase (use maven-shade-plugin si es necesaria la reubicación de clase).
  org.apache.maven.plugins maven-assembly-plugin   package  single     ${fully.qualified.main.class}    jar-with-dependencies      

Tienes target/${project.bulid.finalName}-jar-with-dependencies.jar .


Apache Maven Shade Plugin

  • Pros
  • Contras
  org.apache.maven.plugins maven-shade-plugin    shade   true   ${fully.qualified.main.class}       

Tienes target/${project.build.finalName}-shaded.jar .


onejar-maven-plugin

  • Pros
  • Contras
    • No se admite activamente desde 2012.
    com.jolira onejar-maven-plugin    ${fully.qualified.main.class} true  

Tomando la respuesta de Unanswered y reformatándola, tenemos:

    org.apache.maven.plugins maven-jar-plugin    true fully.qualified.MainClass      maven-assembly-plugin   jar-with-dependencies      

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

  [...]    maven-assembly-plugin    true fully.qualified.MainClass    jar-with-dependencies     make-my-jar-with-dependencies package  single     [...]  [...]   

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.

Ver ejemplo a continuación

     org.apache.maven.plugins maven-shade-plugin 1.4   package  shade      bouncycastle:bcprov-jdk15      com.main.MyMainClass    properties.properties   applicationContext.xml   META-INF/cxf/cxf.extension   META-INF/cxf/bus-extensions.xml        

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

  org.dstovall onejar-maven-plugin 1.3.0    com.company.MainClass   one-jar     

Necesita agregar repository para ese complemento:

   onejar-maven-plugin.googlecode.com http://onejar-maven-plugin.googlecode.com/svn/mavenrepo   

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

    maven-jar-plugin    fully.qualified.MainClass      maven-dependency-plugin   unpack-dependencies package  unpack-dependencies        ${basedir}/target/dependency    

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.

Puede agregar lo siguiente a su pom.xml :

  install   maven-compiler-plugin 2.3.2  1.6 1.6    org.apache.maven.plugins maven-jar-plugin 2.3.1    true com.mycompany.package.MainClass      maven-assembly-plugin   jar-with-dependencies    com.mycompany.package.MainClass      make-my-jar-with-dependencies package  single       

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 :

   org.apache.maven.plugins maven-jar-plugin 2.3.2    true com.example.MyMainClass     

Finalmente crea el jar ejecutable invocando:

 mvn clean package shade:shade 

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.

   org.apache.maven.plugins maven-shade-plugin 2.3    package  shade     path.to.MainClass       

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:

  ...    org.apache.maven.plugins maven-dependency-plugin   unpack-dependencies package  unpack-dependencies      ...   ${basedir}/target/dependency /    ...  

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.

https://github.com/creditkarma/maven-exec-jar-plugin

Y aquí hay una publicación de blog con detalles sobre el complemento y por qué lo hicimos: https://engineering.creditkarma.com/general-engineering/new-executable-jar-plugin-available-apache-maven/

Puede usar el plugin maven-shade para construir un jarro Uber como el que se muestra a continuación

   org.apache.maven.plugins maven-shade-plugin   package  shade     

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.

Mira esto para más detalles.

Clase: org.apache.maven.plugin.assembly.io.DefaultAssemblyReader

Ejemplo:

    maven-assembly-plugin 2.2.1   make-assembly package  single   assembly-zip-for-wid      cz.ness.ct.ip.assemblies TEST_SharedAssemblyDescriptor 1.0.0-SNAPSHOT    

Debería ser así:

   maven-dependency-plugin   unpack-dependencies generate-resources  unpack-dependencies     

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:

 java -jar ProjectMainJar.jar com.stackoverflow.projectName.MainDynamicClassLoaderClass 

Si lo desea, desde la línea de comando en sí. Simplemente ejecute el comando debajo de la ruta del proyecto

assembly mvn: assembly

También puedes utilizar este complemento, es bastante bueno y lo uso para empacar mis jarrones http://sonatype.github.io/jarjar-maven-plugin/

Algo que me ha funcionado fue:

   maven-dependency-plugin   unpack-dependencies prepare-package  unpack-dependencies   ${project.build.directory}/classes      org.apache.maven.plugins maven-jar-plugin   unpack-dependencies package      true lib/ SimpleKeyLogger     

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

Esta es la mejor manera que encontré:

   org.apache.maven.plugins maven-jar-plugin 2.4    true com.myDomain.etc.MainClassName dependency-jars/      org.apache.maven.plugins maven-dependency-plugin 2.5.1   copy-dependencies package  copy-dependencies    ${project.build.directory}/dependency-jars/      

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.

     org.apache.maven.plugins maven-assembly-plugin    true com.your.package.MainClass    jar-with-dependencies     make-my-jar-with-dependencies package  single        

Después de hacer esto, no olvide ejecutar la herramienta MAVEN con este comando mvn clean compile assembly: single

http://jkoder.com/maven-creating-a-jar-together-with-its-dependency-jars-into-a-single-executable-jar-file/

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

     org.apache.maven.plugins maven-jar-plugin 2.4    true lib/ WordListDriver       

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

   org.apache.maven.plugins maven-dependency-plugin   copy-dependencies prepare-package  copy-dependencies   ${project.build.directory}/lib compile true false false true      org.apache.maven.plugins maven-assembly-plugin 2.6    true com.rbccm.itf.cdd.poller.landingzone.LandingZonePoller    jar-with-dependencies     make-my-jar-with-dependencies package  single      org.apache.maven.plugins maven-shade-plugin 2.4.3  false false   META-INF/services/javax.ws.rs.ext.Providers   META-INF/spring.factories   META-INF/spring.handlers   META-INF/spring.schemas   META-INF/spring.tooling           shade     

Para cualquiera que busque opciones para excluir dependencias específicas del uber-jar, esta es una solución que funcionó para mí:

    org.apache.spark spark-core_2.11 1.6.1 provided <=============      maven-assembly-plugin   jar-with-dependencies    ...      make-assembly package  single        

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 .

configuración del complemento maven

   log-enrichment   maven-assembly-plugin   jar-with-dependencies      

construir

 mvn clean compile assembly:single 

verificar

 ll target/ total 35100 drwxrwx--- 1 root vboxsf 4096 Sep 29 16:25 ./ drwxrwx--- 1 root vboxsf 4096 Sep 29 16:25 ../ drwxrwx--- 1 root vboxsf 0 Sep 29 16:08 archive-tmp/ drwxrwx--- 1 root vboxsf 0 Sep 29 16:25 classes/ drwxrwx--- 1 root vboxsf 0 Sep 29 16:25 generated-sources/ drwxrwx--- 1 root vboxsf 0 Sep 29 16:25 generated-test-sources/ -rwxrwx--- 1 root vboxsf 35929841 Sep 29 16:10 log-enrichment-jar-with-dependencies.jar* drwxrwx--- 1 root vboxsf 0 Sep 29 16:08 maven-status/ 

Agregar a pom.xml:

   com.jolira onejar-maven-plugin 1.4.4  

y

  com.jolira onejar-maven-plugin 1.4.4    one-jar     

Eso es. El paquete mvn siguiente también creará un contenedor de grasa adicionalmente, incluidos todos los tarros de dependencia.

Intereting Posts