[ https://issues.apache.org/jira/browse/GROOVY-8096?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17755586#comment-17755586 ]
Eric Milles commented on GROOVY-8096: ------------------------------------- One way to provide a resolved class via {{CompilerConfiguration}} is to apply the {{BaseScript}} transform, like this: {code:groovy} def config = new org.codehaus.groovy.control.CompilerConfiguration() config.addCompilationCustomizers(new org.codehaus.groovy.control.customizers.ASTTransformationCustomizer( groovy.transform.BaseScript, value: BindingScript )) //config.scriptBaseClass = BindingScript.name def scriptText = ''' @groovy.transform.Field def script_args = getProperty('args') assert script_args[0] == 'Hello Groovy' script_args[0] ''' def arg0 = 'Hello Groovy' def shell = new GroovyShell(config) def result = shell.run scriptText, 'TestBindingsInFieldInitializersWithConfigJavaBaseScript.groovy', [arg0] assert result == arg0 {code} You could also add this as the first line of your script source: "@groovy.transform.BaseScript BindingScript superClass" > setScriptBaseClass with Java base class breaks @Field initialization from > Binding due to generated call to wrong constructor > ---------------------------------------------------------------------------------------------------------------------------- > > Key: GROOVY-8096 > URL: https://issues.apache.org/jira/browse/GROOVY-8096 > Project: Groovy > Issue Type: Bug > Components: Compiler, GroovyScriptEngine > Affects Versions: 2.4.8 > Reporter: Christoffer Hammarström > Priority: Major > Labels: test > > I created a pull request on GitHub with a failing test showing the problem: > [https://github.com/apache/groovy/pull/502] > This test fails because {{ModuleNode.createStatementsClass()}} calls > {{.getSuperClass().getDeclaredConstructor(SCRIPT_CONTEXT_CTOR)}} and gets > {{null}} back, though the constructor does exist! > {{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}} > {{ModuleNode.createStatementsClass()}} calls > {{.getSuperClass().getDeclaredConstructor(SCRIPT_CONTEXT_CTOR)}} > Then {{ClassNode.constructors}} is set to an empty ArrayList in > {{ClassNode.getDeclaredConstructors()}}, insteaf of looking them up from the > Java class. > The script constructor is then generated in > {{ModuleNode.createStatementsClass()}} as: > *BROKEN BEHAVIOUR* > {code:java} > Constructor(Binding context) { > super(); // Fields are initialized after the call to > super() > // Fields are initialized here with new > Binding() instead of context > setBinding(context); // This is too late, fields are initialized > after super(), before this call to setBinding > } > {code} > instead of > *EXPECTED BEHAVIOUR* > {code:java} > Constructor(Binding context) { > super(context); // Fields are initialized after the call to > super(context) > } > {code} > We're calling the default constructor in the base class with {{super()}}, > instead of passing along the {{Binding context}} with {{super(context)}} > This breaks initialization of Fields that depend on the {{Binding context}}, > because Fields are initialized between the call to {{super()}} and the > {{setBinding(context)}}: [http://stackoverflow.com/a/14806340/233014] > 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. > For convenience, here is the failing test: > {code:java|title=GroovyShellTest2.groovy} > void testBindingsInFieldInitializersWithConfigJavaBaseScript() { > def config = new org.codehaus.groovy.control.CompilerConfiguration() > config.scriptBaseClass = BindingScript.class.name > def shell = new GroovyShell(config); > def scriptText = ''' > @groovy.transform.Field def script_args = getProperty('args') // > Will get MissingPropertyException here because this @Field is initialized > after the call to super(), before the call to setBinding in the script > constructor > assert script_args[0] == 'Hello Groovy' > script_args[0] > ''' > def arg0 = 'Hello Groovy' > def result = shell.run scriptText, > 'TestBindingsInFieldInitializersWithConfigJavaBaseScript.groovy', [arg0] > assert result == arg0 > } > {code} > and the Java script base class: > {code:java|title=BindingScript.java} > package groovy.lang; > /** > * A Script which requires a Binding passed in the constructor and disallows > calling the default constructor. > */ > public abstract class BindingScript extends Script { > // Making the default constructor private instead gives IllegalAccessError > // Removing the default constructor instead gives NoSuchMethodError > // Removing both constructors just calls to the default constructor in > groovy.lang.Script giving MissingPropertyException on field initialization > protected BindingScript() { > // This constructor erroneously gets called instead of the other one > } > > protected BindingScript(Binding binding) { > super(binding); > // This is the constructor that should have been called, because then > the binding would have been passed in the above call, before @Fields are > initialised. > } > } > {code} -- This message was sent by Atlassian Jira (v8.20.10#820010)