You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@groovy.apache.org by Thierry Hanser <Th...@lhasalimited.org> on 2016/03/08 17:31:39 UTC

Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)

Hi,

The following very simple code is behaving really strangely.
Could anyone please tell me if this is an issue in Groovy or something I am not doing properly (I would like to vote for the latter, yet...).

In Java

x='one';
System.out.println("init x: " + x);

In Groovy

println '1 = ' + x
x = 'two'
println '2 = ' + x

Output:

init x: one  <- initial value assignement OK

1 = one      <- successfully accessing 'x' from within the compiled script OK
                the Groovy script has picked up the value of the Java variable;
                the implicit getX() has been called

2 = one                <- should be 'two' as per Groovy code (second line)
                but is unchanged ???

It seems that the Groovy script can't change the value of 'x' (can't access setX()). However there is no compilation error ('x' is not read-only)
When implementing getX/setX methods, only the getter is called (in both print statements, line 1,3) but during the assignment instruction (line 2), the setter is silently ignored (the value of 'x' remains 'one' instead of 'two'.

The Java/Groovy binding is operational since the 'one' value of 'x' in the Java  base class is successfully retrieved. So could anyone please tell me where the issue is?
The confusing part is that even within in the Groovy context alone, the assignment 'x='two' is not honoured (and yet there are no compilation/runtime error)

Note that I tried all combinations of setters/getters/visibility and can at the best read but never modify the variable 'x'. The same behaviour occurs with using the GroovyScriptEngine or GroovyClassLoader

Thank you very much in advance for your help.

Thierry
-

PS: (I am not sure if my previous message went through as I was still in the mailing list registration process, apologies if it is a duplicate)

Full code:

import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer;

import groovy.lang.Binding;
import groovy.lang.Closure
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyShell;
import groovy.transform.CompileStatic;;

abstract class GroovyDemoScript extends Script
{
    public String x;

    public GroovyDemoScript()
    {
           x='one';
           System.out.println("init x: " + x);
    }

    public static void main(String...args) throws Throwable
    {
           ////
           // Compilation configuration
           CompilerConfiguration configuration = new CompilerConfiguration();
           configuration.addCompilationCustomizers(new ASTTransformationCustomizer(CompileStatic.class));

                                // make sure we use the Java base class where 'x' is defined
           configuration.setScriptBaseClass(GroovyDemoScript.class.name);

           GroovyShell shell = new GroovyShell(this.getClass().getClassLoader(), new Binding(), configuration);

           // source code
           String scriptSource= "println '1 = ' + x; x = 'two'; println '2 = ' + x\n";

           // compile the source code and run the compiled script
           GroovyDemoScript compiledScript = shell.parse(scriptSource);
           compiledScript.run();
    }
}


________________________________
Switchboard: +44 (0)113 394 6020
Technical Support: +44 (0)113 394 6030
________________________________
Lhasa Limited, a not-for-profit organisation, promotes scientific knowledge & understanding through the development of computer-aided reasoning & information systems in chemistry & the life sciences. Registered Charity Number 290866. Registered Office: Granary Wharf House, 2 Canal Wharf, Leeds, LS11 5PS. Company Registration Number 01765239. Registered in England and Wales.
This communication, including any associated attachments, is intended for the use of the addressee only and may contain confidential, privileged or copyright material. If you are not the intended recipient, you must not copy this message or attachment or disclose the contents to any other person. If you have received this transmission in error, please notify the sender immediately and delete the message and any attachment from your system. Except where specifically stated, any views expressed in this message are those of the individual sender and do not represent the views of Lhasa Limited. Lhasa Limited cannot accept liability for any statements made which are the sender's own. Lhasa Limited does not guarantee that electronic communications, including any attachments, are free of viruses. Virus scanning is recommended and is the responsibility of the recipient.

RE: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)

Posted by Thierry Hanser <Th...@lhasalimited.org>.
Apologies, I meant the binding variables are empty at start (x is not explicitly bound) yet the value of x is retrieved (as part of the base script class) and you are right Dinko, the assignment statement subsequently binds explicitly the variable [x:two] and by doing so somehow disconnects it from the original base script class which is the issues observed.



Interestingly when wrapping the code in a closure the assignment works properly (still creates a binding and keeps the link to the base class 'x' variable). Then if I create explicit getter/setter we fall back to the wrong behaviour, even within a closure.



Adding in the base script class:


    public Object process(Closure code)
    {
       System.out.println("Processing with x : " + x);
       return code.call();

    }



And in Groovy:



Process

{

   println '1 = ' + x

   x = x + 'two'

   println '2 = ' + x

}



Output:


init x: one

Processing with x : one
1 = one
2 = two



As expected



adding in the base class:


    public void setX(String value)
    {
       x = value;
       System.out.println("Setting x to : " + value + " => x = " + x);
    }

    public String getX()
    {
       System.out.println("Getting x : "  + x);
       return x;

    }



will produce again:


init x: one
Processing with x : one
Getting x : one
1 = one
Getting x : one

2 = one



Note that the getter is always properly called but the setter is never called.





Finally removing the setter (to test the compile time analysis) produces:


Script1.groovy: 1: [Static type checking] - Cannot set read-only property: x
@ line 1, column 29.

   process{println '1 = ' + x; x = 'two'; println '2 = ' + x


which is expected and demonstrate the acknowledgment of the setter setX() when present;

The issue is related to CompileChecked and can be  summarised in that the setter is acknowledged at compile time but not called at runtime.



(again using just TypeChecked instead of CompileStatic removes the problem which

tells us that the problem lies in CompileStatic as pointed by Jason)



Cheers



Thierry





-----Original Message-----
From: Dinko Srkoč [mailto:dinko.srkoc@gmail.com]
Sent: 09 March 2016 11:36
To: users@groovy.apache.org
Subject: Re: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)



On 9 March 2016 at 11:56, Thierry Hanser <Th...@lhasalimited.org>> wrote:

> Thank you for the suggestion Dinko.

>

> I tried your experiment and the binding variables set remains actually

> empty ([:]) which is what I expected since there is no explicit

> binding involved (the variable 'x' is directly declared in the base

> script which is the point of the approach)



Interestingly this is different from what I'm getting. The statement `x = 'two'` adds the value 'two' to the newly added binding variable `x` (with binding being empty before that statement).



Cheers,

Dinko



>

> An interesting hint to the problem is that if I explicitly implement the getter and don't have a setter, there will be indeed an expected 'can't change a read-only value' compilation error which means that the getter/setter status is correctly analysed in the compilation decision tree and the setter must be present (or implicit) in order to allow the assignment in line 2 (x = 'two'); the problem is that it is not invoked at runtime; i.e. at compilation time Groovy's understanding is correct but the compiled code does not actually invoke the setter.

>

> This is disturbing and concerning as it leads to unpredictable behaviour.

>

> Thierry

>

>

> -----Original Message-----

> From: Dinko Srkoč [mailto:dinko.srkoc@gmail.com]

> Sent: 08 March 2016 18:20

> To: users@groovy.apache.org<ma...@groovy.apache.org>

> Subject: Re: Failing to change the value of a Java variable from

> wihtin a Groovy script (potential issue?)

>

> On 8 March 2016 at 18:11, Thierry Hanser <Th...@lhasalimited.org>> wrote:

>>

>> Thank you  Jason, you were indeed right, without CompileStatic or using TypeChecked works.

>

> Well, it works, but probably not the way you think it works. Here's what you can do to get more insight into what's going on:

>

> * print the script's variable bindings - add to `scriptSource`:

> `println binding.variables`

> * access the field `x` directly - to `JavaScriptDemo` add a method like this:

>

>     public String myX() { return x; }

>

>   then print that as well: `println myX()`

> * run the script with and without `CompileStatic` and compare the

> results

>

> After running the experiment you'll probably notice that the field `x` is never really changed. When you try to add the value 'two' to `x` you're actually creating a new binding variable. The difference with CompileStatic is in accessing the field or the binding if binding exists.

>

> Cheers,

> Dinko

>

>>

>> This is concerning as I would prefer static compilation (type checking being a must).

>>

>>

>>

>> I can work around the issue in my context but it impacts the elegance of the underlying DSL.

>>

>> However from the Groovy script engine perspective it is more concerning.

>>

>>

>>

>> Maybe Cedric or Guy know if there are any known issues and planned fixes related to that problem?

>>

>>

>>

>> Thanks again Jason.

>>

>>

>>

>> Thierry

>>

>>

>>

>> ---

>>

>> PS:  There was a couple of typos in the source code (never post-edit in outlook ;-) ). Apologies for any inconveniences.

>>

>> Here is the correct adjusted and working code:

>>

>>

>>

>> import org.codehaus.groovy.control.CompilerConfiguration;

>>

>> import

>> org.codehaus.groovy.control.customizers.ASTTransformationCustomizer;

>>

>>

>>

>> import groovy.lang.Binding;

>>

>> import groovy.lang.GroovyShell;

>>

>> import groovy.lang.Script;

>>

>> import groovy.transform.CompileStatic;;

>>

>>

>>

>> public abstract class JavaScriptDemo extends Script

>>

>> {

>>

>>     public String x;

>>

>>

>>

>>     public JavaScriptDemo()

>>

>>     {

>>

>>            x="one";

>>

>>            System.out.println("init x: " + x);

>>

>>     }

>>

>>

>>

>>      /**

>>

>>      * Demo main

>>

>>      * @param args

>>

>>      * @throws Throwable

>>

>>      */

>>

>>     public static void main(String...args) throws Throwable

>>

>>     {

>>

>>            ////

>>

>>            // Compilation configuration

>>

>>            CompilerConfiguration configuration = new

>> CompilerConfiguration();

>>

>>            configuration.addCompilationCustomizers(new

>> ASTTransformationCustomizer(CompileStatic.class));

>>

>>

>> configuration.setScriptBaseClass(JavaScriptDemo.class.getName());

>>

>>            GroovyShell shell = new

>> GroovyShell(JavaScriptDemo.class.getClassLoader(), new Binding(),

>> configuration);

>>

>>

>>

>>            // source code

>>

>>            String scriptSource= "println '1 = ' + x; x = 'two';

>> println '2 = ' + x\n";

>>

>>

>>

>>            // compile the source code and run the compiled script

>>

>>            JavaScriptDemo compiledScript =

>> (JavaScriptDemo)shell.parse(scriptSource);

>>

>>         compiledScript.run();

>>

>>     }

>>

>> }

