PS: Below is what I get when I look at the Demo.class with the "JD"
decompiler...
Is this maybe some kind of Grape concurrency issue similar to GROOVY-7407?
https://issues.apache.org/jira/browse/GROOVY-7407
(I still get the same result when I am applying the workaround listed
there - which I wrote myself, by the way - but maybe the workaround does
not cover all possibilities?)
import groovy.grape.Grape;
import groovy.lang.Binding;
import groovy.lang.Script;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.SimpleEmail;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.callsite.CallSite;
public class Demo extends Script
{
public Demo()
{
Demo this;
CallSite[] arrayOfCallSite = $getCallSiteArray();
}
public Demo(Binding context)
{
super(context);
}
public static void main(String[] args)
{
CallSite[] arrayOfCallSite = $getCallSiteArray();
arrayOfCallSite[0].call(InvokerHelper.class, Demo.class, args);
}
public Object run()
{
CallSite[] arrayOfCallSite = $getCallSiteArray();
try { try {
arrayOfCallSite[1].call(arrayOfCallSite[2].callConstructor(SimpleEmail.class));
} catch (EmailException e)
{
return Boolean.valueOf(true);
} } finally { }
return Boolean.valueOf(false); return null;
}
static
{
$getCallSiteArray()[3].callStatic(Grape.class,
ScriptBytecodeAdapter.createMap(new Object[0]),
ScriptBytecodeAdapter.createMap(new Object[] { "group",
"org.apache.commons", "module", "commons-email", "version", "1.3.3" }));
}
}
On 27.02.17 10:51, Alain Stalder 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)]
.