Failure to load properly Groovy library into Groovy shell executing script

293 views Asked by At

My software used groovy.lang Java package to execute Groovy scripts from a shell, binding the variables in the script to Java objects.

A typical script looks like:

package packagename

// import Java classes


abstract class MyClass extends Script {
    def myfunction() {
    }
}

in this example, 'myfunction' will be called from the outside.

The scripts (located at the file system) are loaded by the following sequence from Java - the code returns GroovyShell class instance:

GroovyClassLoader groovyClassLoader = new GroovyClassLoader(...)
File groovyFile = new File(groovyURL.toURI());
Class<?> groovyClass = groovyClassLoader.parseClass(groovyFile);
CompilerConfiguration groovyConfig = new CompilerConfiguration();
groovyConfig.setScriptBaseClass(groovyClass.getName());
return new GroovyShell(groovyClassLoader, new Binding(), groovyConfig);

My design goal is to add a Groovy library that can be shared between scripts My preference is to implement a class (adding lines into the existing script seems to be a hack).

I made a simple class representing the library code. Right now, it looks like:

package shared

class MySharedLib
{
    static def testFunction()
    {
        return "test";
    }
}

To make sure the class it loaded, I added a call to

groovyClassLoader.parseClass(groovyLibraryFile)

before loading the actual script by:

groovyClassLoader.parseClass(groovyFile);

Now, from the script, I can call the library:

shared.MySharedLib.testFunction()

indeed return the string "test".

However, when trying to do the import via:

import shared.MySharedLib

in the script (before class definition) - I always got an error when loading the script:

Exception in thread "main" org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
script754084858.groovy: 14: unable to resolve class shared.MySharedLib
 @ line 14, column 1.

Tried to modify the classpath, it did not help. I realize something is wrong with my setup. Will appreciate any tip how to load a Groovy library in the correct way.

Max

1

There are 1 answers

0
Max On

Thanks for comments. I think I understand the cause. It turns out that at some point, the "script" is being compiled using

GroovyClassLoader classLoader = new GroovyClassLoader(parentClassLoader);
GroovyCodeSource codeSource = new GroovyCodeSource(code, scriptClassName + ".groovy", "/groovy/script");
CompilationUnit cu = new CompilationUnit(classLoader);
cu.addSource(codeSource.getName(), codeSource.getScriptText());
cu.compile(CompilePhase.CLASS_GENERATION.getPhaseNumber());

The compilation fails when reaching the "import" statement, since the library class is not in the classpath, so it's unreachable.

Calling classLoader.addClasspath(path) with the appropriate path solves the issue. So the problem was related to compilation - not to execution.