>>

>>

>>

>> From: Winnebeck, Jason [mailto:Jason.Winnebeck@windstream.com]

>> Sent: 08 March 2016 16:46

>> To: users@groovy.apache.org<ma...@groovy.apache.org>

>> Subject: RE: Failing to change the value of a Java variable from

>> wihtin a Groovy script (potential issue?)

>>

>>

>>

>> Unfortunately static compile can be pretty flaky at times and I run into bugs often with it and have to redesign code. For small scripts I would advise against it (if you need type checking, use TypeChecked). I’m wondering if the script is getting compiled to get field x from the base class but favors setting binding.x = ‘two’ in the script.

>>

>>

>>

>> I would try without static compilation and see if it works. If it does work without static compilation, upgrade to the very latest Groovy (2.4.6) as bugs are fixed in static compiler all the time. If that doesn’t fix the problem, then change the Java field to private and create a getX() and setX(String). If that doesn’t work and you still need static compile, try an explicit setX(‘two’) or this.x = ‘two’ in the script. Historically the static compiler has been more reliable when you are more explicit.

>>

>>

>>

>> Jason

>>

>>

>>

>> From: Thierry Hanser [mailto:Thierry.Hanser@lhasalimited.org]

>> Sent: Tuesday, March 08, 2016 11:32 AM

>> To: 'users@groovy.apache.org' <us...@groovy.apache.org>>

>> Subject: Failing to change the value of a Java variable from wihtin a

>> Groovy script (potential issue?)

>>

>>

>>

>> Hi,

>>

>>

>>

>> The following very simple code is behaving really strangely.

>>

>> Could anyone please tell me if this is an issue in Groovy or something I am not doing properly (I would like to vote for the latter, yet...).

>>

>>

>>

>> In Java

>>

>>

>>

>> x='one';

>>

>> System.out.println("init x: " + x);

>>

>>

>>

>> In Groovy

>>

>>

>>

>> println '1 = ' + x

>>

>> x = 'two'

>>

>> println '2 = ' + x

>>

>>

>>

>> Output:

>>

>>

>>

>> init x: one  <- initial value assignement OK

>>

>>

>>

>> 1 = one      <- successfully accessing ‘x’ from within the compiled script OK

>>

>>                 the Groovy script has picked up the value of the Java

>> variable;

>>

>>                 the implicit getX() has been called

>>

>>

>>

>> 2 = one                <- should be ‘two’ as per Groovy code (second line)

>>

>>                 but is unchanged ???

>>

>>

>>

>> It seems that the Groovy script can’t change the value of ‘x’ (can’t

>> access setX()). However there is no compilation error (‘x’ is not

>> read-only)

>>

>> When implementing getX/setX methods, only the getter is called (in both print statements, line 1,3) but during the assignment instruction (line 2), the setter is silently ignored (the value of ‘x’ remains ‘one’ instead of ‘two’.

>>

>>

>>

>> The Java/Groovy binding is operational since the ‘one’ value of ‘x’ in the Java  base class is successfully retrieved. So could anyone please tell me where the issue is?

>>

>> The confusing part is that even within in the Groovy context alone,

>> the assignment ‘x=’two’ is not honoured (and yet there are no

>> compilation/runtime error)

>>

>>

>>

>> Note that I tried all combinations of setters/getters/visibility and

>> can at the best read but never modify the variable ‘x’. The same

>> behaviour occurs with using the GroovyScriptEngine or

>> GroovyClassLoader

>>

>>

>>

>> Thank you very much in advance for your help.

>>

>>

>>

>> Thierry

>>

>> -

>>

>>

>>

>> PS: (I am not sure if my previous message went through as I was still

>> in the mailing list registration process, apologies if it is a

>> duplicate)

>>

>>

>>

>> Full code:

>>

>>

>>

>> import org.codehaus.groovy.control.CompilerConfiguration;

>>

>> import

>> org.codehaus.groovy.control.customizers.ASTTransformationCustomizer;

>>

>>

>>

>> import groovy.lang.Binding;

>>

>> import groovy.lang.Closure

>>

>> import groovy.lang.GroovyClassLoader;

>>

>> import groovy.lang.GroovyShell;

>>

>> import groovy.transform.CompileStatic;;

>>

>>

>>

>> abstract class GroovyDemoScript extends Script

>>

>> {

>>

>>     public String x;

>>

>>

>>

>>     public GroovyDemoScript()

>>

>>     {

>>

>>            x='one';

>>

>>            System.out.println("init x: " + x);

>>

>>     }

>>

>>

>>

>>     public static void main(String...args) throws Throwable

>>

>>     {

>>

>>            ////

>>

>>            // Compilation configuration

>>

>>            CompilerConfiguration configuration = new

>> CompilerConfiguration();

>>

>>            configuration.addCompilationCustomizers(new

>> ASTTransformationCustomizer(CompileStatic.class));

>>

>>

>>

>>                                 // make sure we use the Java base

>> class where ‘x’ is defined

>>

>>

>> configuration.setScriptBaseClass(GroovyDemoScript.class.name);

>>

>>

>>

>>            GroovyShell shell = new

>> GroovyShell(this.getClass().getClassLoader(), new Binding(),

>> configuration);

>>

>>

>>

>>            // source code

>>

>>            String scriptSource= "println '1 = ' + x; x = 'two';

>> println '2 = ' + x\n";

>>

>>

>>

>>            // compile the source code and run the compiled script

>>

>>            GroovyDemoScript compiledScript =

>> shell.parse(scriptSource);

>>

>>            compiledScript.run();

>>

>>     }

>>

>> }

>>

>>

>>

>> ________________________________

>>

>> Switchboard: +44 (0)113 394 6020

>>

>> Technical Support: +44 (0)113 394 6030

>>

>> ________________________________

>>

>> Lhasa Limited, a not-for-profit organisation, promotes scientific knowledge & understanding through the development of computer-aided reasoning & information systems in chemistry & the life sciences. Registered Charity Number 290866. Registered Office: Granary Wharf House, 2 Canal Wharf, Leeds, LS11 5PS. Company Registration Number 01765239. Registered in England and Wales.

>>

>> This communication, including any associated attachments, is intended for the use of the addressee only and may contain confidential, privileged or copyright material. If you are not the intended recipient, you must not copy this message or attachment or disclose the contents to any other person. If you have received this transmission in error, please notify the sender immediately and delete the message and any attachment from your system. Except where specifically stated, any views expressed in this message are those of the individual sender and do not represent the views of Lhasa Limited. Lhasa Limited cannot accept liability for any statements made which are the sender's own. Lhasa Limited does not guarantee that electronic communications, including any attachments, are free of viruses. Virus scanning is recommended and is the responsibility of the recipient.

>>

>> ________________________________

>>

>> This email message and any attachments are for the sole use of the intended recipient(s). Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message and any attachments.

Re: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)

Posted by Dinko Srkoč <di...@gmail.com>.
On 9 March 2016 at 11:56, Thierry Hanser
<Th...@lhasalimited.org> wrote:
> Thank you for the suggestion Dinko.
>
> I tried your experiment and the binding variables set remains actually empty ([:]) which is what I expected since there is no explicit binding involved (the variable 'x' is directly declared in the base script which is the point of the approach)

Interestingly this is different from what I'm getting. The statement
`x = 'two'` adds the value 'two' to the newly added binding variable
`x` (with binding being empty before that statement).

Cheers,
Dinko

