Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Works for Me
-
2.4.4
-
None
-
Java web app on either Apache on Linux or Windows, or WebSphere on AIX. Java 7.1. Groovy via ScriptEngineManager.getEngineByName("groovy")
Description
Just updated from Groovy 2.3.6 to 2.4.4 and this code no longer works when dynamic invocation is used (works fine when indy not used):
d1.setIndexes(new HashMap<List<String>,DatasetIndex>());
where d1 is one of the Java classes imported to the Groovy script. setIndexes is just a plain setter of a field on the class. The error is
BUG! Unknown transformation for argument <... stuff from toString of d1 here...> at position 0 with class com.ibm.cayce.sdv.dataset.Dataset for parameter of type class org.codehaus.groovy.vmplugin.v7.IndyInterface
It contains no stack trace, but by searching for sources of "Unknown transformation for argument", I found it to be in TypeTransformer.addTransformer. If I put a breakpoint there, this is the call stack:
TypeTransformers.addTransformer(MethodHandle, int, Object, Class) line: 124
Selector$MethodSelector.correctCoerce() line: 793
Selector$MethodSelector.setCallSiteTarget() line: 958
IndyInterface.selectMethod(MutableCallSite, Class, String, int, Boolean, Boolean, Boolean, Object, Object[]) line: 214
Script2.run() line: 2
GroovyScriptEngineImpl.eval(Class, ScriptContext) line: 323
GroovyScriptEngineImpl.eval(String, ScriptContext) line: 124
GroovyScriptEngineImpl(AbstractScriptEngine).eval(String) line: 276
Looks like TypeTransformer was introduced via org.codehaus.groovy.vmplugin.v7 in version 2.3.8, but I don't see anything in the 2.3.8 change log about it (at least not under an obvious description).
FWIW, we turn on dynamic invocation via:
CompilerConfiguration configuration = new CompilerConfiguration(); configuration.setTargetBytecode(System.getProperty("java.specification.version"));
configuration.getOptimizationOptions().put("indy", true);
configuration.getOptimizationOptions().put("int", false);
configuration.addCompilationCustomizers(importCustomizer,secureCustomizer);
GroovyClassLoader gcl = new GroovyClassLoader(this.getClass().getClassLoader(), configuration);
((GroovyScriptEngineImpl) engine).setClassLoader(gcl);
Please let me know if any more info is needed, or if there is a work around (other than not using indy).