groovy
groovy copied to clipboard
GROOVY-8096 setScriptBaseClass with Java class breaks @Field Binding init due to call to super() instead of super(Binding)
This test fails because ClassNode.getSuperClass().getDeclaredConstructor(SCRIPT_CONTEXT_CTOR)
doesn't see the constructors in the Java base class.
ModuleNode.setScriptBaseClassFromConfig(ClassNode)
calls .setSuperClass(ClassHelper.make(baseClassName))
on the scriptDummy
ClassNode
.
The ClassNode
created for this script's base class has .lazyInitDone = true
and .constructors = null
so when .getSuperClass().getDeclaredConstructor(SCRIPT_CONTEXT_CTOR)
is called by ModuleNode.createStatementsClass()
, then ClassNode.constructors
is set to an empty ArrayList in ClassNode.getDeclaredConstructors()
The script constructor is then generated as
Constructor(Binding context) {
super(); // Fields are initialized after the call to super()
// Fields are initialized here
setBinding(context); // Fields are initialized before the call to setBinding(context)
}
instead of
Constructor(Binding context) {
super(context); // Fields are initialized after the call to super(context)
}
Fields are initialized between the call to super() and the setBinding(context) which means Field initializers don't have access to the Binding context.
This leads to MissingPropertyException
because we're trying to look up variables from the new Binding()
created in the default constructor, instead of the binding we passed in.
Created JIRA ticket at https://issues.apache.org/jira/browse/GROOVY-8096
Just to clarify - this isn't a PR designed to fix a problem (although BindingScript might prove useful in a solution) but to illustrate a problem. Correct?
@paulk-asert Correct, this just adds a couple of unit tests to illustrate the problem. I hope you agree that it's better than just describing it. :)
I was able to make a patch myself where i use Class.forName() to look up the class, but i highly doubt it is correct.