Crear JAR ejecutable con Gradle


Hasta ahora he creado archivos JAR ejecutables a través del Eclipse "Exportar..."funcionalidad, pero ahora cambié a IntelliJ IDEA y Gradle para la automatización de compilación.

Algunos artículos aquí sugieren el complemento "aplicación", pero esto no conduce completamente al resultado que esperaba (solo un JAR, sin scripts de inicio o algo así).

¿Cómo puedo lograr el mismo resultado que Eclipse hace con el "Exportar..."¿diálogo?

Author: Roland, 2014-02-12

8 answers

Un archivo jar ejecutable es solo un archivo jar que contiene una entrada de Clase Main en su manifiesto. Así que solo necesita configurar la tarea jar para agregar esta entrada en su manifiesto:

jar {
    manifest {
        attributes 'Main-Class': 'com.foo.bar.MainClass'
    }
}

Es posible que también necesite agregar entradas classpath en el manifiesto, pero eso se haría de la misma manera.

Véase http://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html

 110
Author: JB Nizet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-12 07:26:16

Las respuestas de JB Nizet y Jorge_B son correctas.

En su forma más simple, crear un JAR ejecutable con Gradle es solo cuestión de agregar las entradas apropiadas al manifiesto . Sin embargo, es mucho más común tener dependencias que necesitan ser incluidas en el classpath, lo que hace que este enfoque sea complicado en la práctica.

El complemento de la aplicación proporciona un enfoque alternativo; en lugar de crear un JAR ejecutable, proporciona:

  • a run tarea para facilitar fácilmente la ejecución de la aplicación directamente desde la compilación
  • una tarea installDist que genera una estructura de directorios que incluye el JAR construido, todos los JARs de los que depende, y un script de inicio que lo reúne todo en un programa que puede ejecutar
  • distZip y distTar tareas que crean archivos que contienen una distribución completa de la aplicación (scripts de inicio y JARs)

Un tercer enfoque es crear un llamado" fat JAR " que es un ejecutable JAR que incluye no solo el código de su componente, sino también todas sus dependencias. Hay algunos plugins diferentes que utilizan este enfoque. He incluido enlaces a algunos de los que estoy al tanto; estoy seguro de que hay más.

 74
Author: davidmc24,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-18 08:16:05

Como otros han señalado, para que un archivo jar sea ejecutable, el punto de entrada de la aplicación debe estar establecido en el atributo Main-Class del archivo de manifiesto. Si los archivos de la clase de dependencia no están colocados, entonces deben establecerse en la entrada Class-Path del archivo de manifiesto.

He probado todo tipo de combinaciones de plugins y lo que no es para la simple tarea de crear un jar ejecutable y de alguna manera, incluir las dependencias. Todos los plugins parecen carecer de una forma u otra, pero finalmente lo conseguí como quería. No hay scripts misteriosos, ni un millón de mini archivos diferentes que contaminen el directorio de compilación, un archivo de script de compilación bastante limpio, y sobre todo: no hay un millón de archivos de clase de terceros extranjeros fusionados en mi archivo jar.

Lo siguiente es un copy-paste de aquí para su conveniencia..

[Cómo] crear un archivo zip de distribución con jars de dependencias en el subdirectorio /lib y agregar todas las dependencias a la entrada Class-Path en el manifiesto archivo:

apply plugin: 'java'
apply plugin: 'java-library-distribution'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.apache.commons:commons-lang3:3.3.2'
}

// Task "distZip" added by plugin "java-library-distribution":
distZip.shouldRunAfter(build)

jar {
    // Keep jar clean:
    exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.MF'

    manifest {
        attributes 'Main-Class': 'com.somepackage.MainClass',
                   'Class-Path': configurations.runtime.files.collect { "lib/$it.name" }.join(' ')
    }
    // How-to add class path:
    //     https://stackoverflow.com/questions/22659463/add-classpath-in-manifest-using-gradle
    //     https://gist.github.com/simon04/6865179
}

Alojado como un gist aquí.

El resultado se puede encontrar en build/distributions y el contenido descomprimido se ve así:

Lib/commons-lang3-3.3.2.jar
MyJarFile.jar

Contenido de MyJarFile.jar#META-INF/MANIFEST.mf:

Manifest-Version: 1.0
Clase principal: com.algún paquete.MainClass
Class-Path: lib / commons-lang3-3.3.2.jar

 29
Author: Martin Andersson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:41

La solución de menor esfuerzo para mí fue hacer uso del gradle-shadow-plugin

Además de aplicar el plugin todo lo que hay que hacer es:

  • Configura la tarea jar para poner tu clase Principal en manifest

    jar { manifestar { los atributos Principales de la-Clase': 'com.mi.app.Principal' } }

  • Ejecutar la tarea gradle ./ gradlew shadowJar

  • Toma el app-version-all.tarro from build / libs/

Y finalmente ejecutarlo a través de:

java -jar app-version-all.jar
 17
Author: Ostkontentitan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-09 07:38:18

¿Has probado la tarea' installApp'? ¿No crea un directorio completo con un conjunto de scripts de inicio?

Http://www.gradle.org/docs/current/userguide/application_plugin.html

 5
Author: Jorge_B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-12 07:18:46

Puede definir un artefacto jar en la configuración del módulo (o estructura del proyecto).

  • Haga clic con el botón derecho en el módulo > Abrir configuración del módulo > Artefactos > + > JAR > desde módulos con dependencias.
  • Establece la clase main.

Hacer un frasco es tan fácil como hacer clic en "Construir artefacto"..."del menú Construir. Como beneficio adicional, puede empaquetar todas las dependencias en un solo jar.

Probado en IntelliJ IDEA 14 Ultimate.

 3
Author: Mondain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-08 13:04:53

Gracias Konstantin, funcionó como un encanto con pocos matices. Por alguna razón, especificar la clase main como parte del manifiesto jar no funcionó del todo y en su lugar quería el atributo mainClassName. Aquí hay un fragmento de build.gradle que incluye todo para que funcione:

plugins {
  id 'java' 
  id 'com.github.johnrengelman.shadow' version '1.2.2'
}
...
...
apply plugin: 'application'
apply plugin: 'com.github.johnrengelman.shadow'
...
...
mainClassName = 'com.acme.myapp.MyClassMain'
...
...
...
shadowJar {
    baseName = 'myapp'
}

Después de ejecutar gradle shadowJar, obtienes myapp-{version}-all.jar en su carpeta de compilación que se puede ejecutar como java-jar myapp - {version} - all.frasco.

 3
Author: Alex Yavorskiy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-06 19:40:10

Comprobé algunos enlaces para la solución, finalmente hice los pasos mencionados a continuación para que funcione. Estoy usando Gradle 2.9.

Realiza los siguientes cambios en tu archivo de compilación, gradle:

  1. Mencionar plugin:

    apply plugin: 'eu.appsatori.fatjar'
    
  2. Proporciona el Buildscript:

    buildscript {
    repositories {
        jcenter()
    }
    
    dependencies {
        classpath "eu.appsatori:gradle-fatjar-plugin:0.3"
    }
    }
    
  3. Proporcione la Clase Principal:

    fatJar {
      classifier 'fat'
      manifest {
        attributes 'Main-Class': 'my.project.core.MyMainClass'
      }
      exclude 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.SF'
    }
    
  4. Crea el fatjar:

    ./gradlew clean fatjar
    
  5. Ejecuta el fatjar desde / build / libs/:

    java -jar MyFatJar.jar
    
 2
Author: Sandeep Sarkar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-03 23:22:02