Friday 11 May 2012

Watch out for Groovy closures called from a subclass calling method in the superclass!

Okay I'll admit the title of the post is a little long, but it is really hard to describe it. I ran into this problem today and am posting about it, just in case some other poor chap comes across it.

It might be best to see the code first:

class SubClass extends SuperClass { 
   public static void main(String[] args) { 
     new SubClass().start() 
   } 
   public void start() { 
     closureFromSubClass() 
   } 
   private closureFromSubClass = { 
     closure("hello") 
   } 
 } 
 class SuperClass { 
   def closure = { str -> 
     method(str) 
   } 
   private void method(str) { 
     println (str) 
   } 
 } 


So what do you think is the output when I run this script? You would think that it'll print `hello`, right?

Well, I thought that as well, since there are no compile errors that show up in Eclipse...but instead, this is what I got:


Caught: groovy.lang.MissingMethodException: No signature of method: SubClass.method() is applicable for argument types: (java.lang.String) values: [hello] 
 Possible solutions: getAt(java.lang.String), with(groovy.lang.Closure) 
 groovy.lang.MissingMethodException: No signature of method: SubClass.method() is applicable for argument types: (java.lang.String) values: [hello] 
 Possible solutions: getAt(java.lang.String), with(groovy.lang.Closure) 
      at SuperClass$_closure1.doCall(Test.groovy:20) 
      at SuperClass.invokeMethod(Test.groovy) 
      at SubClass$_closure1.doCall(Test.groovy:13) 
      at SubClass$_closure1.doCall(Test.groovy) 
      at SubClass.start(Test.groovy:9) 
      at SubClass$start.call(Unknown Source) 
      at SubClass.main(Test.groovy:5) 


Well, it turns out that the private identifier from the method method() was the culprit. Once I removed it private access then it works. So next time when you see Groovy complaining and you are calling closures within closures from a different class, check to make sure your access modifiers are right!

No comments:

Post a Comment