You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@groovy.apache.org by Michael Rüegg <ru...@gmail.com> on 2016/03/24 13:39:37 UTC

ClassLoader issue when loading custom DSL with GroovyScriptEngine

Hi,

I have a problem with parsing my own DSL when using GroovyScriptEngine. Here’s the code:

class DslLoader {

 def load(String dsl) {
   CompilerConfiguration config = new CompilerConfiguration(CompilerConfiguration.DEFAULT)
   config.scriptBaseClass = MyBaseScript.class.name
   ClassLoader parentClassLoader = DslScriptLoader.classLoader
   GroovyClassLoader groovyClassLoader = new GroovyClassLoader(parentClassLoader, config)
   assert parentClassLoader.loadClass('groovy.lang.GroovyObject') != null // NO PROBLEMS HERE
   URL url = new File(‘path/to/my-dsl.jar').toURI().toURL()
   URL[] urlRoots = [url]
   GroovyScriptEngine engine = new GroovyScriptEngine(urlRoots, groovyClassLoader)
   assert engine.groovyClassLoader.loadClass('groovy.lang.GroovyObject') != null // NO PROBLEMS HERE
   Class clazz = engine.groovyClassLoader.parseClass(dsl, 'script’) // HERE I GET java.lang.ClassNotFoundException: groovy.lang.GroovyObject
   script = InvokerHelper.createScript(clazz, new Binding())
 }

}


As you can see from the comments, I’m able to load the class ‘groovy.lang.GroovyObject’ when using the same class loader I pass to GroovyScriptEngine. But when I call parseClass(), my application fails with a 

java.lang.ClassNotFoundException: groovy.lang.GroovyObject

The code above is part of an OSGI bundle which is deployed to a container. groovy-all.jar is on the bundle class path: 

Bundle-ClassPath: .,META -INF/lib/groovy-all-2.4.4.jar 

I don’t understand why GroovyScriptEngine is not able to load Groovy’s own classes although the passed class loader can do it. Am I overlooking something? Do you have an idea what is wrong?

Thanks in advance,
Michael

Re: ClassLoader issue when loading custom DSL with GroovyScriptEngine

Posted by Michael Rüegg <ru...@gmail.com>.
Hi,

Thanks for your answer.

What finally worked was the following (note that I had to configure a parent class loader, otherwise I always got classnotfounds for Groovy’s classes like groovy.lang.Script):


CompilerConfiguration config = new CompilerConfiguration(CompilerConfiguration.DEFAULT)
config.scriptBaseClass = MyBaseScript.class.name
//        config.addCompilationCustomizers(new ASTTransformationCustomizer(TypeChecked))
ClassLoader parentClassLoader = DslScriptLoader.classLoader
GroovyClassLoader groovyClassLoader = new GroovyClassLoader(parentClassLoader, config)
Class<?> clazz = groovyClassLoader(dsl)
Object cc = clazz.newInstance();
Script script = (Script) cc;


What is still not working (because it throws NoClassDefFoundError: groovy/lang/GroovyObject) is adding the ASTTransformationCustomizer as commented out above. Do you know if that uses a different classloader?

Best regards,
Michael


> On 29 Mar 2016, at 09:29, Korbee Reinout <Re...@snb.ch> wrote:
> 
> I don't see why you need the GroovyScriptEngine. Maybe the GroovyShell would be the more appropriate choice to run scripts in this example? In a similar situation in an OSGi bundle I have used:
> 
> GroovyClassLoader GROOVY_CLASSLOADER = new GroovyClassLoader();
> Class<?> clazz = GROOVY_CLASSLOADER.parseClass(string_with_script_as_text);
> Object cc = clazz.newInstance();
> Script script = (Script) cc;
> 
> And then on the script you can just call: script.setBinding()
> 
> And to run I call: script.run(). 
> 
> 
> -----Original Message-----
> From: Michael Rüegg [mailto:rueegg.michael@gmail.com] 
> Sent: Donnerstag, 24. März 2016 13:40
> To: users@groovy.apache.org
> Cc: Michael Rüegg <ru...@gmail.com>
> Subject: ClassLoader issue when loading custom DSL with GroovyScriptEngine
> 
> Hi,
> 
> I have a problem with parsing my own DSL when using GroovyScriptEngine. Here’s the code:
> 
> class DslLoader {
> 
> def load(String dsl) {
>   CompilerConfiguration config = new CompilerConfiguration(CompilerConfiguration.DEFAULT)
>   config.scriptBaseClass = MyBaseScript.class.name
>   ClassLoader parentClassLoader = DslScriptLoader.classLoader
>   GroovyClassLoader groovyClassLoader = new GroovyClassLoader(parentClassLoader, config)
>   assert parentClassLoader.loadClass('groovy.lang.GroovyObject') != null // NO PROBLEMS HERE
>   URL url = new File(‘path/to/my-dsl.jar').toURI().toURL()
>   URL[] urlRoots = [url]
>   GroovyScriptEngine engine = new GroovyScriptEngine(urlRoots, groovyClassLoader)
>   assert engine.groovyClassLoader.loadClass('groovy.lang.GroovyObject') != null // NO PROBLEMS HERE
>   Class clazz = engine.groovyClassLoader.parseClass(dsl, 'script’) // HERE I GET java.lang.ClassNotFoundException: groovy.lang.GroovyObject
>   script = InvokerHelper.createScript(clazz, new Binding())  }
> 
> }
> 
> 
> As you can see from the comments, I’m able to load the class ‘groovy.lang.GroovyObject’ when using the same class loader I pass to GroovyScriptEngine. But when I call parseClass(), my application fails with a 
> 
> java.lang.ClassNotFoundException: groovy.lang.GroovyObject
> 
> The code above is part of an OSGI bundle which is deployed to a container. groovy-all.jar is on the bundle class path: 
> 
> Bundle-ClassPath: .,META -INF/lib/groovy-all-2.4.4.jar 
> 
> I don’t understand why GroovyScriptEngine is not able to load Groovy’s own classes although the passed class loader can do it. Am I overlooking something? Do you have an idea what is wrong?
> 
> Thanks in advance,
> Michael
> 
> This e-mail message contains confidential information and is intended only for the named recipient(s). If you are not an intended recipient, any disclosure, copying or distribution is prohibited. Please notify the sender immediately by e-mail if you have received this message in error and delete this message from your system. As internet communications are not secure, the Swiss National Bank accepts no liability for any errors or omissions in the contents of this message. Any views expressed in this message are those of the individual sender, except where the sender specifically states them to be the views of the Swiss National Bank.


RE: ClassLoader issue when loading custom DSL with GroovyScriptEngine

Posted by Korbee Reinout <Re...@snb.ch>.
I don't see why you need the GroovyScriptEngine. Maybe the GroovyShell would be the more appropriate choice to run scripts in this example? In a similar situation in an OSGi bundle I have used:

GroovyClassLoader GROOVY_CLASSLOADER = new GroovyClassLoader();
Class<?> clazz = GROOVY_CLASSLOADER.parseClass(string_with_script_as_text);
Object cc = clazz.newInstance();
Script script = (Script) cc;

And then on the script you can just call: script.setBinding()

And to run I call: script.run(). 


-----Original Message-----
From: Michael Rüegg [mailto:rueegg.michael@gmail.com] 
Sent: Donnerstag, 24. März 2016 13:40
To: users@groovy.apache.org
Cc: Michael Rüegg <ru...@gmail.com>
Subject: ClassLoader issue when loading custom DSL with GroovyScriptEngine

Hi,

I have a problem with parsing my own DSL when using GroovyScriptEngine. Here’s the code:

class DslLoader {

 def load(String dsl) {
   CompilerConfiguration config = new CompilerConfiguration(CompilerConfiguration.DEFAULT)
   config.scriptBaseClass = MyBaseScript.class.name
   ClassLoader parentClassLoader = DslScriptLoader.classLoader
   GroovyClassLoader groovyClassLoader = new GroovyClassLoader(parentClassLoader, config)
   assert parentClassLoader.loadClass('groovy.lang.GroovyObject') != null // NO PROBLEMS HERE
   URL url = new File(‘path/to/my-dsl.jar').toURI().toURL()
   URL[] urlRoots = [url]
   GroovyScriptEngine engine = new GroovyScriptEngine(urlRoots, groovyClassLoader)
   assert engine.groovyClassLoader.loadClass('groovy.lang.GroovyObject') != null // NO PROBLEMS HERE
   Class clazz = engine.groovyClassLoader.parseClass(dsl, 'script’) // HERE I GET java.lang.ClassNotFoundException: groovy.lang.GroovyObject
   script = InvokerHelper.createScript(clazz, new Binding())  }

}


As you can see from the comments, I’m able to load the class ‘groovy.lang.GroovyObject’ when using the same class loader I pass to GroovyScriptEngine. But when I call parseClass(), my application fails with a 

java.lang.ClassNotFoundException: groovy.lang.GroovyObject

The code above is part of an OSGI bundle which is deployed to a container. groovy-all.jar is on the bundle class path: 

Bundle-ClassPath: .,META -INF/lib/groovy-all-2.4.4.jar 

I don’t understand why GroovyScriptEngine is not able to load Groovy’s own classes although the passed class loader can do it. Am I overlooking something? Do you have an idea what is wrong?

Thanks in advance,
Michael

This e-mail message contains confidential information and is intended only for the named recipient(s). If you are not an intended recipient, any disclosure, copying or distribution is prohibited. Please notify the sender immediately by e-mail if you have received this message in error and delete this message from your system. As internet communications are not secure, the Swiss National Bank accepts no liability for any errors or omissions in the contents of this message. Any views expressed in this message are those of the individual sender, except where the sender specifically states them to be the views of the Swiss National Bank.