>
> An interesting hint to the problem is that if I explicitly implement the getter and don't have a setter, there will be indeed an expected 'can't change a read-only value' compilation error which means that the getter/setter status is correctly analysed in the compilation decision tree and the setter must be present (or implicit) in order to allow the assignment in line 2 (x = 'two'); the problem is that it is not invoked at runtime; i.e. at compilation time Groovy's understanding is correct but the compiled code does not actually invoke the setter.
>
> This is disturbing and concerning as it leads to unpredictable behaviour.
>
> Thierry
>
>
> -----Original Message-----
> From: Dinko Srkoč [mailto:dinko.srkoc@gmail.com]
> Sent: 08 March 2016 18:20
> To: users@groovy.apache.org
> Subject: Re: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)
>
> On 8 March 2016 at 18:11, Thierry Hanser <Th...@lhasalimited.org> wrote:
>>
>> Thank you  Jason, you were indeed right, without CompileStatic or using TypeChecked works.
>
> Well, it works, but probably not the way you think it works. Here's what you can do to get more insight into what's going on:
>
> * print the script's variable bindings - add to `scriptSource`:
> `println binding.variables`
> * access the field `x` directly - to `JavaScriptDemo` add a method like this:
>
>     public String myX() { return x; }
>
>   then print that as well: `println myX()`
> * run the script with and without `CompileStatic` and compare the results
>
> After running the experiment you'll probably notice that the field `x` is never really changed. When you try to add the value 'two' to `x` you're actually creating a new binding variable. The difference with CompileStatic is in accessing the field or the binding if binding exists.
>
> Cheers,
> Dinko
>
>>
>> This is concerning as I would prefer static compilation (type checking being a must).
>>
>>
>>
>> I can work around the issue in my context but it impacts the elegance of the underlying DSL.
>>
>> However from the Groovy script engine perspective it is more concerning.
>>
>>
>>
>> Maybe Cedric or Guy know if there are any known issues and planned fixes related to that problem?
>>
>>
>>
>> Thanks again Jason.
>>
>>
>>
>> Thierry
>>
>>
>>
>> ---
>>
>> PS:  There was a couple of typos in the source code (never post-edit in outlook ;-) ). Apologies for any inconveniences.
>>
>> Here is the correct adjusted and working code:
>>
>>
>>
>> import org.codehaus.groovy.control.CompilerConfiguration;
>>
>> import
>> org.codehaus.groovy.control.customizers.ASTTransformationCustomizer;
>>
>>
>>
>> import groovy.lang.Binding;
>>
>> import groovy.lang.GroovyShell;
>>
>> import groovy.lang.Script;
>>
>> import groovy.transform.CompileStatic;;
>>
>>
>>
>> public abstract class JavaScriptDemo extends Script
>>
>> {
>>
>>     public String x;
>>
>>
>>
>>     public JavaScriptDemo()
>>
>>     {
>>
>>            x="one";
>>
>>            System.out.println("init x: " + x);
>>
>>     }
>>
>>
>>
>>      /**
>>
>>      * Demo main
>>
>>      * @param args
>>
>>      * @throws Throwable
>>
>>      */
>>
>>     public static void main(String...args) throws Throwable
>>
>>     {
>>
>>            ////
>>
>>            // Compilation configuration
>>
>>            CompilerConfiguration configuration = new
>> CompilerConfiguration();
>>
>>            configuration.addCompilationCustomizers(new
>> ASTTransformationCustomizer(CompileStatic.class));
>>
>>
>> configuration.setScriptBaseClass(JavaScriptDemo.class.getName());
>>
>>            GroovyShell shell = new
>> GroovyShell(JavaScriptDemo.class.getClassLoader(), new Binding(),
>> configuration);
>>
>>
>>
>>            // source code
>>
>>            String scriptSource= "println '1 = ' + x; x = 'two';
>> println '2 = ' + x\n";
>>
>>
>>
>>            // compile the source code and run the compiled script
>>
>>            JavaScriptDemo compiledScript =
>> (JavaScriptDemo)shell.parse(scriptSource);
>>
>>         compiledScript.run();
>>
>>     }
>>
>> }
>>
>>
>>
>> From: Winnebeck, Jason [mailto:Jason.Winnebeck@windstream.com]
>> Sent: 08 March 2016 16:46
>> To: users@groovy.apache.org
>> Subject: RE: Failing to change the value of a Java variable from
>> wihtin a Groovy script (potential issue?)
>>
>>
>>
>> Unfortunately static compile can be pretty flaky at times and I run into bugs often with it and have to redesign code. For small scripts I would advise against it (if you need type checking, use TypeChecked). I’m wondering if the script is getting compiled to get field x from the base class but favors setting binding.x = ‘two’ in the script.
>>
>>
>>
>> I would try without static compilation and see if it works. If it does work without static compilation, upgrade to the very latest Groovy (2.4.6) as bugs are fixed in static compiler all the time. If that doesn’t fix the problem, then change the Java field to private and create a getX() and setX(String). If that doesn’t work and you still need static compile, try an explicit setX(‘two’) or this.x = ‘two’ in the script. Historically the static compiler has been more reliable when you are more explicit.
>>
>>
>>
>> Jason
>>
>>
>>
>> From: Thierry Hanser [mailto:Thierry.Hanser@lhasalimited.org]
>> Sent: Tuesday, March 08, 2016 11:32 AM
>> To: 'users@groovy.apache.org' <us...@groovy.apache.org>
>> Subject: Failing to change the value of a Java variable from wihtin a
>> Groovy script (potential issue?)
>>
>>
>>
>> Hi,
>>
>>
>>
>> The following very simple code is behaving really strangely.
>>
>> Could anyone please tell me if this is an issue in Groovy or something I am not doing properly (I would like to vote for the latter, yet...).
>>
>>
>>
>> In Java
>>
>>
>>
>> x='one';
>>
>> System.out.println("init x: " + x);
>>
>>
>>
>> In Groovy
>>
>>
>>
>> println '1 = ' + x
>>
>> x = 'two'
>>
>> println '2 = ' + x
>>
>>
>>
>> Output:
>>
>>
>>
>> init x: one  <- initial value assignement OK
>>
>>
>>
>> 1 = one      <- successfully accessing ‘x’ from within the compiled script OK
>>
>>                 the Groovy script has picked up the value of the Java
>> variable;
>>
>>                 the implicit getX() has been called
>>
>>
>>
>> 2 = one                <- should be ‘two’ as per Groovy code (second line)
>>
>>                 but is unchanged ???
>>
>>
>>
>> It seems that the Groovy script can’t change the value of ‘x’ (can’t
>> access setX()). However there is no compilation error (‘x’ is not
>> read-only)
>>
>> When implementing getX/setX methods, only the getter is called (in both print statements, line 1,3) but during the assignment instruction (line 2), the setter is silently ignored (the value of ‘x’ remains ‘one’ instead of ‘two’.
>>
>>
>>
>> The Java/Groovy binding is operational since the ‘one’ value of ‘x’ in the Java  base class is successfully retrieved. So could anyone please tell me where the issue is?
>>
>> The confusing part is that even within in the Groovy context alone,
>> the assignment ‘x=’two’ is not honoured (and yet there are no
>> compilation/runtime error)
>>
>>
>>
>> Note that I tried all combinations of setters/getters/visibility and
>> can at the best read but never modify the variable ‘x’. The same
>> behaviour occurs with using the GroovyScriptEngine or
>> GroovyClassLoader
>>
>>
>>
>> Thank you very much in advance for your help.
>>
>>
>>
>> Thierry
>>
>> -
>>
>>
>>
>> PS: (I am not sure if my previous message went through as I was still
>> in the mailing list registration process, apologies if it is a
>> duplicate)
>>
>>
>>
>> Full code:
>>
>>
>>
>> import org.codehaus.groovy.control.CompilerConfiguration;
>>
>> import
>> org.codehaus.groovy.control.customizers.ASTTransformationCustomizer;
>>
>>
>>
>> import groovy.lang.Binding;
>>
>> import groovy.lang.Closure
>>
>> import groovy.lang.GroovyClassLoader;
>>
>> import groovy.lang.GroovyShell;
>>
>> import groovy.transform.CompileStatic;;
>>
>>
>>
>> abstract class GroovyDemoScript extends Script
>>
>> {
>>
>>     public String x;
>>
>>
>>
>>     public GroovyDemoScript()
>>
>>     {
>>
>>            x='one';
>>
>>            System.out.println("init x: " + x);
>>
>>     }
>>
>>
>>
>>     public static void main(String...args) throws Throwable
>>
>>     {
>>
>>            ////
>>
>>            // Compilation configuration
>>
>>            CompilerConfiguration configuration = new
>> CompilerConfiguration();
>>
>>            configuration.addCompilationCustomizers(new
>> ASTTransformationCustomizer(CompileStatic.class));
>>
>>
>>
>>                                 // make sure we use the Java base
>> class where ‘x’ is defined
>>
>>
>> configuration.setScriptBaseClass(GroovyDemoScript.class.name);
>>
>>
>>
>>            GroovyShell shell = new
>> GroovyShell(this.getClass().getClassLoader(), new Binding(),
>> configuration);
>>
>>
>>
>>            // source code
>>
>>            String scriptSource= "println '1 = ' + x; x = 'two';
>> println '2 = ' + x\n";
>>
>>
>>
>>            // compile the source code and run the compiled script
>>
>>            GroovyDemoScript compiledScript =
>> shell.parse(scriptSource);
>>
>>            compiledScript.run();
>>
>>     }
>>
>> }
>>
>>
>>
>> ________________________________
>>
>> Switchboard: +44 (0)113 394 6020
>>
>> Technical Support: +44 (0)113 394 6030
>>
>> ________________________________
>>
>> Lhasa Limited, a not-for-profit organisation, promotes scientific knowledge & understanding through the development of computer-aided reasoning & information systems in chemistry & the life sciences. Registered Charity Number 290866. Registered Office: Granary Wharf House, 2 Canal Wharf, Leeds, LS11 5PS. Company Registration Number 01765239. Registered in England and Wales.
>>
>> This communication, including any associated attachments, is intended for the use of the addressee only and may contain confidential, privileged or copyright material. If you are not the intended recipient, you must not copy this message or attachment or disclose the contents to any other person. If you have received this transmission in error, please notify the sender immediately and delete the message and any attachment from your system. Except where specifically stated, any views expressed in this message are those of the individual sender and do not represent the views of Lhasa Limited. Lhasa Limited cannot accept liability for any statements made which are the sender's own. Lhasa Limited does not guarantee that electronic communications, including any attachments, are free of viruses. Virus scanning is recommended and is the responsibility of the recipient.
>>
>> ________________________________
>>
>> This email message and any attachments are for the sole use of the intended recipient(s). Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message and any attachments.

RE: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)

Posted by Thierry Hanser <Th...@lhasalimited.org>.
Thank you for the suggestion Dinko. 

I tried your experiment and the binding variables set remains actually empty ([:]) which is what I expected since there is no explicit binding involved (the variable 'x' is directly declared in the base script which is the point of the approach)

An interesting hint to the problem is that if I explicitly implement the getter and don't have a setter, there will be indeed an expected 'can't change a read-only value' compilation error which means that the getter/setter status is correctly analysed in the compilation decision tree and the setter must be present (or implicit) in order to allow the assignment in line 2 (x = 'two'); the problem is that it is not invoked at runtime; i.e. at compilation time Groovy's understanding is correct but the compiled code does not actually invoke the setter.

This is disturbing and concerning as it leads to unpredictable behaviour.

Thierry


-----Original Message-----
From: Dinko Srkoč [mailto:dinko.srkoc@gmail.com] 
Sent: 08 March 2016 18:20
To: users@groovy.apache.org
Subject: Re: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)

On 8 March 2016 at 18:11, Thierry Hanser <Th...@lhasalimited.org> wrote:
>
> Thank you  Jason, you were indeed right, without CompileStatic or using TypeChecked works.

Well, it works, but probably not the way you think it works. Here's what you can do to get more insight into what's going on:

* print the script's variable bindings - add to `scriptSource`:
`println binding.variables`
* access the field `x` directly - to `JavaScriptDemo` add a method like this:

    public String myX() { return x; }

  then print that as well: `println myX()`
