Solución:
Un archivo jar ejecutable es solo un archivo jar que contiene una entrada de clase principal en su manifiesto. Entonces 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 deba agregar entradas de classpath en el manifiesto, pero eso se haría de la misma manera.
Ver http://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html
Las respuestas de JB Nizet y Jorge_B son correctas.
En su forma más simple, crear un JAR ejecutable con Gradle es solo una cuestión de agregar las entradas apropiadas al manifiesto. Sin embargo, es mucho más común tener dependencias que deben incluirse en la ruta de clases, 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 la ejecución de la aplicación directamente desde la compilación - un
installDist
tarea que genera una estructura de directorio que incluye el JAR construido, todos los JAR de los que depende y un script de inicio que lo reúne todo en un programa que puede ejecutar -
distZip
ydistTar
tareas que crean archivos que contienen una distribución completa de la aplicación (scripts de inicio y JAR)
Un tercer enfoque es crear un “JAR gordo”, que es un JAR ejecutable que incluye no solo el código de su componente, sino también todas sus dependencias. Hay algunos complementos diferentes que utilizan este enfoque. He incluido enlaces a algunos que conozco; Seguro que hay más.
- sombra
- un frasco
- bota de primavera
- cápsula
Como han señalado otros, para que un archivo jar sea ejecutable, el punto de entrada de la aplicación debe establecerse en el Main-Class
atributo del archivo de manifiesto. Si los archivos de la clase de dependencia no están colocados, deben configurarse en el Class-Path
entrada del archivo de manifiesto.
He probado todo tipo de combinaciones de complementos y qué no por la simple tarea de crear un jar ejecutable y de alguna manera, incluir las dependencias. Todos los complementos parecen faltar de una forma u otra, pero finalmente lo obtuve como quería. Sin 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: ni un millón de archivos de clase de terceros extranjeros fusionados en mi archivo jar.
Lo siguiente es una copia y pegado de aquí para su conveniencia.
[How-to] crear un archivo zip de distribución con jarras de dependencia en el subdirectorio /lib
y agregue todas las dependencias a Class-Path
entrada en el archivo de manifiesto:
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 una esencia 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
:
Versión de manifiesto: 1.0
Clase principal: com.somepackage.MainClass
Ruta de clase: lib / commons-lang3-3.3.2.jar