how to export a executable jar in gradle, and this jar can run as it include reference libraries

前端 未结 5 2283
长情又很酷
长情又很酷 2020-12-25 10:15

how to export a executable jar in gradle, and this jar can run as it include reference libraries.

build.gradle

apply plugin: \'java\'

manifest.mainA         


        
5条回答
  •  眼角桃花
    2020-12-25 11:00

    Hopefully this helps someone (as I unfortunately spent quite some time trying to find the solution). Here's the solution that worked for me for creating an executable JAR. I'm embedding Jetty in the main method, Jetty 9 to be specific and using Gradle 2.1.

    Include the following code into your build.gradle file (if a subproject is the "main" project that the jar needs to be built from, then add it to the subproject which should start like this project(':') { insert the code somewhere here, after dependencies.}.

    Also, you need to add the plugin java for this to work: apply plugin: 'java' .

    My jar task looks as follows:

    apply plugin: 'java'
    
    jar {
    
        archiveName = "yourjar.jar"
    
        from {
    
            configurations.runtime.collect {
                it.isDirectory() ? it : zipTree(it)
            }
    
            configurations.compile.collect {
                it.isDirectory() ? it : zipTree(it)
            }
        }
    
        manifest {
            attributes 'Main-Class': 'your.package.name.Mainclassname'
        }
    
        exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
    }
    

    And then you can execute your yourjar.jar via the commandline:

    java -jar yourjar.jar
    

    The META-INF/.RSA, META-INF/.SF and META-INF/*.DSA have to be excluded for it to work. Otherwise a SecurityException gets thrown.

    The problem seems to lie with embedded Jetty, as Jetty moved to Eclipse and now is signing their JARs, which I read becomes problematic when other, unsigned JARs want to load the signed ones. Please feel free to educate me if I am wrong in this, that's just what I read.

    The JARs that the project depends on are defined in the dependencies as follows:

    dependencies {
    
        // add the subprojects / modules that this depends on
        compile project(':subproject-1')
        compile project(':subproject-2')
    
        compile group: 'org.eclipse.jetty', name: 'jetty-server', version: '9.2.6.v20141205'
        compile group: 'org.eclipse.jetty', name: 'jetty-servlet', version: '9.2.6.v20141205'
        compile group: 'org.eclipse.jetty', name: 'jetty-http', version: '9.2.6.v20141205'
    
    }
    

    EDIT: Before, instead of just

    configurations.runtime.collect{...}
    

    i had

    configurations.runtime.asFileTree.files.collect{...}
    

    This caused strange behaviour in a larger project in clean build. When running the jar after executing gradle clean build for the first time (after manually cleaning the build directory), it would throw a NoClassDefFoundException (in our project with many subprojects), but running the jar after executing gradle clean build a second time (without emptying the build directory manually), for some reason it had all dependencies. This didn't happen if asFileTree.files was left out.

    Also I should note, all compile dependencies are included in runtime, however not all runtime are included in compile. So if you are just using compile

            configurations.compile.collect {
                it.isDirectory() ? it : zipTree(it)
            }
    

    Then be sure to remember that if there is a NoClassDefFoundException thrown, some class isn't found at runtime, which means you should also include this:

            configurations.runtime.collect {
                it.isDirectory() ? it : zipTree(it)
            }
    

提交回复
热议问题