* run the script with and without `CompileStatic` and compare the results

After running the experiment you'll probably notice that the field `x` is never really changed. When you try to add the value 'two' to `x` you're actually creating a new binding variable. The difference with CompileStatic is in accessing the field or the binding if binding exists.

Cheers,
Dinko

>
> This is concerning as I would prefer static compilation (type checking being a must).
>
>
>
> I can work around the issue in my context but it impacts the elegance of the underlying DSL.
>
> However from the Groovy script engine perspective it is more concerning.
>
>
>
> Maybe Cedric or Guy know if there are any known issues and planned fixes related to that problem?
>
>
>
> Thanks again Jason.
>
>
>
> Thierry
>
>
>
> ---
>
> PS:  There was a couple of typos in the source code (never post-edit in outlook ;-) ). Apologies for any inconveniences.
>
> Here is the correct adjusted and working code:
>
>
>
> import org.codehaus.groovy.control.CompilerConfiguration;
>
> import 
> org.codehaus.groovy.control.customizers.ASTTransformationCustomizer;
>
>
>
> import groovy.lang.Binding;
>
> import groovy.lang.GroovyShell;
>
> import groovy.lang.Script;
>
> import groovy.transform.CompileStatic;;
>
>
>
> public abstract class JavaScriptDemo extends Script
>
> {
>
>     public String x;
>
>
>
>     public JavaScriptDemo()
>
>     {
>
>            x="one";
>
>            System.out.println("init x: " + x);
>
>     }
>
>
>
>      /**
>
>      * Demo main
>
>      * @param args
>
>      * @throws Throwable
>
>      */
>
>     public static void main(String...args) throws Throwable
>
>     {
>
>            ////
>
>            // Compilation configuration
>
>            CompilerConfiguration configuration = new 
> CompilerConfiguration();
>
>            configuration.addCompilationCustomizers(new 
> ASTTransformationCustomizer(CompileStatic.class));
>
>            
> configuration.setScriptBaseClass(JavaScriptDemo.class.getName());
>
>            GroovyShell shell = new 
> GroovyShell(JavaScriptDemo.class.getClassLoader(), new Binding(), 
> configuration);
>
>
>
>            // source code
>
>            String scriptSource= "println '1 = ' + x; x = 'two'; 
> println '2 = ' + x\n";
>
>
>
>            // compile the source code and run the compiled script
>
>            JavaScriptDemo compiledScript = 
> (JavaScriptDemo)shell.parse(scriptSource);
>
>         compiledScript.run();
>
>     }
>
> }
>
>
>
> From: Winnebeck, Jason [mailto:Jason.Winnebeck@windstream.com]
> Sent: 08 March 2016 16:46
> To: users@groovy.apache.org
> Subject: RE: Failing to change the value of a Java variable from 
> wihtin a Groovy script (potential issue?)
>
>
>
> Unfortunately static compile can be pretty flaky at times and I run into bugs often with it and have to redesign code. For small scripts I would advise against it (if you need type checking, use TypeChecked). I’m wondering if the script is getting compiled to get field x from the base class but favors setting binding.x = ‘two’ in the script.
>
>
>
> I would try without static compilation and see if it works. If it does work without static compilation, upgrade to the very latest Groovy (2.4.6) as bugs are fixed in static compiler all the time. If that doesn’t fix the problem, then change the Java field to private and create a getX() and setX(String). If that doesn’t work and you still need static compile, try an explicit setX(‘two’) or this.x = ‘two’ in the script. Historically the static compiler has been more reliable when you are more explicit.
>
>
>
> Jason
>
>
>
> From: Thierry Hanser [mailto:Thierry.Hanser@lhasalimited.org]
> Sent: Tuesday, March 08, 2016 11:32 AM
> To: 'users@groovy.apache.org' <us...@groovy.apache.org>
> Subject: Failing to change the value of a Java variable from wihtin a 
> Groovy script (potential issue?)
>
>
>
> Hi,
>
>
>
> The following very simple code is behaving really strangely.
>
> Could anyone please tell me if this is an issue in Groovy or something I am not doing properly (I would like to vote for the latter, yet...).
>
>
>
> In Java
>
>
>
> x='one';
>
> System.out.println("init x: " + x);
>
>
>
> In Groovy
>
>
>
> println '1 = ' + x
>
> x = 'two'
>
> println '2 = ' + x
>
>
>
> Output:
>
>
>
> init x: one  <- initial value assignement OK
>
>
>
> 1 = one      <- successfully accessing ‘x’ from within the compiled script OK
>
>                 the Groovy script has picked up the value of the Java 
> variable;
>
>                 the implicit getX() has been called
>
>
>
> 2 = one                <- should be ‘two’ as per Groovy code (second line)
>
>                 but is unchanged ???
>
>
>
> It seems that the Groovy script can’t change the value of ‘x’ (can’t 
> access setX()). However there is no compilation error (‘x’ is not 
> read-only)
>
> When implementing getX/setX methods, only the getter is called (in both print statements, line 1,3) but during the assignment instruction (line 2), the setter is silently ignored (the value of ‘x’ remains ‘one’ instead of ‘two’.
>
>
>
> The Java/Groovy binding is operational since the ‘one’ value of ‘x’ in the Java  base class is successfully retrieved. So could anyone please tell me where the issue is?
>
> The confusing part is that even within in the Groovy context alone, 
> the assignment ‘x=’two’ is not honoured (and yet there are no 
> compilation/runtime error)
>
>
>
> Note that I tried all combinations of setters/getters/visibility and 
> can at the best read but never modify the variable ‘x’. The same 
> behaviour occurs with using the GroovyScriptEngine or 
> GroovyClassLoader
>
>
>
> Thank you very much in advance for your help.
>
>
>
> Thierry
>
> -
>
>
>
> PS: (I am not sure if my previous message went through as I was still 
> in the mailing list registration process, apologies if it is a 
> duplicate)
>
>
>
> Full code:
>
>
>
> import org.codehaus.groovy.control.CompilerConfiguration;
>
> import 
> org.codehaus.groovy.control.customizers.ASTTransformationCustomizer;
>
>
>
> import groovy.lang.Binding;
>
> import groovy.lang.Closure
>
> import groovy.lang.GroovyClassLoader;
>
> import groovy.lang.GroovyShell;
>
> import groovy.transform.CompileStatic;;
>
>
>
> abstract class GroovyDemoScript extends Script
>
> {
>
>     public String x;
>
>
>
>     public GroovyDemoScript()
>
>     {
>
>            x='one';
>
>            System.out.println("init x: " + x);
>
>     }
>
>
>
>     public static void main(String...args) throws Throwable
>
>     {
>
>            ////
>
>            // Compilation configuration
>
>            CompilerConfiguration configuration = new 
> CompilerConfiguration();
>
>            configuration.addCompilationCustomizers(new 
> ASTTransformationCustomizer(CompileStatic.class));
>
>
>
>                                 // make sure we use the Java base 
> class where ‘x’ is defined
>
>            
> configuration.setScriptBaseClass(GroovyDemoScript.class.name);
>
>
>
>            GroovyShell shell = new 
> GroovyShell(this.getClass().getClassLoader(), new Binding(), 
> configuration);
>
>
>
>            // source code
>
>            String scriptSource= "println '1 = ' + x; x = 'two'; 
> println '2 = ' + x\n";
>
>
>
>            // compile the source code and run the compiled script
>
>            GroovyDemoScript compiledScript = 
> shell.parse(scriptSource);
>
>            compiledScript.run();
>
>     }
>
> }
>
>
>
> ________________________________
>
> Switchboard: +44 (0)113 394 6020
>
> Technical Support: +44 (0)113 394 6030
>
> ________________________________
>
> Lhasa Limited, a not-for-profit organisation, promotes scientific knowledge & understanding through the development of computer-aided reasoning & information systems in chemistry & the life sciences. Registered Charity Number 290866. Registered Office: Granary Wharf House, 2 Canal Wharf, Leeds, LS11 5PS. Company Registration Number 01765239. Registered in England and Wales.
>
> This communication, including any associated attachments, is intended for the use of the addressee only and may contain confidential, privileged or copyright material. If you are not the intended recipient, you must not copy this message or attachment or disclose the contents to any other person. If you have received this transmission in error, please notify the sender immediately and delete the message and any attachment from your system. Except where specifically stated, any views expressed in this message are those of the individual sender and do not represent the views of Lhasa Limited. Lhasa Limited cannot accept liability for any statements made which are the sender's own. Lhasa Limited does not guarantee that electronic communications, including any attachments, are free of viruses. Virus scanning is recommended and is the responsibility of the recipient.
>
> ________________________________
>
> This email message and any attachments are for the sole use of the intended recipient(s). Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message and any attachments.

Re: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)

Posted by Dinko Srkoč <di...@gmail.com>.
On 8 March 2016 at 18:11, Thierry Hanser
<Th...@lhasalimited.org> wrote:
>
> Thank you  Jason, you were indeed right, without CompileStatic or using TypeChecked works.

Well, it works, but probably not the way you think it works. Here's
what you can do to get more insight into what's going on:

* print the script's variable bindings - add to `scriptSource`:
`println binding.variables`
* access the field `x` directly - to `JavaScriptDemo` add a method like this:

    public String myX() { return x; }

  then print that as well: `println myX()`
* run the script with and without `CompileStatic` and compare the results

After running the experiment you'll probably notice that the field `x`
is never really changed. When you try to add the value 'two' to `x`
you're actually creating a new binding variable. The difference with
CompileStatic is in accessing the field or the binding if binding
exists.

Cheers,
Dinko

