I have read how to simply import a groovy file in another groovy script
I want to define common functions in one groovy file and call those functions from other groo
I think that the best choice is to organize utility things in form of groovy classes, add them to classpath and let main script refer to them via import keyword.
Example:
scripts/DbUtils.groovy
class DbUtils{
def save(something){...}
}
scripts/script1.groovy:
import DbUtils
def dbUtils = new DbUtils()
def something = 'foobar'
dbUtils.save(something)
running script:
cd scripts
groovy -cp . script1.groovy
After some investigation I have come to the conclusion that the following approach seems the best.
some/subpackage/Util.groovy
@GrabResolver(name = 'nexus', root = 'https://local-nexus-server:8443/repository/maven-public', m2Compatible = true)
@Grab('com.google.errorprone:error_prone_annotations:2.1.3')
@Grab('com.google.guava:guava:23.0')
@GrabExclude('com.google.errorprone:error_prone_annotations')
import com.google.common.base.Strings
class Util {
void msg(int a, String b, Map c) {
println 'Message printed by msg method inside Util.groovy'
println "Print 5 asterisks using the Guava dependency ${Strings.repeat("*", 5)}"
println "Arguments are a=$a, b=$b, c=$c"
}
}
example.groovy
#!/usr/bin/env groovy
Class clazz = new GroovyClassLoader().parseClass("${new File(getClass().protectionDomain.codeSource.location.path).parent}/some/subpackage/Util.groovy" as File)
GroovyObject u = clazz.newInstance()
u.msg(1, 'b', [a: 'b', c: 'd'])
In order to run the example.groovy
script, add it to your system path and type from any directory:
example.groovy
The script prints:
Message printed by msg method inside Util.groovy
Print 5 asterisks using the Guava dependency *****
Arguments are a=1, b=b, c=[a:b, c:d]
The above example was tested in the following environment: Groovy Version: 2.4.13 JVM: 1.8.0_151 Vendor: Oracle Corporation OS: Linux
The example demonstrates the following:
Util
class inside a groovy script.Util
class calling the Guava
third party library by including it as a Grape
dependency (@Grab('com.google.guava:guava:23.0')
).Util
class can reside in a subdirectory.Util
class.Additional comments/suggestions:
new Util()
, but most importantly it would have to be placed in a file named anything but Util.groovy. Refer to Scripts versus classes for more details about the differences between groovy scripts and groovy classes."${new File(getClass().protectionDomain.codeSource.location.path).parent}/some/subpackage/Util.groovy"
instead of "some/subpackage/Util.groovy"
. This will guarantee that the Util.groovy
file will always be found in relation to the groovy script's location (example.groovy
) and not the current working directory. For example, using "some/subpackage/Util.groovy"
would result in searching at WORK_DIR/some/subpackage/Util.groovy
.myScript.groovy
is a script name, and MyClass.groovy
is a class name. Naming my-script.groovy
will result in runtime errors in certain scenarios because the resulting class will not have a valid Java class name.A combination of @grahamparks and @snowindy answers with a couple of modifications is what worked for my Groovy scripts running on Tomcat:
Utils.groovy
class Utils {
def doSth() {...}
}
MyScript.groovy:
/* import Utils --> This import does not work. The class is not even defined at this time */
Class groovyClass = new GroovyClassLoader(getClass().getClassLoader()).parseClass(new File("full_path_to/Utils.groovy")); // Otherwise it assumes current dir is $CATALINA_HOME
def foo = groovyClass.newInstance(); // 'def' solves compile time errors!!
foo.doSth(); // Actually works!
For late-comers, it appears that groovy now support the :load file-path
command which simply redirects input from the given file, so it is now trivial to include library scripts.
It works as input to the groovysh & as a line in a loaded file:
groovy:000> :load file1.groovy
file1.groovy can contain:
:load path/to/another/file
invoke_fn_from_file();
Groovy can import other groovy classes exactly like Java does. Just be sure the extension of the library file is .groovy.
$ cat lib/Lib.groovy
package lib
class Lib {
static saySomething() { println 'something' }
def sum(a,b) { a+b }
}
$ cat app.gvy
import lib.Lib
Lib.saySomething();
println new Lib().sum(37,5)
$ groovy app
something
42
How about treat the external script as a Java class? Based on this article: https://www.jmdawson.net/blog/2014/08/18/using-functions-from-one-groovy-script-in-another/
getThing.groovy The external script
def getThingList() {
return ["thing","thin2","thing3"]
}
printThing.groovy The main script
thing = new getThing() // new the class which represents the external script
println thing.getThingList()
Result
$ groovy printThing.groovy
[thing, thin2, thing3]