Groovy is one of the famous JVM based language which come up with a lot of groovier functionality in it. Groovy provides a great feature : Metaprogramming at run time and this is what i am calling Dynamicity of Groovy.
Do not confuse with Dynamically Typed languages and Dynamic languages. Dynamically Typed languages have feature of verifying the type safety of a program at runtime[Ref. stackoverflow] whereas the Dynamic languages allow extension of the program at run time by adding new code, by extending objects and definitions, or by modifying the type system[Ref. WIKI].
So runtime meta programming in groovy is to provide or modify the definition of methods and properties at run time/dynamically. By this we can handle the method call which is even not exist in class. But for this, firstly we have to understand the method call in groovy which is a bit different from java.


Method call handling in Groovy

Diagram explanation : A method call is executed in following manner.

  1. Firstly check if method exist in class or meta class
  2. If a property of closure type with same name as method called.
  3. If missingMethod() exist then call that method.
  4. If invokeMethod() exist then call that method.
  5. Else MissingMethodException is thrown.


Please check the code for above steps on GitHub.

Handle method calls when method not exist in class

  • This is not actually adding the code at run time. Rather then that our code will handle the calls for those properties/methods which do not exist in class at run time. But question is how can our code handle the method calls or property access?
    This is where groovy is different from Java, in Groovy a method call never invokes a class method directly. Groovy has its own method dispatch mechanism which is expalined above by diagram. A method invocation on an object is always goes first to the GroovyObject.invokeMethod() or methodMissing() of the object. Every groovy class implements the GroovyObject implicitly.
    So if a method not exist then it will intercepted at missingMethod/invokeMethod. We can write our own code to handle the request. For eample Expando.class : If a property is not exist in class then it will still store it in its instance. Code for Expando class.

        class FakeExpando {
            def map = [:]
    
            void setProperty(String property, def val) { map[property] = val }
    
            def getProperty(String property) { map[property] }
        
            // It will search the closure in map and call it
            def invokeMethod(String name, args) {
              def clo = map[name]
              if (clo instanceof Closure) {
                clo(args)
              } else {
                throw new MissingMethodException(name, FakeExpando.class, args)
              }
           }
        }
        
        //Test cases to test the above code.
        class FakeExpandoSpec extends spock.lang.Specification {
        	def "canary test"() {
            	expect:
           	 	true == true
        	}
        
          	def "execute closure to object"() {
              given:
              def fe = new FakeExpando()
              when:
              fe.firstName = 'Aman'
              fe.behaviour = {('Aman' == delegate.firstName)?'Cool':'maniac'}
              fe.behaviour.delegate = fe
              then:
              'Aman' == fe.firstName
              'Cool' == fe.behaviour()
        	}
    	}
       

In the similar way, dynamic finder of grails domain classes works. Some other example are dsl formation, html builder and xml builders.