>
> This is concerning as I would prefer static compilation (type checking being a must).
>
>
>
> I can work around the issue in my context but it impacts the elegance of the underlying DSL.
>
> However from the Groovy script engine perspective it is more concerning.
>
>
>
> Maybe Cedric or Guy know if there are any known issues and planned fixes related to that problem?
>
>
>
> Thanks again Jason.
>
>
>
> Thierry
>
>
>
> ---
>
> PS:  There was a couple of typos in the source code (never post-edit in outlook ;-) ). Apologies for any inconveniences.
>
> Here is the correct adjusted and working code:
>
>
>
> import org.codehaus.groovy.control.CompilerConfiguration;
>
> import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer;
>
>
>
> import groovy.lang.Binding;
>
> import groovy.lang.GroovyShell;
>
> import groovy.lang.Script;
>
> import groovy.transform.CompileStatic;;
>
>
>
> public abstract class JavaScriptDemo extends Script
>
> {
>
>     public String x;
>
>
>
>     public JavaScriptDemo()
>
>     {
>
>            x="one";
>
>            System.out.println("init x: " + x);
>
>     }
>
>
>
>      /**
>
>      * Demo main
>
>      * @param args
>
>      * @throws Throwable
>
>      */
>
>     public static void main(String...args) throws Throwable
>
>     {
>
>            ////
>
>            // Compilation configuration
>
>            CompilerConfiguration configuration = new CompilerConfiguration();
>
>            configuration.addCompilationCustomizers(new ASTTransformationCustomizer(CompileStatic.class));
>
>            configuration.setScriptBaseClass(JavaScriptDemo.class.getName());
>
>            GroovyShell shell = new GroovyShell(JavaScriptDemo.class.getClassLoader(), new Binding(), configuration);
>
>
>
>            // source code
>
>            String scriptSource= "println '1 = ' + x; x = 'two'; println '2 = ' + x\n";
>
>
>
>            // compile the source code and run the compiled script
>
>            JavaScriptDemo compiledScript = (JavaScriptDemo)shell.parse(scriptSource);
>
>         compiledScript.run();
>
>     }
>
> }
>
>
>
> From: Winnebeck, Jason [mailto:Jason.Winnebeck@windstream.com]
> Sent: 08 March 2016 16:46
> To: users@groovy.apache.org
> Subject: RE: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)
>
>
>
> Unfortunately static compile can be pretty flaky at times and I run into bugs often with it and have to redesign code. For small scripts I would advise against it (if you need type checking, use TypeChecked). I’m wondering if the script is getting compiled to get field x from the base class but favors setting binding.x = ‘two’ in the script.
>
>
>
> I would try without static compilation and see if it works. If it does work without static compilation, upgrade to the very latest Groovy (2.4.6) as bugs are fixed in static compiler all the time. If that doesn’t fix the problem, then change the Java field to private and create a getX() and setX(String). If that doesn’t work and you still need static compile, try an explicit setX(‘two’) or this.x = ‘two’ in the script. Historically the static compiler has been more reliable when you are more explicit.
>
>
>
> Jason
>
>
>
> From: Thierry Hanser [mailto:Thierry.Hanser@lhasalimited.org]
> Sent: Tuesday, March 08, 2016 11:32 AM
> To: 'users@groovy.apache.org' <us...@groovy.apache.org>
> Subject: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)
>
>
>
> Hi,
>
>
>
> The following very simple code is behaving really strangely.
>
> Could anyone please tell me if this is an issue in Groovy or something I am not doing properly (I would like to vote for the latter, yet...).
>
>
>
> In Java
>
>
>
> x='one';
>
> System.out.println("init x: " + x);
>
>
>
> In Groovy
>
>
>
> println '1 = ' + x
>
> x = 'two'
>
> println '2 = ' + x
>
>
>
> Output:
>
>
>
> init x: one  <- initial value assignement OK
>
>
>
> 1 = one      <- successfully accessing ‘x’ from within the compiled script OK
>
>                 the Groovy script has picked up the value of the Java variable;
>
>                 the implicit getX() has been called
>
>
>
> 2 = one                <- should be ‘two’ as per Groovy code (second line)
>
>                 but is unchanged ???
>
>
>
> It seems that the Groovy script can’t change the value of ‘x’ (can’t access setX()). However there is no compilation error (‘x’ is not read-only)
>
> When implementing getX/setX methods, only the getter is called (in both print statements, line 1,3) but during the assignment instruction (line 2), the setter is silently ignored (the value of ‘x’ remains ‘one’ instead of ‘two’.
>
>
>
> The Java/Groovy binding is operational since the ‘one’ value of ‘x’ in the Java  base class is successfully retrieved. So could anyone please tell me where the issue is?
>
> The confusing part is that even within in the Groovy context alone, the assignment ‘x=’two’ is not honoured (and yet there are no compilation/runtime error)
>
>
>
> Note that I tried all combinations of setters/getters/visibility and can at the best read but never modify the variable ‘x’. The same behaviour occurs with using the GroovyScriptEngine or GroovyClassLoader
>
>
>
> Thank you very much in advance for your help.
>
>
>
> Thierry
>
> -
>
>
>
> PS: (I am not sure if my previous message went through as I was still in the mailing list registration process, apologies if it is a duplicate)
>
>
>
> Full code:
>
>
>
> import org.codehaus.groovy.control.CompilerConfiguration;
>
> import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer;
>
>
>
> import groovy.lang.Binding;
>
> import groovy.lang.Closure
>
> import groovy.lang.GroovyClassLoader;
>
> import groovy.lang.GroovyShell;
>
> import groovy.transform.CompileStatic;;
>
>
>
> abstract class GroovyDemoScript extends Script
>
> {
>
>     public String x;
>
>
>
>     public GroovyDemoScript()
>
>     {
>
>            x='one';
>
>            System.out.println("init x: " + x);
>
>     }
>
>
>
>     public static void main(String...args) throws Throwable
>
>     {
>
>            ////
>
>            // Compilation configuration
>
>            CompilerConfiguration configuration = new CompilerConfiguration();
>
>            configuration.addCompilationCustomizers(new ASTTransformationCustomizer(CompileStatic.class));
>
>
>
>                                 // make sure we use the Java base class where ‘x’ is defined
>
>            configuration.setScriptBaseClass(GroovyDemoScript.class.name);
>
>
>
>            GroovyShell shell = new GroovyShell(this.getClass().getClassLoader(), new Binding(), configuration);
>
>
>
>            // source code
>
>            String scriptSource= "println '1 = ' + x; x = 'two'; println '2 = ' + x\n";
>
>
>
>            // compile the source code and run the compiled script
>
>            GroovyDemoScript compiledScript = shell.parse(scriptSource);
>
>            compiledScript.run();
>
>     }
>
> }
>
>
>
> ________________________________
>
> Switchboard: +44 (0)113 394 6020
>
> Technical Support: +44 (0)113 394 6030
>
> ________________________________
>
> Lhasa Limited, a not-for-profit organisation, promotes scientific knowledge & understanding through the development of computer-aided reasoning & information systems in chemistry & the life sciences. Registered Charity Number 290866. Registered Office: Granary Wharf House, 2 Canal Wharf, Leeds, LS11 5PS. Company Registration Number 01765239. Registered in England and Wales.
>
> This communication, including any associated attachments, is intended for the use of the addressee only and may contain confidential, privileged or copyright material. If you are not the intended recipient, you must not copy this message or attachment or disclose the contents to any other person. If you have received this transmission in error, please notify the sender immediately and delete the message and any attachment from your system. Except where specifically stated, any views expressed in this message are those of the individual sender and do not represent the views of Lhasa Limited. Lhasa Limited cannot accept liability for any statements made which are the sender's own. Lhasa Limited does not guarantee that electronic communications, including any attachments, are free of viruses. Virus scanning is recommended and is the responsibility of the recipient.
>
> ________________________________
>
> This email message and any attachments are for the sole use of the intended recipient(s). Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message and any attachments.

RE: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)

Posted by Thierry Hanser <Th...@lhasalimited.org>.
Thank you  Jason, you were indeed right, without CompileStatic or using TypeChecked works.
This is concerning as I would prefer static compilation (type checking being a must).

I can work around the issue in my context but it impacts the elegance of the underlying DSL.
However from the Groovy script engine perspective it is more concerning.

Maybe Cedric or Guy know if there are any known issues and planned fixes related to that problem?

Thanks again Jason.

Thierry

---
PS:  There was a couple of typos in the source code (never post-edit in outlook ;-) ). Apologies for any inconveniences.
Here is the correct adjusted and working code:

import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer;

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import groovy.transform.CompileStatic;;

public abstract class JavaScriptDemo extends Script
{
    public String x;

    public JavaScriptDemo()
    {
           x="one";
           System.out.println("init x: " + x);
    }

     /**
     * Demo main
     * @param args
     * @throws Throwable
     */
    public static void main(String...args) throws Throwable
    {
           ////
           // Compilation configuration
           CompilerConfiguration configuration = new CompilerConfiguration();
           configuration.addCompilationCustomizers(new ASTTransformationCustomizer(CompileStatic.class));
           configuration.setScriptBaseClass(JavaScriptDemo.class.getName());
           GroovyShell shell = new GroovyShell(JavaScriptDemo.class.getClassLoader(), new Binding(), configuration);

           // source code
           String scriptSource= "println '1 = ' + x; x = 'two'; println '2 = ' + x\n";

           // compile the source code and run the compiled script
           JavaScriptDemo compiledScript = (JavaScriptDemo)shell.parse(scriptSource);
        compiledScript.run();
    }
}

From: Winnebeck, Jason [mailto:Jason.Winnebeck@windstream.com]
Sent: 08 March 2016 16:46
To: users@groovy.apache.org
Subject: RE: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)

Unfortunately static compile can be pretty flaky at times and I run into bugs often with it and have to redesign code. For small scripts I would advise against it (if you need type checking, use TypeChecked). I'm wondering if the script is getting compiled to get field x from the base class but favors setting binding.x = 'two' in the script.

I would try without static compilation and see if it works. If it does work without static compilation, upgrade to the very latest Groovy (2.4.6) as bugs are fixed in static compiler all the time. If that doesn't fix the problem, then change the Java field to private and create a getX() and setX(String). If that doesn't work and you still need static compile, try an explicit setX('two') or this.x = 'two' in the script. Historically the static compiler has been more reliable when you are more explicit.

