Friday, 25 March 2016

Groovy - A Dynamic Language (Part 2)

Now in this episode we will see a little interesting approach demonstrating the dynamic behaviour of Groovy.

The Objective will be to implement Delegation Design Pattern using Composition rather than inheritance which is always considered to be better approach.

Here we have defined Bus, Car, Truck and a Vehicle class.
The Vehicle class has a call to the method vehicleDelegator() defined within an instance block and having a list of delegator classes as parameter,and this method only does all the Magic.

The method call of vehicleDelegator is there, but where is the definition, we have defined it as within the metaClass of Object class, so it will be present in all classes as all class extends Object.

So when we create an instance of Vehicle this method vehicleDelegator() gets called and at the same time it registers a methodMissing() for Vehicle class.

So whenever we call any method of Vehicle class, control goes into methodMissing() which searches for the particular method in each of the classes passed as parameter to the vehicleDelegator() method. If it finds them invokes them, and registers them in the metaClass of the Vehicle class so that if the same method invoked again from Vehicle, methodMissing() is not invoked and if the method as called from Vehicle is not present in any of the delegator classes then Exception is thrown.

This is a beautiful concept of Method Caching, and reveals the Groovy's true dynamism.


class Vehicle {

    {vehicleDelegator Car, Bus, Truck}

    def startUp()
    {
        println "Vehicle StartUp....."
    }
}

class Bus {

    def busOwner(name)
    {
        println "Bus owner is $name"
    }

}

class Car {

    def carOwner(name)
    {
        println "Car owner is $name"
    }

}


class Truck {

    def truckOwner(name)
    {
        println "Truck owner is $name"
    }
}


class MOPSynthesis {

    static main(args)
    {

        Object.metaClass.vehicleDelegator = { Class... delegates ->

            def delegatesObInstances = delegates.collect {
                it.newInstance()
            }

            delegate.metaClass.methodMissing = {     name, methArgs ->
                println "Intercepting Calls to $name with Args $args....."
                def delegator = delegates.find {
                    it.metaClass.respondsTo(it, name, methArgs)
                }
                if (delegator) {
                    delegate.metaClass."${name}" = { Object[] varArgs ->
                        delegator.newInstance().invokeMethod(name, varArgs);
                    }
                    delegator.newInstance().invokeMethod(name, methArgs);
                }
                 else
                    {
                        throw new MissingMethodException(name, delegate.getClass(), args)
                    }

            }
        }

        def vehicle = new Vehicle()
        vehicle.carOwner('Mic')
        vehicle.carOwner('Puchu')
        vehicle.carOwner('Stag!!')

    }
}

View Subhankar Paul's profile on LinkedIn

Groovy - A Dynamic Language (Part 1)

Groovy is always being referred as a Dynamic Language, But the first question arises is what makes Groovy so.
While I was exploring the Groovier way of this dynamic phenomenon, I came across something know as MetaObject Protocol.
Programmatically it is an interface whose methods are being implemented by the reference implementation of the MetaClass interface.

Now what role does MetaClass interface plays in this Dynamic Behaviour if Groovy then? In the same way Programatically MetaClass interface extends MetaObjectProtocol. This MetaClass defines the behaviour of any POGO or POJO.

So MetaObjectProtocol can be defined as a set of rules defining how Groovy Runtime controls or processes requests for a method call and how to control the intermediate layer.

The request processing approach/process by the Groovy Runtime during a method call can well be obtained from the below diagram. (Referenced from Venkat's Programming Groovy 2 book)

The dyanmic nature of Groovy language can be implemented in the following ways:

1)Runtime
1.1) Categories
1.2) Expando / MetaClass / ExpandoMetaClass
2)Compile Time
2.1) AST Transformations
2.2) Extension Module
We will be mostly implementing dynamic behaviour with Expando / MetaClass / ExpandoMetaClass here.

So from the above diagram we can tell that invokeMethod(), missingMethod() etc. can be really helpful in implementing or exploring the dynamic behaviour of Groovy.

Lets traverse through an example:


class Person implements GroovyInterceptable {

    def name
    def agent

    def invokeMethod(String name,  args)
    {
       System.out.println "1.Intercepting for Method $name with Args $args"
        def method = metaClass.getMetaMethod(name,args)
        if(method) {
            System.out.println "1.Original Method Present"
            method.invoke(this, args)
        }
        else {
            System.out.println "1.Forwarding to Metaclass"
            metaClass.invokeMethod(this, name, args)
        }
    }

    def methodMissing(String name,  args)
    {
        System.out.println "1. Missing Method $name with Args $args"


        Person.metaClass."$name" = { Object[] methArgs ->
            System.out.println "Default implementation provided!!!"
        }

         //"$name"(args)
    }

    def getName(name)
    {
         name
    }


}

class MorphedPerson {

    static main(args)
    {
       /* Person.metaClass.getAge = {

            "Naming in Progress for $delegate"
        }*/

      /*  Person.metaClass.invokeMethod = {String name, arg ->
            println "2. Intercepting for Method $name with Arguments $args for delegate $delegate"
            Person.metaClass.invokeMissingMethod(delegate,name,args)
        }*/

        /**
         * When two methods are defined one in
         * Class and another in Metaclass (Dynamically),
         * Metaclass Methods always gains precedence
         */

       /* Person.metaClass.methodMissing = {name, methArgs ->
            println "2. Metaclass Missing Method $name with Args $methArgs"

        }*/

        /**
         * Method Synthesis when done from inside Person Class
         * it is not working but when done from outside it is
         * working
         */

        Person.metaClass.methodMissing = {name,  methArgs ->

            println "2. Missing Method $name with Args $methArgs"


            Person.metaClass."$name" = { Object[] vArgs ->
                println "Default implementation provided!!!"
            }

            "$name"(args)
        }

        def person = new Person()
        person.getAge('MIC')
        person.getAge('MIC2')

        println person.getName('MIC')
        println person.getName('MIC2')
    }
}



Here we have defined a domain class Person and tried to add dynamic behaviour to it with MorphedPerson.
When a method is not present for a particular domain we are creating the method implementation on the fly and adding the same to the Metaclass so that in the next invocation of the same method that implementation which was added earlier gets invoked, not the missingMethod().

So in a way we can say that we are caching the method implemetation here.

In the above example we can also see the roles that invokeMethod() or missingMethod() can play in implementing the Dynamic nature of Groovy.

If any body asks me where are its Practical Implemenations, then My Answer would be be that various Builder that Groovy provides, Like Markup Builder and obviously Groovy DSLs.

I am dividing this Post in two parts.

In the

next part

we will see a more interesting Groovy Dynamic Behaviour implementation

View Subhankar Paul's profile on LinkedIn