1

I'm trying to run a Groovy script from Java using GroovyClassLoader. Basically, what I do is this:

GroovyClassLoader groovyLoader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader());
clazz = groovyLoader.parseClass(myFile);
GroovyObject go = (GroovyObject) go.newInstance();
return go.invokeMethod("MyMethod", myObject);

The problem is that when I'm parsing the groovy file, my imports are not resolved even though the classes are in the Java classpath. If I add a line with:

groovyLoader.addClasspath("MyclassPath");

then everything works fine (this is our last resort in case we are unable to figure this out). This makes me think that there are two differents classpaths, one for Java and one for Groovy. But still, since I'm passing the Java classloader as a constructor argument for the GroovyClassloader, I'd think that if the classes are not found on the Groovy classpath, they should be looked up in Java's.

Am I wrong? Can someone shed some light on this?

Thank you.

Aurasphere
  • 3,841
  • 12
  • 44
  • 71
  • 2
    Does anything change when you don't pass in your own classloader but just use the default no-arg GroovyClassLoader constructor? – Gimby Jun 22 '16 at 15:24

2 Answers2

0

After lots of tests, I've figured out that the Groovy launched by Java has indeed the same classpath of the launching Java. The problem on the OP was caused by a configuration problem on our side.

For future readers, I recommend this question How to get classpath in Groovy? which gave a lot of help during the debugging process.

Community
  • 1
  • 1
Aurasphere
  • 3,841
  • 12
  • 44
  • 71
  • It does seem to, yes. I also wanted to point out that even when I added a classloader to Java to dynamically add a new jar file, those jar classes are usable in Groovy also with just a regular import *.*.* – Stan Towianski Jul 09 '19 at 02:28
0

Encountered similar problem with imports resolution. In my case switching to

new GroovyClassLoader(this.getClass().getClassLoader())

instead of

new GroovyClassLoader(Thread.currentThread().getContextClassLoader())

fixed the problem.

Note that according to the docs GroovyClassLoader() is equivalent to GroovyClassLoader(Thread.currentThread().getContextClassLoader()):

public GroovyClassLoader() creates a GroovyClassLoader using the current Thread's context Class loader as parent.

My actual situation was a Tomcat instance running a webapp which was supposed to load a groovy class from classpath and run a function from it, however the imports in groovy class failed to resolve at runtime. While debugging I noticed that classloaders for current thread and current class were different. I also used debugger evaluation feature to find out if a classloader is aware of particular class like so:

this.getClass().getClassLoader().classes.stream().filter(c -> c.getName().contains("YourClassInQuestion")).collect(Collectors.toList())

Also here is an explanation of the difference between class and thread classloaders.

Hope this helps. Thanks.

Alina Grosu
  • 253
  • 3
  • 8