Search code examples
javagradlegroovyuberjar

Compile a groovy script with all it's dependencies which are managed by gradle and then run it as a standalone application via the command line


I have a simple groovy script with a single java library dependency:

package com.mrhacki.myApp

import me.tongfei.progressbar.ProgressBar

    class Loading {        
        static void main(String[] arguments) {        
            List list = ["file1", "file2", "file3"]        
            for (String x : ProgressBar.wrap(list, "TaskName")) {
                println(x)
            }        
        }
    }

I'm using gradle to manage the dependencies of the project. The gradle configuration for the project is pretty straightforward too:

plugins {
    id 'groovy'
}

group 'com.mrhacki'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.codehaus.groovy:groovy-all:2.3.11'
    compile 'me.tongfei:progressbar:0.7.2'
}  

If I run the script from the Intellij IDE, the script is executed as expected.

What I would like to do now is to compile the script with this dependency into one single .jar file, so I can distribute it as such, and run the application from any filesystem path, as the script logic will be dependent on the path from which the execution was called.

I've tried with a few gradle fat jars examples out there but none have worked for me since the .jar file is constantly throwing Could not find or load main class Loading when I try it to run.

If anyone would be so kind to give a hint or to show an example of a gradle task that would do a build that fits my described needs I would be very gratefull.

I'm aware of the groovy module Grape with the @Grab annotation too, but I would leave that as a last resort since I don't want the users to wait for the dependencies download, and would like to bundle them with the app.

I'm using groovy 2.5.6 and gradle 4.10 for the project

Thanks


Solution

  • You can simply create the fat-jar yourself, without any extra plugin, using the jar Task. For a simple/small project like yours, it should be straightforward :

    jar {
        manifest {
            // required attribute "Main-Class"
            attributes "Main-Class": "com.mrhacki.myApp.Loading"
        }
    
        // collect (and unzip) dependencies into the fat jar
        from {
            configurations.compile.collect { 
                it.isDirectory() ? it : zipTree(it) 
            }
        }
    }
    

    EDIT : pleas take other comments into consideration: if you have more that one external lib you might have issues with this solution, so you should go for a solution with "shadow" plugins in this case.