Jason

From: Thierry Hanser [mailto:Thierry.Hanser@lhasalimited.org]
Sent: Tuesday, March 08, 2016 11:32 AM
To: 'users@groovy.apache.org' <us...@groovy.apache.org>>
Subject: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)

Hi,

The following very simple code is behaving really strangely.
Could anyone please tell me if this is an issue in Groovy or something I am not doing properly (I would like to vote for the latter, yet...).

In Java

x='one';
System.out.println("init x: " + x);

In Groovy

println '1 = ' + x
x = 'two'
println '2 = ' + x

Output:

init x: one  <- initial value assignement OK

1 = one      <- successfully accessing 'x' from within the compiled script OK
                the Groovy script has picked up the value of the Java variable;
                the implicit getX() has been called

2 = one                <- should be 'two' as per Groovy code (second line)
                but is unchanged ???

It seems that the Groovy script can't change the value of 'x' (can't access setX()). However there is no compilation error ('x' is not read-only)
When implementing getX/setX methods, only the getter is called (in both print statements, line 1,3) but during the assignment instruction (line 2), the setter is silently ignored (the value of 'x' remains 'one' instead of 'two'.

The Java/Groovy binding is operational since the 'one' value of 'x' in the Java  base class is successfully retrieved. So could anyone please tell me where the issue is?
The confusing part is that even within in the Groovy context alone, the assignment 'x='two' is not honoured (and yet there are no compilation/runtime error)

Note that I tried all combinations of setters/getters/visibility and can at the best read but never modify the variable 'x'. The same behaviour occurs with using the GroovyScriptEngine or GroovyClassLoader

Thank you very much in advance for your help.

Thierry
-

PS: (I am not sure if my previous message went through as I was still in the mailing list registration process, apologies if it is a duplicate)

Full code:

import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer;

import groovy.lang.Binding;
import groovy.lang.Closure
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyShell;
import groovy.transform.CompileStatic;;

abstract class GroovyDemoScript extends Script
{
    public String x;

    public GroovyDemoScript()
    {
           x='one';
           System.out.println("init x: " + x);
    }

    public static void main(String...args) throws Throwable
    {
           ////
           // Compilation configuration
           CompilerConfiguration configuration = new CompilerConfiguration();
           configuration.addCompilationCustomizers(new ASTTransformationCustomizer(CompileStatic.class));

                                // make sure we use the Java base class where 'x' is defined
           configuration.setScriptBaseClass(GroovyDemoScript.class.name);

           GroovyShell shell = new GroovyShell(this.getClass().getClassLoader(), new Binding(), configuration);

           // source code
           String scriptSource= "println '1 = ' + x; x = 'two'; println '2 = ' + x\n";

           // compile the source code and run the compiled script
           GroovyDemoScript compiledScript = shell.parse(scriptSource);
           compiledScript.run();
    }
}

________________________________
Switchboard: +44 (0)113 394 6020
Technical Support: +44 (0)113 394 6030
________________________________
Lhasa Limited, a not-for-profit organisation, promotes scientific knowledge & understanding through the development of computer-aided reasoning & information systems in chemistry & the life sciences. Registered Charity Number 290866. Registered Office: Granary Wharf House, 2 Canal Wharf, Leeds, LS11 5PS. Company Registration Number 01765239. Registered in England and Wales.
This communication, including any associated attachments, is intended for the use of the addressee only and may contain confidential, privileged or copyright material. If you are not the intended recipient, you must not copy this message or attachment or disclose the contents to any other person. If you have received this transmission in error, please notify the sender immediately and delete the message and any attachment from your system. Except where specifically stated, any views expressed in this message are those of the individual sender and do not represent the views of Lhasa Limited. Lhasa Limited cannot accept liability for any statements made which are the sender's own. Lhasa Limited does not guarantee that electronic communications, including any attachments, are free of viruses. Virus scanning is recommended and is the responsibility of the recipient.
________________________________
This email message and any attachments are for the sole use of the intended recipient(s). Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message and any attachments.

RE: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)

Posted by "Winnebeck, Jason" <Ja...@windstream.com>.
Unfortunately static compile can be pretty flaky at times and I run into bugs often with it and have to redesign code. For small scripts I would advise against it (if you need type checking, use TypeChecked). I'm wondering if the script is getting compiled to get field x from the base class but favors setting binding.x = 'two' in the script.

I would try without static compilation and see if it works. If it does work without static compilation, upgrade to the very latest Groovy (2.4.6) as bugs are fixed in static compiler all the time. If that doesn't fix the problem, then change the Java field to private and create a getX() and setX(String). If that doesn't work and you still need static compile, try an explicit setX('two') or this.x = 'two' in the script. Historically the static compiler has been more reliable when you are more explicit.

Jason

From: Thierry Hanser [mailto:Thierry.Hanser@lhasalimited.org]
Sent: Tuesday, March 08, 2016 11:32 AM
To: 'users@groovy.apache.org' <us...@groovy.apache.org>
Subject: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)

Hi,

The following very simple code is behaving really strangely.
Could anyone please tell me if this is an issue in Groovy or something I am not doing properly (I would like to vote for the latter, yet...).

In Java

x='one';
System.out.println("init x: " + x);

In Groovy

println '1 = ' + x
x = 'two'
println '2 = ' + x

Output:

init x: one  <- initial value assignement OK

1 = one      <- successfully accessing 'x' from within the compiled script OK
                the Groovy script has picked up the value of the Java variable;
                the implicit getX() has been called

2 = one                <- should be 'two' as per Groovy code (second line)
                but is unchanged ???

It seems that the Groovy script can't change the value of 'x' (can't access setX()). However there is no compilation error ('x' is not read-only)
When implementing getX/setX methods, only the getter is called (in both print statements, line 1,3) but during the assignment instruction (line 2), the setter is silently ignored (the value of 'x' remains 'one' instead of 'two'.

The Java/Groovy binding is operational since the 'one' value of 'x' in the Java  base class is successfully retrieved. So could anyone please tell me where the issue is?
The confusing part is that even within in the Groovy context alone, the assignment 'x='two' is not honoured (and yet there are no compilation/runtime error)

Note that I tried all combinations of setters/getters/visibility and can at the best read but never modify the variable 'x'. The same behaviour occurs with using the GroovyScriptEngine or GroovyClassLoader

Thank you very much in advance for your help.

Thierry
-

PS: (I am not sure if my previous message went through as I was still in the mailing list registration process, apologies if it is a duplicate)

Full code:

import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer;

import groovy.lang.Binding;
import groovy.lang.Closure
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyShell;
import groovy.transform.CompileStatic;;

abstract class GroovyDemoScript extends Script
{
    public String x;

    public GroovyDemoScript()
    {
           x='one';
           System.out.println("init x: " + x);
    }

    public static void main(String...args) throws Throwable
    {
           ////
           // Compilation configuration
           CompilerConfiguration configuration = new CompilerConfiguration();
           configuration.addCompilationCustomizers(new ASTTransformationCustomizer(CompileStatic.class));

                                // make sure we use the Java base class where 'x' is defined
           configuration.setScriptBaseClass(GroovyDemoScript.class.name);

           GroovyShell shell = new GroovyShell(this.getClass().getClassLoader(), new Binding(), configuration);

           // source code
           String scriptSource= "println '1 = ' + x; x = 'two'; println '2 = ' + x\n";

           // compile the source code and run the compiled script
           GroovyDemoScript compiledScript = shell.parse(scriptSource);
           compiledScript.run();
    }
}

________________________________
Switchboard: +44 (0)113 394 6020
Technical Support: +44 (0)113 394 6030
________________________________
Lhasa Limited, a not-for-profit organisation, promotes scientific knowledge & understanding through the development of computer-aided reasoning & information systems in chemistry & the life sciences. Registered Charity Number 290866. Registered Office: Granary Wharf House, 2 Canal Wharf, Leeds, LS11 5PS. Company Registration Number 01765239. Registered in England and Wales.
This communication, including any associated attachments, is intended for the use of the addressee only and may contain confidential, privileged or copyright material. If you are not the intended recipient, you must not copy this message or attachment or disclose the contents to any other person. If you have received this transmission in error, please notify the sender immediately and delete the message and any attachment from your system. Except where specifically stated, any views expressed in this message are those of the individual sender and do not represent the views of Lhasa Limited. Lhasa Limited cannot accept liability for any statements made which are the sender's own. Lhasa Limited does not guarantee that electronic communications, including any attachments, are free of viruses. Virus scanning is recommended and is the responsibility of the recipient.

----------------------------------------------------------------------
This email message and any attachments are for the sole use of the intended recipient(s). Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message and any attachments.

Re: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?) [POTENTIAL FIX]

Posted by Jochen Theodorou <bl...@gmx.org>.
On 05.04.2016 20:00, Thierry Hanser wrote:
[...]
> The solution is indeed close to what Jochen suggested. I just think that for the sake of symmetry all we need to do is to check whether the variable exists in the binding and behave accordingly. If it exists change its value in the binding, if it does not exist delegate to the  meta class (or call super.super). This would ensure a consistent (symmetrical) behaviour between getProperty() and setProperty().
>
> @Override
> public void setProperty(String property, Object newValue)
> {	
>     if ("binding".equals(property)) setBinding((Binding) newValue);
>     else if("metaClass".equals(property)) setMetaClass((MetaClass)newValue);
>     else if(getBinding().hasVariable(property))  getBinding().setVariable(property, newValue);  // <== if variable exist => set binding value
>     else getMetaClass().setProperty(this, property, newValue); // <== variable does not exist => delegate to meta class
> }
>
> Note that the origin of the dissymmetry is actually a consequence of the dissymmetry between the getVariable() and the setVariable() methods in the Binding class. getVariable() throws an exception when the variable does not exist where as setVariable() does not (it adds the variable to the linked map). The former exception is used by getProperty() in Script to trigger the delegation to the meta class but this can be used by setProperty() since no exception is thrown by setVariable() in Binding.

