Blog

  •  

    Metaobject Protocol

    Metaprogramming means writing programs that manipulate programs. In Groovy, we can use MOP to invoke methods dynamically and synthesize classes and methods on the fly. This can give us the feeling that our object favorably changed its class. Groovy allows metaprogramming for POJOs and POGOs.

     

    Intercepting Methods Using GroovyInterceptable

    If Groovy object implements GroovyInterceptable, then its invokeMethod() is called when any of its methods are called—both existing methods and nonexistent methods. That is, GroovyInterceptable’s invokeMethod() hijacks all calls to the object.

     class Phone implements GroovyInterceptable {
     
       def redial() { System.out.println "redial called..." }
       def keypad() { System.out.println "keypad called..." }
       def makeCall() { System.out.println "makeCall called..." }
    
       def invokeMethod(String name, args) {
      
          System.out.print("Call to $name intercepted... ")
    
          if (name != 'keypad') {
               System.out.print("running filter... ")
               Phone.metaClass.getMetaMethod('keypad').invoke(this, null)
          }
    
          def validMethod = Phone.metaClass.getMetaMethod(name, args)
          if (validMethod != null) {
               validMethod.invoke(this, args)
          } else {
               Phone.metaClass.invokeMethod(this, name, args)
          }
        }
      }
    
     phone = new Phone()
     phone.redial()
     phone.makeCall()
     phone.keypad()
     try {
       phone.hang()
      } catch(Exception ex) {
         println ex
     }
    

    The output shows the proper interception of methods:

    Call to redial intercepted... running filter...  keypad called...

    redial called..

    Call to makeCall intercepted... running filter...   keypad called...

    makeCall called...

    Call to keypad intercepted... keypad called...

    Call to hang intercepted... running filter... keypad called...

    groovy.lang.MissingMethodException:  No signature of method: Car.speed()  is applicable for argument types: () values: [ ]

     

    Intercepting Methods Using MetaClass

    If we don’t have the privileges to modify the class source code ,in this case we may decide at runtime to start intercepting calls based on some condition or application state. In these cases, we can intercept methods by implementing the invokeMethod() method on the MetaClass

       class Phone implements GroovyInterceptable {
     
           def redial() { System.out.println "redial called..." }
           def keypad() { System.out.println "keypad called..." }
           def makeCall() { System.out.println "makeCall called..." }
       }
    
       Phone.metaClass.invokeMethod = { String name, args ->
    
       if (name != 'redial') {
         System.out.print("Call to $name intercepted... ")
         System.out.print("running filter... ")
         Phone.metaClass.getMetaMethod('redial').invoke(delegate, null)
       }
    
      def validMethod = Phone.metaClass.getMetaMethod(name, args)
      if (validMethod != null) {
         validMethod.invoke(delegate, args)
      } else {
         Phone.metaClass.invokeMissingMethod(delegate, name, args)
      }
     }
    
      phone = new Phone()
      phone.redial()
      phone.makeCall()
      phone.keypad()
    
     try {
       phone.hang()
     } catch(Exception ex) {
        println ex
     }
    
    

    Let’s observe the method interceptions in the output:

    Call to redial intercepted... running filter... keypad called...

    redial called...

    Call to makeCall intercepted... running filter... keypad called...

    makeCall called...

    Call to check intercepted... keypad called...

    Call to speed intercepted... running filter... keypad called...

    groovy.lang.MissingMethodException: No signature of method: Car.speed() is applicable for argument types: () values: [ ]

     

    There are two differences between these two versions of invokeMethod()  we implemented on Phone, The first difference is the use of delegate instead of this. The delegate within the intercepting closure refers to the target object whose methods are being intercepted. The second difference is where we call invokeMissingMethod() on the MetaClass instead of calling invokeMethod. We’re already in invokeMethod(), so we should not call it recursively here.

     

    Hope it helps!

     

Tags: grails

View All PostsLeave a Comment
comments powered by Disqus

Mobile Applications

Video Content

Bigdata & NoSQL

SaaS Applications

Miscellaneous

Archives


Alexa Certified Site Stats for www.oodlestechnologies.com