groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Paul King <pa...@asert.com.au>
Subject Re: Grape and loading classes that extend java.lang.Exception from compiled Groovy bytecode
Date Mon, 27 Feb 2017 21:47:15 GMT
Is there a reason you don't want to use:

@GrabConfig(systemClassLoader=true)

along with your @Grab?

On Mon, Feb 27, 2017 at 7:51 PM, Alain Stalder <astalder@span.ch> wrote:
> Maybe someone can point me in the right direction regarding the following
> issue with Grape...
>
> Issue in code (in words further below):
>
> --
> import org.codehaus.groovy.control.CompilerConfiguration
>
> def demoScriptText = """\
> @Grab('org.apache.commons:commons-email:1.3.3')
> import org.apache.commons.mail.*
>
> try {
>   new SimpleEmail().send()
> } catch (EmailException e) {
>   // expected
>   return true
> }
> return false
> """
>
> // setup/clean target directory for script class
> File targetDir = new File('demo-target')
> if (!targetDir.exists()) {
>   assert targetDir.mkdir()
> }
> File classFile = new File(targetDir, 'Demo.class')
> if (classFile.exists()) {
>   assert classFile.delete()
> }
>
> // parse+run script with first GroovyClassLoader
> def config = new CompilerConfiguration()
> config.setTargetDirectory(targetDir)
> def loader1 = new
> GroovyClassLoader(Thread.currentThread().contextClassLoader, config)
> def script1 = loader1.parseClass(demoScriptText,
> 'Demo.groovy').newInstance()
> assert script1.run()
>
> // load compiled script class with second GroovyClassLoader
> def loader2 = new GroovyClassLoader()
> loader2.addClasspath(targetDir.path)
> try {
>   def script2 = loader2.loadClass('Demo').newInstance()
>   assert false
> } catch (NoClassDefFoundError e) {
>   println 'Failed as expected:'
>   println()
>   println e
>   println()
>   println e.stackTrace
> }
> --
>
> Issue in words:
>
> - Compile a script that uses Grape to load a dependency and use a class
>   that extends java.lang.Exception from that dependency in the script.
> - Loading and running that script with the GroovyClassLoader that compiled
>   it, works fine.
> - Then try to load the class from its class file (bytecode) with a new
>    GroovyClassLoader; this fails with a NoClassDefFoundError.
> - (Apparently has nothing specifically to do with commons-email, same effect
>   with Commons httpclient and an Exception class declared there.)
>
> The strange thing about this is that in the example above, EmailException is
> not found, but SimpleEmail - which is in the same grabbed JAR - is found!
> In fact, if I change the catch in the script to "catch (Exception e)", I can
> load and run the script from its class file without any problems.
>
> Question:
>
> Any ideas what could cause this, or where to look closer or maybe how to
> circumvent this by compiling the class differently?
>
> (My concrete use case is with Grengine, where I do not compile to a class
> in the file system, but to cached bytecode.)
>
> Alain
>
> --
>
> Here is the output I get (Groovy 2.4.8, JDK 1.8.0_121, Mac):
>
> Failed as expected:
>
> java.lang.NoClassDefFoundError: org/apache/commons/mail/EmailException
>
> [java.lang.Class.forName0(Native Method),
> java.lang.Class.forName(Class.java:348),
> org.codehaus.groovy.runtime.callsite.CallSiteArray$1.run(CallSiteArray.java:68),
> org.codehaus.groovy.runtime.callsite.CallSiteArray$1.run(CallSiteArray.java:65),
> java.security.AccessController.doPrivileged(Native Method),
> org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallStaticSite(CallSiteArray.java:65),
> org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallSite(CallSiteArray.java:162),
> org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48),
> org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113),
> org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117),
> demo.run(demo.groovy:37),
> groovy.lang.GroovyShell.runScriptOrMainOrTestOrRunnable(GroovyShell.java:263),
> groovy.lang.GroovyShell.run(GroovyShell.java:518),
> groovy.lang.GroovyShell.run(GroovyShell.java:497),
> groovy.lang.GroovyShell.run(GroovyShell.java:170),
> groovy.lang.GroovyShell$run$1.call(Unknown Source),
> groovy.ui.Console$_runScriptImpl_closure16.doCall(Console.groovy:1005),
> groovy.ui.Console$_runScriptImpl_closure16.doCall(Console.groovy),
> sun.reflect.GeneratedMethodAccessor296.invoke(Unknown Source),
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43),
> java.lang.reflect.Method.invoke(Method.java:498),
> org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93),
> groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325),
> org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294),
> groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1027),
> groovy.lang.Closure.call(Closure.java:414),
> groovy.lang.Closure.call(Closure.java:408),
> groovy.lang.Closure.run(Closure.java:495),
> java.lang.Thread.run(Thread.java:745)]
>

Mime
View raw message