well.. this means a script "x=1", without any further doing will fail. 
At the beginning the binding is empty, so 
getBinding().hasVariable(property) will return false, and a setX() does 
not exist.

what I suggested was actually to first ask the meta class and then the 
binding.

[...]
> @Override
> public void setProperty(String property, Object newValue)
> {	
>     if ("binding".equals(property)) setBinding((Binding) newValue);
>     else if("metaClass".equals(property)) setMetaClass((MetaClass)newValue);
>     else
>     {
>        getBinding().setVariable(property, newValue);  // <== update binding
>        getMetaClass().setProperty(this, property, newValue); // <== notify meta class
>     }
> }

hmm... what about exceptions when setting the property? The obvious one 
to handle is of course if the property does not exist. But there is also 
the type conversion problem. For example if your property is an int and 
your value is a String. Will this cause an exception being thrown to the 
user level code? If yes, you will not have the old behaviour. Will the 
binding still have the value? And besides actually being able the call 
the setter, let's not forget the method code itself can still throw 
exception... for example NullPointerException. Different level, but same 
question as before.

bye Jochen


RE: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?) [POTENTIAL FIX]

Posted by Thierry Hanser <Th...@lhasalimited.org>.
Hi everyone,

After further investigating the unexpected behaviour due to the getProperty()/setProperty() behaviour dissymmetry, I understood the underlying ground which is indeed compatible with what Jochen described.

 In the Script class, getProperty() implicitly checks if the variable exists in the binding using the exception try/catch. If it exists it gets the value from the binding and if it does not exists if delegates to the super class (GroovyObjectSupport) which in turn delegates to the meta class which eventually calls getX(). 

On the other hand setProperty() simply sets the variable in the binding regardless of its existence prior to the assignment. At this stage the meta class gets no chance to act when the variable does not exists which introduces a non symmetrical behaviour between getProperty() and setProperty().

In the Script class:

    public Object getProperty(String property) {
        try {
            return binding.getVariable(property);   // <== property exists -> value from binding
        } catch (MissingPropertyException e) {
            return super.getProperty(property);     // <== property does not exist -> value from the super class which delegates to the meta class

        }
    }

    public void setProperty(String property, Object newValue) {
        if ("binding".equals(property))
            setBinding((Binding) newValue);
        else if("metaClass".equals(property))
            setMetaClass((MetaClass)newValue);
        else
            binding.setVariable(property, newValue); // <== change/set value in binding regardless of the existence of the variable in the binding or not
    }

The solution is indeed close to what Jochen suggested. I just think that for the sake of symmetry all we need to do is to check whether the variable exists in the binding and behave accordingly. If it exists change its value in the binding, if it does not exist delegate to the  meta class (or call super.super). This would ensure a consistent (symmetrical) behaviour between getProperty() and setProperty(). 

@Override
public void setProperty(String property, Object newValue) 
{	
   if ("binding".equals(property)) setBinding((Binding) newValue);
   else if("metaClass".equals(property)) setMetaClass((MetaClass)newValue);
   else if(getBinding().hasVariable(property))  getBinding().setVariable(property, newValue);  // <== if variable exist => set binding value
   else getMetaClass().setProperty(this, property, newValue); // <== variable does not exist => delegate to meta class
}

Note that the origin of the dissymmetry is actually a consequence of the dissymmetry between the getVariable() and the setVariable() methods in the Binding class. getVariable() throws an exception when the variable does not exist where as setVariable() does not (it adds the variable to the linked map). The former exception is used by getProperty() in Script to trigger the delegation to the meta class but this can be used by setProperty() since no exception is thrown by setVariable() in Binding. 

Finally to be I would suggest to not use the exception of the getVariable() method (in Binding) to decide articulate the behaviour of the getProperty() method (in Script). To be fully symmetrical and consistent I would suggest to also fix the getProperty() method in the following manner:

@Override
public Object getProperty(String property)
{
   if(getBinding().hasVariable(property))  return getBinding().getVariable(property);
   else return  getMetaClass().getProperty(this, property);
}

Another positive consequence is that the binding variables become consistent since script level remain separate from the dynamically introduced binding.
If we wanted both variable/property spaces to be automatically merged and in sync at assignment time then we would have to remove the existence test in the setProperty() code (but I am not sure this is what we want; it is a higher level design decision)

@Override
public void setProperty(String property, Object newValue) 
{	
   if ("binding".equals(property)) setBinding((Binding) newValue);
   else if("metaClass".equals(property)) setMetaClass((MetaClass)newValue);
   else   
   {      
      getBinding().setVariable(property, newValue);  // <== update binding
      getMetaClass().setProperty(this, property, newValue); // <== notify meta class
   }
}

Unless I missed out some other subtle aspects, I think this should have been the original implementation of the Script setProperty(). 
Could this be a candidate for a fix?   (BTW, this solution works and provides the same behaviour with and without the CompileStatic option activated)

Thank you all for your help.

Thierry



-----Original Message-----
From: Thierry Hanser [mailto:Thierry.Hanser@lhasalimited.org] 
Sent: 05 April 2016 17:24
To: users@groovy.apache.org
Subject: RE: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)

Thank you for your explanations Jochen.

Your assumption is correct except that I think you meant to say that *The subsequent "println '2 = ' + x" will then get the value property instead of asking for the binding.* since the value ('one') is the one from the unchanged variable/property 'x'.

I am confused by the lack of symmetry in the handling of the binding/properties value.

"print x" in a script will call getX() (if available) whereas "x = 'two'" will call setProperty() which will add 'x' (if not present) to the binding but will not subsequently call setX(). As a result when you use the value of a property 'x' in a script you are guaranteed to call getX() but if you assign a value to 'x' you are not guaranteed that setX() is called !

This dissymmetry seems odd to me (and obviously leads to unexpected behaviour).

Note that without static compilation the same dissymmetry is observed, however for some reason the property 'x' is then properly updated but still without calling setX()

Really confusing to me !!!

I understand there are issues with the CompileStatic option. Do we know what level of prioritization are these issues in the bigger Groovy roadmap?

Thanks a lot,

Thierry

--

Groovy script:

"println '1 = ' + x; x = 'two'; println binding.variables;  println '2 = ' + x\n";

With static compilation:

init x: one
Getting x : one
1 = one
Setting property : x = two
[x:two]
Getting x : one
2 = one

Without static compilation:

init x: one
Getting x : one
1 = one
Setting property : x = two
[x:two]
2 = two


Java:

public abstract class JavaScriptDemo extends Script {
    public String x;

    public JavaScriptDemo()
    {
                x="one";
                System.out.println("init x: " + x);
    }

    public Object process(Closure code)
    {
        System.out.println("Processing with x : " + x);
        return code.call();
    }

    public void setX(String text)
    {
        System.out.println("Setting x : "  + x);
        x = text;
    }

    public String getX()
    {
        System.out.println("Getting x : "  + x);
        return x;
    }


        @Override
        public void setProperty(String property, Object value)
        {
        System.out.println("Setting property : "  + property + " = " + value);
        super.setProperty(property, value);
        }


        /**
     * Demo main
     * @param args
     * @throws Throwable
     */
    public static void main(String...args) throws Throwable
    {
                ////
                // Compilation configuration
                CompilerConfiguration configuration = new CompilerConfiguration();
                //configuration.addCompilationCustomizers(new ASTTransformationCustomizer(CompileStatic.class));
                configuration.setScriptBaseClass(JavaScriptDemo.class.getName());
                GroovyShell shell = new GroovyShell(JavaScriptDemo.class.getClassLoader(), configuration);

                // source code
                String scriptSource= "println '1 = ' + x; x = 'two'; println binding.variables;  println '2 = ' + x\n";

                // compile the source code and run the compiled script
                JavaScriptDemo compiledScript = (JavaScriptDemo)shell.parse(scriptSource);
        compiledScript.run();
    }
}

-----Original Message-----
From: Jochen Theodorou [mailto:blackdrag@gmx.org]
Sent: 09 March 2016 13:37
To: users@groovy.apache.org
Subject: Re: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)



On 08.03.2016 17:31, Thierry Hanser wrote:
[...]
> *In Groovy*
>
> println '1 = ' + x
> x = 'two'
> println '2 = ' + x
>
> *Output*:
>
> init x: one <- initial value assignement OK
>
> 1 = one <- successfully accessing 'x' from within the compiled script 
> OK
>
>                  the Groovy script has picked up the value of the Java 
> variable;
>
>                  the implicit getX() has been called
>
> 2 = one<- should be 'two' as per Groovy code (second line)
>
>                  but is unchanged ???

I think I know the problem...

When using a normal script your code above would have failed, because the binding does not contain x. But what exactly happens if the binding does not contain x? Groovy will ask the script class for a property of that name. Just to point it out very much: The property lookup is done only after binding is asked!

What happens in the set case then? The set case will always set a variable in the binding!

This explaines why for you "println '1 = ' + x " gives "one", but the important part is that then "x = 'two'" will leave that property untouched and goes directly to the binding. The subsequent "println '2 = ' + x" will then get the value from the binding instead of asking for the property.

The solution would be to overwrite setProperty to first try setting the property on the script class, basically: a try with this.getMetaClass().setProperty(this, property, newValue); and a super.setProperty in the exception case.

And it seems the static compiler has big issues with handling a script base class

bye Jochen
________________________________
Switchboard: +44 (0)113 394 6020
Technical Support: +44 (0)113 394 6030
________________________________
Lhasa Limited, a not-for-profit organisation, promotes scientific knowledge & understanding through the development of computer-aided reasoning & information systems in chemistry & the life sciences. Registered Charity Number 290866. Registered Office: Granary Wharf House, 2 Canal Wharf, Leeds, LS11 5PS. Company Registration Number 01765239. Registered in England and Wales.
This communication, including any associated attachments, is intended for the use of the addressee only and may contain confidential, privileged or copyright material. If you are not the intended recipient, you must not copy this message or attachment or disclose the contents to any other person. If you have received this transmission in error, please notify the sender immediately and delete the message and any attachment from your system. Except where specifically stated, any views expressed in this message are those of the individual sender and do not represent the views of Lhasa Limited. Lhasa Limited cannot accept liability for any statements made which are the sender's own. Lhasa Limited does not guarantee that electronic communications, including any attachments, are free of viruses. Virus scanning is recommended and is the responsibility of the recipient.

