Yu Shen
Yu Shen

Reputation: 2910

Groovy: How can I from a method implementation access variable/object defined outside of the class?

The following code segment demonstrate my problem:

import java.util.timer.*  

s = "Hello"
println s
class TimerTaskExample extends TimerTask {  
        public void run() {  
            //println new Date() 
            println s 
        }  
}  

int delay = 5000   // delay for 5 sec.  
int period = 10000  // repeat every sec.  
Timer timer = new Timer()  
timer.scheduleAtFixedRate(new TimerTaskExample(), delay, period)  

In my implementation of TimerTaskExample, I'd like to access s which is created in the "global" script scope. But I got the following trace:

Hello
Exception in thread "Timer-2" 
groovy.lang.MissingPropertyException: No such property: s for class: TimerTaskExample
at         org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:50)
at     org.codehaus.groovy.runtime.callsite.GetEffectivePogoPropertySite.getProperty(GetEffectivePogoPropertySite.java:86)
at     org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:231)
at TimerTaskExample.run(ConsoleScript2:8)

I tried google around, but couldn't find a solution.

Thanks a lot!

Yu SHen

Upvotes: 1

Views: 2210

Answers (3)

Mauro Zallocco
Mauro Zallocco

Reputation: 306

Although s (without the def) is defined in the binding, it is not accessible in a class you define in the script. To get access to s in your TimerTaskExample class, you can proceed as follows:

class TimerTaskExample extends TimerTask {  
    def binding
    public void run() {  
        println binding.s 
    }  
}  

new TimerTaskExample(binding:binding)

Upvotes: 2

Arturo Herrero
Arturo Herrero

Reputation: 13112

It looks like you're using a Groovy script.

The only things a method has access to are:

  • Attributes defined by the base class
  • The dynamic properties defined by the MetaClass
  • The binding

Scripts allow the use of undeclared variables (without def), in which case these variables are assumed to come from the script’s binding and are added to the binding if not yet there.

name = 'Dave'
def foo() {
    println name
}

foo()

For each script, Groovy generates a class that extends groovy.lang.Script, which contains a main method so that Java can execute it. In my example, I have only one class:

public class script1324839515179 extends groovy.lang.Script {
    def name = 'Dave'
    def foo() {
        println name
    }
    ...
}

What's happening in your example? You have two classes and the binding variables are in the Script class. TimerTaskExample doesn't know anything about s:

public class script1324839757462 extends groovy.lang.Script {
    def s = "Hello"
    ...
}

public class TimerTaskExample implements groovy.lang.GroovyObject extends java.util.TimerTask {
    void run() {
        println s
    }
    ...
}

Upvotes: 2

Dave Newton
Dave Newton

Reputation: 160170

Groovy doesn't have a "global" scope per se; IMO it's cleanest to keep such "globals" in a class, defined as static finals, as in Java:

public class Constants {
  static final String S = "Hello"
}

println Constants.S
class TimerTaskExample extends TimerTask {  
  public void run() {  
    println Constants.S  
  }  
}  

Upvotes: 1

Related Questions