Gradle - no main manifest attribute

JavaGradleJar

Java Problem Overview


I'm building a JAR file with Gradle. When I try to run it I get the following error

> no main manifest attribute, in RxJavaDemo.jar

I tried manipulating the manifest property but I think I'm forgetting to add the dependencies or something to it. What exactly am I doing wrong?

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

Java Solutions


Solution 1 - Java

Try to change your manifest attributes like:

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

And then just change 'hello.helloWorld' to '<your packagename>.<the name of your Main class>' (where your Main class has a main method). In this case, you make in your manifest an attribute, which point to this class, then a jar is running.

Solution 2 - Java

To make the jar file executable (so that the java -jar command works), specify the Main-Class attribute in MANIFEST.MF.

In Gradle, you can do it by configuring the jar task.

  • for Groovy DSL see these answers ([1], [2])
  • for Kotlin DSL you can use the following code snippet:
tasks.withType<Jar> {
    manifest {
        attributes["Main-Class"] = "com.caco3.Main"
    }
}
Why mainClassName does not work as expected?

Or why mainClassName does not specify the attribute in the manifest?

The mainClassName property comes from the application plugin. The plugin:

> makes it easy to start the application locally during development, and to package the application as a TAR and/or ZIP including operating system specific start scripts.

So the application plugin does not aim at producing executable jars

When a mainClassName property set, then:

  1. $ ./gradlew run will launch the main method in the class specified in the attribute
  2. the zip/tar archive built using distZip/distTar tasks will contain a script, which will launch the main method of the specified previously class.

Here is the line of shell script setting the main class:

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

Solution 3 - Java

FWIW - I used the following jar task to assemble all my compile dependencies into the jar file, and used the above recommendation to get the class-path properly set

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 ''   
}

Solution 4 - Java

To complement Denis Zavedeev answer, here are more ways for Kotlin DSL (build.gradle.kts):

tasks.jar {
    manifest.attributes["Main-Class"] = "com.example.MyMainClass"
}
tasks.jar {
    manifest {
        attributes["Main-Class"] = "com.example.MyMainClass"
    }
}

Side note: to create a runnable fat JAR (also called uber JAR), see this post.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiontmnView Question on Stackoverflow
Solution 1 - JavaStanislavView Answer on Stackoverflow
Solution 2 - JavaDenisView Answer on Stackoverflow
Solution 3 - JavaEric HallanderView Answer on Stackoverflow
Solution 4 - JavaMahozadView Answer on Stackoverflow