Re: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)

Posted by Jochen Theodorou <bl...@gmx.org>.

On 05.04.2016 18:23, Thierry Hanser wrote:
> Thank you for your explanations Jochen.
>
> Your assumption is correct except that I think you meant to say that *The subsequent "println '2 = ' + x" will then get the value property instead of asking for the binding.* since the value ('one') is the one from the unchanged variable/property 'x'.
>
> I am confused by the lack of symmetry in the handling of the binding/properties value.

That's because a script is not intended to be a class. In a script the 
binding is the important instance anything else is just a fallback. A 
simple example would be "this.class". If there is no "class" in the 
binding you get the result of getClass(), which is normally what you 
intend to get. On the other hand, if you did "foo=1", why would you 
expect setFoo() being called instead? You just set something in the 
binding, so why not get it from the binding?

> "print x" in a script will call getX() (if available) whereas "x = 'two'" will call setProperty() which will add 'x' (if not present) to the binding but will not subsequently call setX().

That is write, but don't forget that "print x" will go through 
getProperty, which is written to ask the binding. So there is a symmetry 
with getProperty and setProperty, it just does not extend to getX and 
setX, because the implementation of the setter breaks that.

So the question is really if we should not first look for a setter and 
only use the binding for setting, if the setter is not available. 
Well... traditionally scripts don't really have a lot of setters, that's 
why it normally it does not matter. And if you need that kind of logic, 
you can still use a class in the script... normally... of course base 
script changed that story a bit, but then maybe it should redefine the 
binding logic in this case as well. That's fully up to the custom base 
class actually.

> As a result when you use the value of a property 'x' in a script you are guaranteed to call getX() but if you assign a value to 'x' you are not guaranteed that setX() is called !

wrong "x=1; print x" will get you the value from the binding. so getX() 
is not guaranteed to be called. and setX() is actually never called 
through a "x=1".. unless you did mean with static compilation

> This dissymmetry seems odd to me (and obviously leads to unexpected behaviour).
>
> Note that without static compilation the same dissymmetry is observed, however for some reason the property 'x' is then properly updated but still without calling setX()

I would call that a bug in the static compilation. But I wonder how the 
static compiler is actually supposed to behave. It cannot know the 
values of the binding, thus it would need to compile against the setters 
and getters. It would then be wrong to ask the binding for anything, 
unless you do it directly. Which means all scripts using the binding 
normally won't compile statically. But hey, I think that is ok.

[...]
> I understand there are issues with the CompileStatic option. Do we know what level of prioritization are these issues in the bigger Groovy roadmap?

we normally use only blocker, major and minor. A blocker is a bug you 
cannot work around easily. Since in your case you can call the setter 
instead, it would be no blocker. minor are bugs, that show more little 
inconsistencies. And major priority is the vast majority of the bugs. 
Sometimes we also use blocker to ensure it is in the next release... but 
we have gotten away from this.

bye Jochen

RE: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)

Posted by Thierry Hanser <Th...@lhasalimited.org>.
Thank you for your explanations Jochen.

Your assumption is correct except that I think you meant to say that *The subsequent "println '2 = ' + x" will then get the value property instead of asking for the binding.* since the value ('one') is the one from the unchanged variable/property 'x'.

I am confused by the lack of symmetry in the handling of the binding/properties value.

"print x" in a script will call getX() (if available) whereas "x = 'two'" will call setProperty() which will add 'x' (if not present) to the binding but will not subsequently call setX(). As a result when you use the value of a property 'x' in a script you are guaranteed to call getX() but if you assign a value to 'x' you are not guaranteed that setX() is called !

This dissymmetry seems odd to me (and obviously leads to unexpected behaviour).

Note that without static compilation the same dissymmetry is observed, however for some reason the property 'x' is then properly updated but still without calling setX()

Really confusing to me !!!

I understand there are issues with the CompileStatic option. Do we know what level of prioritization are these issues in the bigger Groovy roadmap?

Thanks a lot,

Thierry

--

Groovy script:

"println '1 = ' + x; x = 'two'; println binding.variables;  println '2 = ' + x\n";

With static compilation:

init x: one
Getting x : one
1 = one
Setting property : x = two
[x:two]
Getting x : one
2 = one

Without static compilation:

init x: one
Getting x : one
1 = one
Setting property : x = two
[x:two]
2 = two


Java:

public abstract class JavaScriptDemo extends Script
{
    public String x;

    public JavaScriptDemo()
    {
                x="one";
                System.out.println("init x: " + x);
    }

    public Object process(Closure code)
    {
        System.out.println("Processing with x : " + x);
        return code.call();
    }

    public void setX(String text)
    {
        System.out.println("Setting x : "  + x);
        x = text;
    }

    public String getX()
    {
        System.out.println("Getting x : "  + x);
        return x;
    }


        @Override
        public void setProperty(String property, Object value)
        {
        System.out.println("Setting property : "  + property + " = " + value);
        super.setProperty(property, value);
        }


        /**
     * Demo main
     * @param args
     * @throws Throwable
     */
    public static void main(String...args) throws Throwable
    {
                ////
                // Compilation configuration
                CompilerConfiguration configuration = new CompilerConfiguration();
                //configuration.addCompilationCustomizers(new ASTTransformationCustomizer(CompileStatic.class));
                configuration.setScriptBaseClass(JavaScriptDemo.class.getName());
                GroovyShell shell = new GroovyShell(JavaScriptDemo.class.getClassLoader(), configuration);

                // source code
                String scriptSource= "println '1 = ' + x; x = 'two'; println binding.variables;  println '2 = ' + x\n";

                // compile the source code and run the compiled script
                JavaScriptDemo compiledScript = (JavaScriptDemo)shell.parse(scriptSource);
        compiledScript.run();
    }
}

-----Original Message-----
From: Jochen Theodorou [mailto:blackdrag@gmx.org]
Sent: 09 March 2016 13:37
To: users@groovy.apache.org
Subject: Re: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)



On 08.03.2016 17:31, Thierry Hanser wrote:
[...]
> *In Groovy*
>
> println '1 = ' + x
> x = 'two'
> println '2 = ' + x
>
> *Output*:
>
> init x: one <- initial value assignement OK
>
> 1 = one <- successfully accessing 'x' from within the compiled script
> OK
>
>                  the Groovy script has picked up the value of the Java
> variable;
>
>                  the implicit getX() has been called
>
> 2 = one<- should be 'two' as per Groovy code (second line)
>
>                  but is unchanged ???

I think I know the problem...

When using a normal script your code above would have failed, because the binding does not contain x. But what exactly happens if the binding does not contain x? Groovy will ask the script class for a property of that name. Just to point it out very much: The property lookup is done only after binding is asked!

What happens in the set case then? The set case will always set a variable in the binding!

This explaines why for you "println '1 = ' + x " gives "one", but the important part is that then "x = 'two'" will leave that property untouched and goes directly to the binding. The subsequent "println '2 = ' + x" will then get the value from the binding instead of asking for the property.

The solution would be to overwrite setProperty to first try setting the property on the script class, basically: a try with this.getMetaClass().setProperty(this, property, newValue); and a super.setProperty in the exception case.

And it seems the static compiler has big issues with handling a script base class

bye Jochen
________________________________
Switchboard: +44 (0)113 394 6020
Technical Support: +44 (0)113 394 6030
________________________________
Lhasa Limited, a not-for-profit organisation, promotes scientific knowledge & understanding through the development of computer-aided reasoning & information systems in chemistry & the life sciences. Registered Charity Number 290866. Registered Office: Granary Wharf House, 2 Canal Wharf, Leeds, LS11 5PS. Company Registration Number 01765239. Registered in England and Wales.
This communication, including any associated attachments, is intended for the use of the addressee only and may contain confidential, privileged or copyright material. If you are not the intended recipient, you must not copy this message or attachment or disclose the contents to any other person. If you have received this transmission in error, please notify the sender immediately and delete the message and any attachment from your system. Except where specifically stated, any views expressed in this message are those of the individual sender and do not represent the views of Lhasa Limited. Lhasa Limited cannot accept liability for any statements made which are the sender's own. Lhasa Limited does not guarantee that electronic communications, including any attachments, are free of viruses. Virus scanning is recommended and is the responsibility of the recipient.

Re: Failing to change the value of a Java variable from wihtin a Groovy script (potential issue?)

Posted by Jochen Theodorou <bl...@gmx.org>.

On 08.03.2016 17:31, Thierry Hanser wrote:
[...]
> *In Groovy*
>
> println '1 = ' + x
> x = 'two'
> println '2 = ' + x
>
> *Output*:
>
> init x: one <- initial value assignement OK
>
> 1 = one <- successfully accessing ‘x’ from within the compiled script OK
>
>                  the Groovy script has picked up the value of the Java
> variable;
>
>                  the implicit getX() has been called
>
> 2 = one<- should be ‘two’ as per Groovy code (second line)
>
>                  but is unchanged ???

I think I know the problem...

When using a normal script your code above would have failed, because 
the binding does not contain x. But what exactly happens if the binding 
does not contain x? Groovy will ask the script class for a property of 
that name. Just to point it out very much: The property lookup is done 
only after binding is asked!

What happens in the set case then? The set case will always set a 
variable in the binding!

This explaines why for you "println '1 = ' + x " gives "one", but the 
important part is that then "x = 'two'" will leave that property 
untouched and goes directly to the binding. The subsequent "println '2 = 
' + x" will then get the value from the binding instead of asking for 
the property.

The solution would be to overwrite setProperty to first try setting the 
property on the script class, basically: a try with 
this.getMetaClass().setProperty(this, property, newValue); and a 
super.setProperty in the exception case.

And it seems the static compiler has big issues with handling a script 
base class

bye Jochen