Gradle: sin atributo de manifiesto principal

91

Me estoy volviendo loco con este error que obtengo cuando ejecuto un archivo JAR creado en Gradle. El error dice "ningún atributo de manifiesto principal, en RxJavaDemo.jar" Intenté manipular la propiedad Manifest pero creo que me olvido de agregar las dependencias o algo. ¿Qué estoy haciendo mal exactamente?

apply plugin: 'java'
apply plugin: 'application'

mainClassName = 'demo.MainDashboard'

dependencies {
    compile files ("H:/Processes/Development/libraries/hikari-cp/HikariCP-2.4.1.jar")
    compile files ("H:/Processes/Development/libraries/controls-fx/controlsfx.jar")
    compile files ("H:/Processes/Development/libraries/database_connections/sqlite-jdbc-3.8.6.jar")
    compile files ("H:/Processes/Development/libraries/guava/guava-18.0.jar")
    compile files ("H:/Processes/Development/libraries/rxjava/rxjava-1.0.12.jar")
    compile files ("H:/Processes/Development/libraries/rxjava-extras/rxjava-extras-0.5.15.jar")
    compile files ("H:/Processes/Development/libraries/rxjavafx/RxJavaFX-1.0.0-RC1-SNAPSHOT.jar")
    compile files ("H:/Processes/Development/libraries/rxjavaguava/rxjava-guava-1.0.3.jar")
    compile files ("H:/Processes/Development/libraries/rxjava-jdbc/rxjava-jdbc-0.6.3.jar")
    compile files ("H:/Processes/Development/libraries/slf4j/slf4j-api-1.7.12.jar")
    compile files ("H:/Processes/Development/libraries/tom-commons/tom-commons.jar")
}

sourceSets {
    main.java.srcDir "src/main/java"
    main.resources.srcDir "src/main/resources"
}

jar { 
    manifest {
    attributes(
        "Class-Path": configurations.compile.collect { it.getName() }.join(' '))
    }
    from configurations.compile.collect { entry -> zipTree(entry) }
}
tmn
fuente

Respuestas:

142

Intente cambiar los atributos de su manifiesto como:

jar {
  manifest {
    attributes(
      'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
      'Main-Class': 'hello.HelloWorld'
    )
  }
}

Y luego simplemente cambie 'hello.helloWorld'a '<your packagename>.<the name of your Main class>'(donde su clase Main tiene un método principal). En este caso, crea en su manifiesto un atributo, que apunta a esta clase, luego se está ejecutando un jar.

Stanislav
fuente
1
@Stanislav ¿El valor 'Main-Class' es la clase principal? ¿Qué son hello y helloWorld en tu ejemplo?
Daniela Maia
2
@DanielaMaia es solo un nombre de clase calificado completo, seguro que debe escribirse como hello.HelloWorld, donde hello es el paquete donde se encuentra la clase HelloWorld
Stanislav
9
Necesitaba quitar la collect {}porción para que funcionara para mí. Su código asume que todas las dependencias están en la misma carpeta que su clase principal.
AutonomousApps
1

FWIW: utilicé la siguiente tarea jar para ensamblar todas mis dependencias de compilación en el archivo jar y utilicé la recomendación anterior para configurar correctamente la ruta de clase

apply plugin: 'java-library'

jar {
  manifest {
    attributes(
      'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
      'Main-Class': 'your.main.class.goes.here'
    )
  }

  // You can reference any part of the dependency configurations,
  // and you can have as many from statements as you need
  from configurations.compile  
  // I just copied them into the top of the jar, so it looks like the eclipse exported 
  // runnable jar, but you could designate a lib directory, and reference that in the 
  // classpath as "lib/$it.name" instead of it.getName()
  into ''   
}
Eric Hallander
fuente
0

Para hacer que el jararchivo sea ejecutable (para que java -jarfuncione el comando), especifique el Main-Classatributo en MANIFEST.MF.

En Gradle, puede hacerlo configurando la jartarea.

  • para Groovy DSL vea estas respuestas ( [1] , [2] )
  • para Kotlin DSL, puede utilizar el siguiente fragmento de código:
tasks.withType<Jar> {
    manifest {
        attributes["Main-Class"] = "com.caco3.Main"
    }
}

¿ mainClassNamePor qué no funciona como se esperaba?

¿O por qué mainClassNameno especifica el atributo en el manifiesto?

los mainClassName propiedad proviene del applicationcomplemento . El complemento:

hace que sea fácil iniciar la aplicación localmente durante el desarrollo y empaquetar la aplicación como TAR y / o ZIP incluidos los scripts de inicio específicos del sistema operativo .

Entonces el application plug-in no tiene como objetivo producir ejecutables jars

Cuando un mainClassName establece propiedad, entonces:

  1. $ ./gradlew runlanzará el mainmétodo en la clase especificada en el atributo
  2. el archivo zip/ tarconstruido usando distZip/distTar tasks contendrá un script, que lanzará el mainmétodo de la clase especificada anteriormente.

Aquí está la línea de script de shell que configura la clase principal:

$ grep Main2 gradletest
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLETEST_OPTS -classpath "\"$CLASSPATH\"" com.caco3.gradletest.Main2 "$APP_ARGS"
Denis Zavedeev
fuente